move handling of dynamic properties from FeaturePythonPyT to DocumentObjectPy

This commit is contained in:
wmayer
2016-11-09 16:09:21 +01:00
parent 07a2182674
commit 76279882da
6 changed files with 87 additions and 140 deletions

View File

@@ -58,7 +58,7 @@ PyTypeObject FeaturePythonPyT<FeaturePyT>::Type = {
0, /*tp_weaklistoffset */
0, /*tp_iter */
0, /*tp_iternext */
App::FeaturePythonPyT<FeaturePyT>::Methods, /*tp_methods */
0, /*tp_methods */
0, /*tp_members */
0, /*tp_getset */
&FeaturePyT::Type, /*tp_base */
@@ -80,14 +80,8 @@ PyTypeObject FeaturePythonPyT<FeaturePyT>::Type = {
0 /*tp_version_tag */
};
/// Methods structure of FeaturePythonPyT
template<class FeaturePyT>
PyMethodDef FeaturePythonPyT<FeaturePyT>::Methods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */
};
template<class FeaturePyT>
FeaturePythonPyT<FeaturePyT>::FeaturePythonPyT(DocumentObject *pcObject, PyTypeObject *T)
FeaturePythonPyT<FeaturePyT>::FeaturePythonPyT(PropertyContainer *pcObject, PyTypeObject *T)
: FeaturePyT(reinterpret_cast<typename FeaturePyT::PointerType>(pcObject), T)
{
}
@@ -100,6 +94,8 @@ FeaturePythonPyT<FeaturePyT>::~FeaturePythonPyT()
template<class FeaturePyT>
int FeaturePythonPyT<FeaturePyT>::__setattr(PyObject *obj, char *attr, PyObject *value)
{
// This overwrites PyObjectBase::__setattr because this actively disallows to delete an attribute
//
if (!static_cast<Base::PyObjectBase*>(obj)->isValid()){
PyErr_Format(PyExc_ReferenceError, "Cannot access attribute '%s' of deleted object", attr);
return -1;
@@ -112,68 +108,9 @@ int FeaturePythonPyT<FeaturePyT>::__setattr(PyObject *obj, char *attr, PyObject
return ret;
}
template<class FeaturePyT>
PyObject *FeaturePythonPyT<FeaturePyT>::_getattr(char *attr)
{
try {
// getter method for special Attributes (e.g. dynamic ones)
PyObject *r = getCustomAttributes(attr);
if(r) return r;
}
catch(const Base::Exception& e) {// catch the FreeCAD exceptions
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;
}
PyObject *rvalue = Py_FindMethod(Methods, this, attr);
if (rvalue == NULL) {
std::map<std::string, PyObject*>::iterator it = dyn_methods.find(attr);
if (it != dyn_methods.end()) {
Py_INCREF(it->second);
rvalue = it->second;
PyErr_Clear();
}
}
if (rvalue == NULL) {
PyErr_Clear();
return FeaturePyT::_getattr(attr);
}
else {
return rvalue;
}
}
template<class FeaturePyT>
int FeaturePythonPyT<FeaturePyT>::_setattr(char *attr, PyObject *value)
{
try {
// setter for special Attributes (e.g. dynamic ones)
int r = setCustomAttributes(attr, value);
if(r==1) return 0;
}
catch(const Base::Exception& e) { // catch the FreeCAD exceptions
std::string str;
str += "FreeCAD exception thrown (";
str += e.what();
str += ")";
e.ReportException();
PyErr_SetString(Base::BaseExceptionFreeCADError,str.c_str());
return -1;
}
catch(const Py::Exception&) {
// The exception text is already set
return -1;
}
int returnValue = FeaturePyT::_setattr(attr, value);
if (returnValue == -1) {
if (value) {
@@ -201,64 +138,49 @@ int FeaturePythonPyT<FeaturePyT>::_setattr(char *attr, PyObject *value)
return returnValue;
}
// -------------------------------------------------------------
template<class FeaturePyT>
PyObject *FeaturePythonPyT<FeaturePyT>::getCustomAttributes(const char* attr) const
PyObject *FeaturePythonPyT<FeaturePyT>::_getattr(char *attr)
{
PY_TRY{
if (Base::streq(attr, "__dict__")){
// Return the default dict
PyTypeObject *tp = this->ob_type;
// register type if needed
if (tp->tp_dict == NULL) {
if (PyType_Ready(tp) < 0)
return 0;
}
PyObject* dict = PyDict_Copy(tp->tp_dict);
std::map<std::string,App::Property*> Map;
FeaturePyT::getPropertyContainerPtr()->getPropertyMap(Map);
for (std::map<std::string,App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it)
PyDict_SetItem(dict, PyString_FromString(it->first.c_str()), PyString_FromString(""));
for (std::map<std::string, PyObject*>::const_iterator it = dyn_methods.begin(); it != dyn_methods.end(); ++it)
PyDict_SetItem(dict, PyString_FromString(it->first.c_str()), PyString_FromString(""));
if (PyErr_Occurred()) {
Py_DECREF(dict);
dict = 0;
}
return dict;
}
// search for dynamic property
Property* prop = FeaturePyT::getDocumentObjectPtr()->getDynamicPropertyByName(attr);
if (prop)
return prop->getPyObject();
else
return 0;
} PY_CATCH
}
template<class FeaturePyT>
int FeaturePythonPyT<FeaturePyT>::setCustomAttributes(const char* attr, PyObject *value)
{
// search for dynamic property
Property* prop = FeaturePyT::getDocumentObjectPtr()->getDynamicPropertyByName(attr);
if (!prop)
return FeaturePyT::setCustomAttributes(attr, value);
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;
} catch (...) {
PyErr_Format(PyExc_AttributeError, "Unknown error in attribute %s", attr);
return -1;
}
// See CallTipsList::extractTips
if (Base::streq(attr, "__fc_template__")) {
Py_INCREF(Py_None);
return Py_None;
}
if (Base::streq(attr, "__dict__")) {
// Return the default dict
PyTypeObject *tp = this->ob_type;
// register type if needed
if (tp->tp_dict == NULL) {
if (PyType_Ready(tp) < 0)
return 0;
}
PyObject* dict = PyDict_Copy(tp->tp_dict);
std::map<std::string,App::Property*> Map;
FeaturePyT::getPropertyContainerPtr()->getPropertyMap(Map);
for (std::map<std::string,App::Property*>::iterator it = Map.begin(); it != Map.end(); ++it)
PyDict_SetItem(dict, PyString_FromString(it->first.c_str()), PyString_FromString(""));
for (std::map<std::string, PyObject*>::const_iterator it = dyn_methods.begin(); it != dyn_methods.end(); ++it)
PyDict_SetItem(dict, PyString_FromString(it->first.c_str()), PyString_FromString(""));
if (PyErr_Occurred()) {
Py_DECREF(dict);
dict = 0;
}
return dict;
}
PyObject *rvalue = NULL;
std::map<std::string, PyObject*>::iterator it = dyn_methods.find(attr);
if (it != dyn_methods.end()) {
Py_INCREF(it->second);
rvalue = it->second;
PyErr_Clear();
return rvalue;
}
PyErr_Clear();
return FeaturePyT::_getattr(attr);
}
} //namespace App