diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp
index cadeba482..daac1f756 100644
--- a/src/App/DocumentObject.cpp
+++ b/src/App/DocumentObject.cpp
@@ -71,23 +71,10 @@ DocumentObject::~DocumentObject(void)
}
}
-namespace App {
-class ObjectExecution
-{
-public:
- ObjectExecution(DocumentObject* o) : obj(o)
- { obj->StatusBits.set(3); }
- ~ObjectExecution()
- { obj->StatusBits.reset(3); }
-private:
- DocumentObject* obj;
-};
-}
-
App::DocumentObjectExecReturn *DocumentObject::recompute(void)
{
// set/unset the execution bit
- ObjectExecution exe(this);
+ ObjectStatusLocker exe(App::Recompute, this);
return this->execute();
}
diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h
index 3a9007c4d..f74785431 100644
--- a/src/App/DocumentObject.h
+++ b/src/App/DocumentObject.h
@@ -49,6 +49,7 @@ enum ObjectStatus {
Recompute = 3,
Restore = 4,
Delete = 5,
+ PythonCall = 6,
Expand = 16
};
@@ -260,6 +261,18 @@ protected: // attributes
const std::string *pcNameInDocument;
};
+class AppExport ObjectStatusLocker
+{
+public:
+ ObjectStatusLocker(ObjectStatus s, DocumentObject* o) : status(s), obj(o)
+ { obj->setStatus(status, true); }
+ ~ObjectStatusLocker()
+ { obj->setStatus(status, false); }
+private:
+ ObjectStatus status;
+ DocumentObject* obj;
+};
+
} //namespace App
#endif // APP_DOCUMENTOBJECT_H
diff --git a/src/App/DocumentObjectPy.xml b/src/App/DocumentObjectPy.xml
index a3e30c9b5..7e774ff84 100644
--- a/src/App/DocumentObjectPy.xml
+++ b/src/App/DocumentObjectPy.xml
@@ -45,11 +45,16 @@
Mark the object as unchanged
-
-
- Register an expression for a property
-
-
+
+
+ Register an expression for a property
+
+
+
+
+ Recomputes this object
+
+
A list of all objects this object links to.
diff --git a/src/App/DocumentObjectPyImp.cpp b/src/App/DocumentObjectPyImp.cpp
index 677f8b3e2..9951be09c 100644
--- a/src/App/DocumentObjectPyImp.cpp
+++ b/src/App/DocumentObjectPyImp.cpp
@@ -256,6 +256,19 @@ PyObject* DocumentObjectPy::setExpression(PyObject * args)
Py_Return;
}
+PyObject* DocumentObjectPy::recompute(PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ try {
+ bool ok = getDocumentObjectPtr()->recomputeFeature();
+ return Py_BuildValue("O", (ok ? Py_True : Py_False));
+ }
+ catch (const Base::Exception& e) {
+ throw Py::RuntimeError(e.what());
+ }
+}
PyObject *DocumentObjectPy::getCustomAttributes(const char* attr) const
{
diff --git a/src/App/FeaturePython.cpp b/src/App/FeaturePython.cpp
index 77094557a..eff825605 100644
--- a/src/App/FeaturePython.cpp
+++ b/src/App/FeaturePython.cpp
@@ -51,6 +51,10 @@ FeaturePythonImp::~FeaturePythonImp()
*/
bool FeaturePythonImp::execute()
{
+ // avoid recursive calls of execute()
+ if (object->testStatus(App::PythonCall))
+ return false;
+
// Run the execute method of the proxy object.
Base::PyGILStateLocker lock;
try {
@@ -59,6 +63,7 @@ bool FeaturePythonImp::execute()
Py::Object feature = static_cast(proxy)->getValue();
if (feature.hasAttr(std::string("execute"))) {
if (feature.hasAttr("__object__")) {
+ ObjectStatusLocker exe(App::PythonCall, object);
Py::Callable method(feature.getAttr(std::string("execute")));
Py::Tuple args;
Py::Object res = method.apply(args);
@@ -67,6 +72,7 @@ bool FeaturePythonImp::execute()
return true;
}
else {
+ ObjectStatusLocker exe(App::PythonCall, object);
Py::Callable method(feature.getAttr(std::string("execute")));
Py::Tuple args(1);
args.setItem(0, Py::Object(object->getPyObject(), true));