From 3e2400aec1037a709a7ef88e195113912bc6ac24 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 9 Nov 2016 10:35:49 +0100 Subject: [PATCH] dynamic properties: + move addProperty, removeProperty and supportedProperties from FeaturePythonPyT to DocumentObjectPy --- src/App/DocumentObjectPy.xml | 24 +++- src/App/DocumentObjectPyImp.cpp | 71 +++++++++++- src/App/FeaturePythonPyImp.h | 12 -- src/App/FeaturePythonPyImp.inl | 194 +------------------------------- 4 files changed, 97 insertions(+), 204 deletions(-) diff --git a/src/App/DocumentObjectPy.xml b/src/App/DocumentObjectPy.xml index 55a0f57ad..a3e30c9b5 100644 --- a/src/App/DocumentObjectPy.xml +++ b/src/App/DocumentObjectPy.xml @@ -13,7 +13,29 @@ This is the father of all classes handled by the document - + + + + addProperty(string, string) -- Add a generic property. + The first argument specifies the type, the second the + name of the property. + + + + + + + removeProperty(string) -- Remove a generic property. + Note, you can only remove user-defined properties but not built-in ones. + + + + + + A list of supported property types + + + Mark the object as changed (touched) diff --git a/src/App/DocumentObjectPyImp.cpp b/src/App/DocumentObjectPyImp.cpp index 7c74b48da..b4b99fa4a 100644 --- a/src/App/DocumentObjectPyImp.cpp +++ b/src/App/DocumentObjectPyImp.cpp @@ -24,11 +24,11 @@ #include "DocumentObject.h" #include "Document.h" +#include "Expression.h" // inclusion of the generated files (generated out of DocumentObjectPy.xml) -#include "DocumentObjectPy.h" -#include "DocumentObjectPy.cpp" -#include "Expression.h" +#include +#include using namespace App; @@ -60,6 +60,71 @@ Py::Object DocumentObjectPy::getDocument(void) const } } +PyObject* DocumentObjectPy::addProperty(PyObject *args) +{ + char *sType,*sName=0,*sGroup=0,*sDoc=0; + short attr=0; + std::string sDocStr; + PyObject *ro = Py_False, *hd = Py_False; + if (!PyArg_ParseTuple(args, "s|ssethO!O!", &sType,&sName,&sGroup,"utf-8",&sDoc,&attr, + &PyBool_Type, &ro, &PyBool_Type, &hd)) // convert args: Python->C + return NULL; // NULL triggers exception + + if (sDoc) { + sDocStr = sDoc; + PyMem_Free(sDoc); + } + + App::Property* prop=0; + try { + prop = getDocumentObjectPtr()->addDynamicProperty(sType,sName,sGroup,sDocStr.c_str(),attr, + PyObject_IsTrue(ro) ? true : false, PyObject_IsTrue(hd) ? true : false); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } + if (!prop) { + std::stringstream str; + str << "No property found of type '" << sType << "'" << std::ends; + throw Py::Exception(Base::BaseExceptionFreeCADError,str.str()); + } + + return Py::new_reference_to(this); +} + +PyObject* DocumentObjectPy::removeProperty(PyObject *args) +{ + char *sName; + if (!PyArg_ParseTuple(args, "s", &sName)) + return NULL; + + try { + bool ok = getDocumentObjectPtr()->removeDynamicProperty(sName); + return Py_BuildValue("O", (ok ? Py_True : Py_False)); + } + catch (const Base::Exception& e) { + throw Py::RuntimeError(e.what()); + } +} + +PyObject* DocumentObjectPy::supportedProperties(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) // convert args: Python->C + return NULL; // NULL triggers exception + + std::vector ary; + Base::Type::getAllDerivedFrom(App::Property::getClassTypeId(), ary); + Py::List res; + for (std::vector::iterator it = ary.begin(); it != ary.end(); ++it) { + Base::BaseClass *data = static_cast(it->createInstance()); + if (data) { + delete data; + res.append(Py::String(it->getName())); + } + } + return Py::new_reference_to(res); +} + PyObject* DocumentObjectPy::touch(PyObject * args) { if (!PyArg_ParseTuple(args, "")) // convert args: Python->C diff --git a/src/App/FeaturePythonPyImp.h b/src/App/FeaturePythonPyImp.h index e5974773f..3ee30c471 100644 --- a/src/App/FeaturePythonPyImp.h +++ b/src/App/FeaturePythonPyImp.h @@ -48,18 +48,6 @@ public: /** @name callbacks and implementers for the python object methods */ //@{ static int __setattr(PyObject *PyObj, char *attr, PyObject *value); - /// callback for the addProperty() method - static PyObject * staticCallback_addProperty (PyObject *self, PyObject *args); - /// implementer for the addProperty() method - PyObject* addProperty(PyObject *args); - /// callback for the removeProperty() method - static PyObject * staticCallback_removeProperty (PyObject *self, PyObject *args); - /// implementer for the removeProperty() method - PyObject* removeProperty(PyObject *args); - /// callback for the supportedProperties() method - static PyObject * staticCallback_supportedProperties (PyObject *self, PyObject *args); - /// implementer for the supportedProperties() method - PyObject* supportedProperties(PyObject *args); //@} /// getter method for special attributes (e.g. dynamic ones) diff --git a/src/App/FeaturePythonPyImp.inl b/src/App/FeaturePythonPyImp.inl index fcd64f6c7..871b91c5d 100644 --- a/src/App/FeaturePythonPyImp.inl +++ b/src/App/FeaturePythonPyImp.inl @@ -83,132 +83,9 @@ PyTypeObject FeaturePythonPyT::Type = { /// Methods structure of FeaturePythonPyT template PyMethodDef FeaturePythonPyT::Methods[] = { - {"addProperty", - (PyCFunction) staticCallback_addProperty, - METH_VARARGS, - "addProperty(string, string) -- Add a generic property.\nThe first argument specifies the type, the second the\nname of the property.\n" - }, - {"removeProperty", - (PyCFunction) staticCallback_removeProperty, - METH_VARARGS, - "removeProperty(string) -- Remove a generic property.\nNote, you can only remove user-defined properties but not built-in ones.\n" - }, - {"supportedProperties", - (PyCFunction) staticCallback_supportedProperties, - METH_VARARGS, - "A list of supported property types" - }, {NULL, NULL, 0, NULL} /* Sentinel */ }; -template -PyObject * FeaturePythonPyT::staticCallback_addProperty (PyObject *self, PyObject *args) -{ - // test if twin object not allready deleted - if (!static_cast(self)->isValid()){ - PyErr_SetString(PyExc_ReferenceError, "This object is already deleted most likely through closing a document. This reference is no longer valid!"); - return NULL; - } - - // test if object is set Const - if (static_cast(self)->isConst()){ - PyErr_SetString(PyExc_ReferenceError, "This object is immutable, you can not set any attribute or call a non const method"); - return NULL; - } - - try { - PyObject* ret = static_cast(self)->addProperty(args); - if (ret != 0) - static_cast(self)->startNotify(); - return ret; - } - catch(const Base::Exception& e) { - std::string str; - str += "FreeCAD exception thrown ("; - str += e.what(); - str += ")"; - e.ReportException(); - PyErr_SetString(Base::BaseExceptionFreeCADError,str.c_str()); - return NULL; - } - catch(const Py::Exception&) { - // The exception text is already set - return NULL; - } -} - -template -PyObject * FeaturePythonPyT::staticCallback_removeProperty (PyObject *self, PyObject *args) -{ - // test if twin object not allready deleted - if (!static_cast(self)->isValid()){ - PyErr_SetString(PyExc_ReferenceError, "This object is already deleted most likely through closing a document. This reference is no longer valid!"); - return NULL; - } - - // test if object is set Const - if (static_cast(self)->isConst()){ - PyErr_SetString(PyExc_ReferenceError, "This object is immutable, you can not set any attribute or call a non const method"); - return NULL; - } - - try { - PyObject* ret = static_cast(self)->removeProperty(args); - if (ret != 0) - static_cast(self)->startNotify(); - return ret; - } - catch(const Base::Exception& e) { - std::string str; - str += "FreeCAD exception thrown ("; - str += e.what(); - str += ")"; - e.ReportException(); - PyErr_SetString(Base::BaseExceptionFreeCADError,str.c_str()); - return NULL; - } - catch(const Py::Exception&) { - // The exception text is already set - return NULL; - } -} - -template -PyObject * FeaturePythonPyT::staticCallback_supportedProperties (PyObject *self, PyObject *args) -{ - // test if twin object not allready deleted - if (!static_cast(self)->isValid()){ - PyErr_SetString(PyExc_ReferenceError, "This object is already deleted most likely through closing a document. This reference is no longer valid!"); - return NULL; - } - - // test if object is set Const - if (static_cast(self)->isConst()){ - PyErr_SetString(PyExc_ReferenceError, "This object is immutable, you can not set any attribute or call a non const method"); - return NULL; - } - - try { - PyObject* ret = static_cast(self)->supportedProperties(args); - if (ret != 0) - static_cast(self)->startNotify(); - return ret; - } - catch(const Base::Exception& e) { - std::string str; - str += "FreeCAD exception thrown ("; - str += e.what(); - str += ")"; - e.ReportException(); - PyErr_SetString(Base::BaseExceptionFreeCADError,str.c_str()); - return NULL; - } - catch(const Py::Exception&) { - // The exception text is already set - return NULL; - } -} - template FeaturePythonPyT::FeaturePythonPyT(DocumentObject *pcObject, PyTypeObject *T) : FeaturePyT(reinterpret_cast(pcObject), T) @@ -326,65 +203,6 @@ int FeaturePythonPyT::_setattr(char *attr, PyObject *value) // ------------------------------------------------------------- -template -PyObject* FeaturePythonPyT::addProperty(PyObject *args) -{ - char *sType,*sName=0,*sGroup=0,*sDoc=0; - short attr=0; - std::string sDocStr; - PyObject *ro = Py_False, *hd = Py_False; - if (!PyArg_ParseTuple(args, "s|ssethO!O!", &sType,&sName,&sGroup,"utf-8",&sDoc,&attr, - &PyBool_Type, &ro, &PyBool_Type, &hd)) // convert args: Python->C - return NULL; // NULL triggers exception - - if (sDoc) { - sDocStr = sDoc; - PyMem_Free(sDoc); - } - - Property* prop=0; - prop = FeaturePyT::getDocumentObjectPtr()->addDynamicProperty(sType,sName,sGroup,sDocStr.c_str(),attr, - PyObject_IsTrue(ro) ? true : false, PyObject_IsTrue(hd) ? true : false); - - if (!prop) { - std::stringstream str; - str << "No property found of type '" << sType << "'" << std::ends; - throw Py::Exception(Base::BaseExceptionFreeCADError,str.str()); - } - - return Py::new_reference_to(this); -} - -template -PyObject* FeaturePythonPyT::removeProperty(PyObject *args) -{ - char *sName; - if (!PyArg_ParseTuple(args, "s", &sName)) - return NULL; - - bool ok = FeaturePyT::getDocumentObjectPtr()->removeDynamicProperty(sName); - return Py_BuildValue("O", (ok ? Py_True : Py_False)); -} - -template -PyObject* FeaturePythonPyT::supportedProperties(PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) // convert args: Python->C - return NULL; // NULL triggers exception - - std::vector ary; - Base::Type::getAllDerivedFrom(App::Property::getClassTypeId(), ary); - Py::List res; - for (std::vector::iterator it = ary.begin(); it != ary.end(); ++it) { - Base::BaseClass *data = static_cast(it->createInstance()); - if (data) { - delete data; - res.append(Py::String(it->getName())); - } - } - return Py::new_reference_to(res); -} - template PyObject *FeaturePythonPyT::getCustomAttributes(const char* attr) const { @@ -414,10 +232,11 @@ PyObject *FeaturePythonPyT::getCustomAttributes(const char* attr) co // search for dynamic property Property* prop = FeaturePyT::getDocumentObjectPtr()->getDynamicPropertyByName(attr); - if (prop) return prop->getPyObject(); - } PY_CATCH; - - return 0; + if (prop) + return prop->getPyObject(); + else + return 0; + } PY_CATCH } template @@ -431,6 +250,7 @@ int FeaturePythonPyT::setCustomAttributes(const char* attr, PyObject else { try { prop->setPyObject(value); + return 1; } catch (Base::Exception &exc) { PyErr_Format(PyExc_AttributeError, "Attribute (Name: %s) error: '%s' ", attr, exc.what()); return -1; @@ -438,8 +258,6 @@ int FeaturePythonPyT::setCustomAttributes(const char* attr, PyObject PyErr_Format(PyExc_AttributeError, "Unknown error in attribute %s", attr); return -1; } - - return 1; } }