mirror of https://github.com/swig/swig
Fixing setting this in Python when using __slots__
Don't attempt to use the class's __dict__ for setting 'this' when a user has extended a class with: __slots__ = ['this']. Was segfaulting. Now we fall back to a simple PyObject_SetAttr if the usual approach to setting 'this' in __dict__ does not work. Closes #1673 Closes #1674
This commit is contained in:
parent
a9731251a4
commit
a01e8474f6
|
@ -7,6 +7,9 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
|||
Version 4.0.2 (in progress)
|
||||
===========================
|
||||
|
||||
2020-02-06: wsfulton
|
||||
[Python] #1673 #1674 Fix setting 'this' when extending a proxy class with __slots__.
|
||||
|
||||
2020-01-31: vadz
|
||||
[Ruby] Add std::auto_ptr<> typemaps.
|
||||
|
||||
|
|
|
@ -21,3 +21,16 @@ if grabstaticpath() != None:
|
|||
Test.static_func()
|
||||
if grabstaticpath() != os.path.basename(mypath):
|
||||
raise RuntimeError("grabstaticpath failed")
|
||||
|
||||
# slots test
|
||||
fs = ForSlots()
|
||||
if fs.ValidVariable != 99:
|
||||
raise RuntimeError("ValidVariable failed")
|
||||
fs.ValidVariable = 11
|
||||
if fs.ValidVariable != 11:
|
||||
raise RuntimeError("ValidVariable failed")
|
||||
try:
|
||||
fs.Invalid = 22
|
||||
raise RuntimeError("It should not be possible to set a random variable name")
|
||||
except AttributeError:
|
||||
pass
|
||||
|
|
|
@ -42,13 +42,31 @@ import os.path
|
|||
%}
|
||||
|
||||
%inline %{
|
||||
|
||||
class Test {
|
||||
public:
|
||||
static void static_func() {};
|
||||
void funk() {};
|
||||
};
|
||||
%}
|
||||
|
||||
// Github issue #1674
|
||||
%extend ForSlots {
|
||||
%pythoncode %{
|
||||
__slots__ = ["this"]
|
||||
%}
|
||||
}
|
||||
// While __slots__ does not contain 'ValidVariable' in the list, it is still possible
|
||||
// to set 'ValidVariable'. A little odd, but the whole attribute setting is bypassed
|
||||
// for setting C/C++ member variables.
|
||||
// Not sure how to test the equivalent for -builtin.
|
||||
%inline %{
|
||||
struct ForSlots {
|
||||
int ValidVariable;
|
||||
ForSlots() : ValidVariable(99) {}
|
||||
};
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
#ifdef SWIGPYTHON_BUILTIN
|
||||
bool is_python_builtin() { return true; }
|
||||
#else
|
||||
|
|
|
@ -1248,22 +1248,19 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
|
|||
SWIGRUNTIME void
|
||||
SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this)
|
||||
{
|
||||
PyObject *dict;
|
||||
#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS)
|
||||
PyObject **dictptr = _PyObject_GetDictPtr(inst);
|
||||
if (dictptr != NULL) {
|
||||
dict = *dictptr;
|
||||
if (dict == NULL) {
|
||||
dict = PyDict_New();
|
||||
*dictptr = dict;
|
||||
}
|
||||
PyDict_SetItem(dict, SWIG_This(), swig_this);
|
||||
return;
|
||||
}
|
||||
PyObject **dictptr = _PyObject_GetDictPtr(inst);
|
||||
if (dictptr != NULL) {
|
||||
PyObject *dict = *dictptr;
|
||||
if (dict == NULL) {
|
||||
dict = PyDict_New();
|
||||
*dictptr = dict;
|
||||
}
|
||||
PyDict_SetItem(dict, SWIG_This(), swig_this);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
dict = PyObject_GetAttrString(inst, "__dict__");
|
||||
PyDict_SetItem(dict, SWIG_This(), swig_this);
|
||||
Py_DECREF(dict);
|
||||
PyObject_SetAttr(inst, SWIG_This(), swig_this);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue