issue #0002902: PyObjectBase notification chain can lead to unexpected changes to document
This commit is contained in:
@@ -181,6 +181,17 @@ int PyObjectBase::__setattr(PyObject *obj, char *attr, PyObject *value)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If an attribute references this as parent then reset it
|
||||
// before setting the new attribute
|
||||
PyObject* cur = static_cast<PyObjectBase*>(obj)->_getattr(attr);
|
||||
if (cur) {
|
||||
if (PyObject_TypeCheck(cur, &(PyObjectBase::Type))) {
|
||||
PyObjectBase* base = static_cast<PyObjectBase*>(cur);
|
||||
base->resetAttribute();
|
||||
}
|
||||
Py_DECREF(cur);
|
||||
}
|
||||
|
||||
int ret = static_cast<PyObjectBase*>(obj)->_setattr(attr, value);
|
||||
#if 1
|
||||
if (ret == 0) {
|
||||
@@ -265,6 +276,18 @@ PyObject *PyObjectBase::_repr(void)
|
||||
return Py_BuildValue("s", a.str().c_str());
|
||||
}
|
||||
|
||||
void PyObjectBase::resetAttribute()
|
||||
{
|
||||
if (this->attribute) {
|
||||
free(this->attribute);
|
||||
this->attribute = 0;
|
||||
}
|
||||
if (this->parent) {
|
||||
Py_DECREF(this->parent);
|
||||
this->parent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PyObjectBase::setAttributeOf(const char* attr, const PyObjectBase* par)
|
||||
{
|
||||
if (this->parent != par) {
|
||||
|
||||
@@ -196,6 +196,7 @@ class BaseExport PyObjectBase : public PyObject
|
||||
protected:
|
||||
/// destructor
|
||||
virtual ~PyObjectBase();
|
||||
void resetAttribute();
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
|
||||
@@ -342,6 +342,18 @@ class DocumentBasicCases(unittest.TestCase):
|
||||
self.Doc.removeObject(L7.Name)
|
||||
self.Doc.removeObject(L8.Name)
|
||||
|
||||
def testPropertyLink(self):
|
||||
o1 = self.Doc.addObject("App::FeatureTest","test1")
|
||||
o2 = self.Doc.addObject("App::FeatureTest","test2")
|
||||
o3 = self.Doc.addObject("App::FeatureTest","test3")
|
||||
|
||||
o1.Link=o2
|
||||
self.assertEqual(o1.Link, o2)
|
||||
o1.Link=o3
|
||||
self.assertEqual(o1.Link, o3)
|
||||
o2.Placement = FreeCAD.Placement()
|
||||
self.assertEqual(o1.Link, o3)
|
||||
|
||||
def tearDown(self):
|
||||
#closing doc
|
||||
FreeCAD.closeDocument("CreateTest")
|
||||
|
||||
Reference in New Issue
Block a user