From 69d0e8bd7ff2d83271d79ef1755f379d1028213a Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 3 Jun 2017 02:21:59 +0200 Subject: [PATCH] py3: partially revert of getattr -> getattro because getattro is only needed for the static callback function issue 0000995 --- src/App/FeaturePythonPyImp.h | 4 +- src/App/FeaturePythonPyImp.inl | 26 ++----- src/Base/PyObjectBase.cpp | 67 +++++++++---------- src/Base/PyObjectBase.h | 6 +- .../templateClassPyExport.py | 25 ++----- 5 files changed, 51 insertions(+), 77 deletions(-) diff --git a/src/App/FeaturePythonPyImp.h b/src/App/FeaturePythonPyImp.h index bcec0c5276..0ca20abb27 100644 --- a/src/App/FeaturePythonPyImp.h +++ b/src/App/FeaturePythonPyImp.h @@ -103,8 +103,8 @@ public: //@{ static int __setattro(PyObject *PyObj, PyObject *attro, PyObject *value); //@} - PyObject *_getattro(PyObject *attr); // __getattr__ function - int _setattro(PyObject *attro, PyObject *value); // __setattr__ function + PyObject *_getattr(char *attr); // __getattr__ function + int _setattr(char *attr, PyObject *value); // __setattr__ function protected: PyObject * dict_methods; diff --git a/src/App/FeaturePythonPyImp.inl b/src/App/FeaturePythonPyImp.inl index 9de1184957..9f7f09fa93 100644 --- a/src/App/FeaturePythonPyImp.inl +++ b/src/App/FeaturePythonPyImp.inl @@ -61,7 +61,7 @@ PyTypeObject FeaturePythonPyT::Type = { 0, /*tp_weaklistoffset */ 0, /*tp_iter */ 0, /*tp_iternext */ - App::FeaturePythonPyT::Methods, /*tp_methods */ + 0, /*tp_methods */ 0, /*tp_members */ 0, /*tp_getset */ &FeaturePyT::Type, /*tp_base */ @@ -118,7 +118,7 @@ int FeaturePythonPyT::__setattro(PyObject *obj, PyObject *attro, PyO return -1; } - int ret = static_cast(obj)->_setattro(attro, value); + int ret = static_cast(obj)->_setattr(attr, value); if (ret == 0) { static_cast(obj)->startNotify(); } @@ -127,21 +127,15 @@ int FeaturePythonPyT::__setattro(PyObject *obj, PyObject *attro, PyO template -int FeaturePythonPyT::_setattro(PyObject *attro, PyObject *value) +int FeaturePythonPyT::_setattr(char *attr, PyObject *value) { - char *attr; -#if PY_MAJOR_VERSION >= 3 - attr = PyUnicode_AsUTF8(attro); -#else - attr = PyString_AsString(attro); -#endif App::Property *prop = FeaturePyT::getPropertyContainerPtr()->getPropertyByName(attr); if (prop && !value) { PyErr_Format(PyExc_AttributeError, "Cannot delete attribute: '%s'", attr); return -1; } - int returnValue = FeaturePyT::_setattro(attro, value); + int returnValue = FeaturePyT::_setattr(attr, value); if (returnValue == -1) { PyObject* dict_item = value; if (value) { @@ -168,14 +162,8 @@ int FeaturePythonPyT::_setattro(PyObject *attro, PyObject *value) } template -PyObject *FeaturePythonPyT::_getattro(PyObject *attro) +PyObject *FeaturePythonPyT::_getattr(char *attr) { - char *attr; -#if PY_MAJOR_VERSION >= 3 - attr = PyUnicode_AsUTF8(attro); -#else - attr = PyString_AsString(attro); -#endif // See CallTipsList::extractTips if (Base::streq(attr, "__fc_template__")) { Py_INCREF(Py_None); @@ -192,7 +180,7 @@ PyObject *FeaturePythonPyT::_getattro(PyObject *attro) return 0; } - PyObject* dict = FeaturePyT::_getattro(attro); + PyObject* dict = FeaturePyT::_getattr(attr); if (dict && PyDict_CheckExact(dict)) { PyObject* dict_old = dict; dict = PyDict_Copy(dict_old); @@ -212,7 +200,7 @@ PyObject *FeaturePythonPyT::_getattro(PyObject *attro) // search for the attribute in the base class PyErr_Clear(); - return FeaturePyT::_getattro(attro); + return FeaturePyT::_getattr(attr); } } //namespace App diff --git a/src/Base/PyObjectBase.cpp b/src/Base/PyObjectBase.cpp index d2a435422e..7b17ca4c8b 100644 --- a/src/Base/PyObjectBase.cpp +++ b/src/Base/PyObjectBase.cpp @@ -95,7 +95,11 @@ PyTypeObject PyObjectBase::Type = { /* --- Functions to access object as input/output buffer ---------*/ 0, /* tp_as_buffer */ /* --- Flags to define presence of optional/expanded features */ +#if PY_MAJOR_VERSION >= 3 Py_TPFLAGS_BASETYPE|Py_TPFLAGS_DEFAULT, /*tp_flags */ +#else + Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_CLASS, /*tp_flags */ +#endif "The most base class for Python binding", /*tp_doc */ 0, /*tp_traverse */ 0, /*tp_clear */ @@ -139,12 +143,11 @@ PyObject* PyObjectBase::__getattro(PyObject * obj, PyObject *attro) { char *attr; #if PY_MAJOR_VERSION >= 3 - if (PyUnicode_Check(attro)) - attr = PyUnicode_AsUTF8(attro); + attr = PyUnicode_AsUTF8(attro); #else - if (PyString_Check(attro)) - attr = PyString_AsString(attro); + attr = PyString_AsString(attro); #endif + // This should be the entry in Type PyObjectBase* pyObj = static_cast(obj); if (!pyObj->isValid()){ @@ -162,7 +165,7 @@ PyObject* PyObjectBase::__getattro(PyObject * obj, PyObject *attro) } } - PyObject* value = pyObj->_getattro(attro); + PyObject* value = pyObj->_getattr(attr); #if 1 if (value && PyObject_TypeCheck(value, &(PyObjectBase::Type))) { if (!static_cast(value)->isConst()) { @@ -194,14 +197,13 @@ int PyObjectBase::__setattro(PyObject *obj, PyObject *attro, PyObject *value) { char *attr; #if PY_MAJOR_VERSION >= 3 - if (PyUnicode_Check(attro)) - attr = PyUnicode_AsUTF8(attro); + attr = PyUnicode_AsUTF8(attro); #else - if (PyString_Check(attro)) - attr = PyString_AsString(attro); + attr = PyString_AsString(attro); #endif + //FIXME: In general we don't allow to delete attributes (i.e. value=0). However, if we want to allow - //we must check then in _setattro() of all subclasses whether value is 0. + //we must check then in _setattr() of all subclasses whether value is 0. if ( value==0 ) { PyErr_Format(PyExc_AttributeError, "Cannot delete attribute: '%s'", attr); return -1; @@ -222,7 +224,7 @@ int PyObjectBase::__setattro(PyObject *obj, PyObject *attro, PyObject *value) } } - int ret = static_cast(obj)->_setattro(attro, value); + int ret = static_cast(obj)->_setattr(attr, value); #if 1 if (ret == 0) { static_cast(obj)->startNotify(); @@ -234,16 +236,8 @@ int PyObjectBase::__setattro(PyObject *obj, PyObject *attro, PyObject *value) /*------------------------------ * PyObjectBase attributes -- attributes ------------------------------*/ -PyObject *PyObjectBase::_getattro(PyObject *attro) +PyObject *PyObjectBase::_getattr(char *attr) { - char *attr; -#if PY_MAJOR_VERSION >= 3 - if (PyUnicode_Check(attro)) - attr = PyUnicode_AsUTF8(attro); -#else - if (PyString_Check(attro)) - attr = PyString_AsString(attro); -#endif if (streq(attr, "__class__")) { // Note: We must return the type object here, // so that our own types feel as really Python objects @@ -266,9 +260,15 @@ PyObject *PyObjectBase::_getattro(PyObject *attro) } else { // As fallback solution use Python's default method to get generic attributes - PyObject *res; - if (attro != NULL) { - res = PyObject_GenericGetAttr(this, attro); + PyObject *w, *res; +#if PY_MAJOR_VERSION >= 3 + w = PyUnicode_InternFromString(attr); +#else + w = PyString_InternFromString(attr); +#endif + if (w != NULL) { + res = PyObject_GenericGetAttr(this, w); + Py_XDECREF(w); return res; } else { // Throw an exception for unknown attributes @@ -279,22 +279,21 @@ PyObject *PyObjectBase::_getattro(PyObject *attro) } } -int PyObjectBase::_setattro(PyObject *attro, PyObject *value) +int PyObjectBase::_setattr(char *attr, PyObject *value) { - char *attr; -#if PY_MAJOR_VERSION >= 3 - if (PyUnicode_Check(attro)) - attr = PyUnicode_AsUTF8(attro); -#else - if (PyString_Check(attro)) - attr = PyString_AsString(attro); -#endif if (streq(attr,"softspace")) return -1; // filter out softspace + PyObject *w; // As fallback solution use Python's default method to get generic attributes - if (attro != NULL) { +#if PY_MAJOR_VERSION >= 3 + w = PyUnicode_InternFromString(attr); // new reference +#else + w = PyString_InternFromString(attr); // new reference +#endif + if (w != NULL) { // call methods from tp_getset if defined - int res = PyObject_GenericSetAttr(this, attro, value); + int res = PyObject_GenericSetAttr(this, w, value); + Py_DECREF(w); return res; } else { // Throw an exception for unknown attributes diff --git a/src/Base/PyObjectBase.h b/src/Base/PyObjectBase.h index 7cdc14dc27..8f2b14bba2 100644 --- a/src/Base/PyObjectBase.h +++ b/src/Base/PyObjectBase.h @@ -222,11 +222,11 @@ public: * If you want to implement attributes in your class, reimplement * this method. * You have to call the method of the base class. - * Note: if you reimplement _gettattro() in a inheriting class you + * Note: if you reimplement _gettattr() in a inheriting class you * need to call the method of the base class! Otherwise even the * methods of the object will disappear! */ - virtual PyObject *_getattro(PyObject *attro); + virtual PyObject *_getattr(char *attr); /// static wrapper for pythons _getattro() static PyObject *__getattro(PyObject * PyObj, PyObject *attro); @@ -236,7 +236,7 @@ public: * this method. * You have to call the method of the base class. */ - virtual int _setattro(PyObject *attro, PyObject *value); // _setattro method + virtual int _setattr(char *attro, PyObject *value); // _setattr method /// static wrapper for pythons _setattro(). // This should be the entry in Type. static int __setattro(PyObject *PyObj, PyObject *attro, PyObject *value); diff --git a/src/Tools/generateTemplates/templateClassPyExport.py b/src/Tools/generateTemplates/templateClassPyExport.py index 761259f871..632b7cf1f4 100644 --- a/src/Tools/generateTemplates/templateClassPyExport.py +++ b/src/Tools/generateTemplates/templateClassPyExport.py @@ -225,8 +225,8 @@ public: /// setter for special attributes (e.g. dynamic ones) /// Output: Success=1, Failure=-1, Ignore=0 int setCustomAttributes(const char* attr, PyObject *obj); - PyObject *_getattro(PyObject *attro); // __getattr__ function - int _setattro(PyObject *attro, PyObject *value); // __setattr__ function + PyObject *_getattr(char *attr); // __getattr__ function + int _setattr(char *attr, PyObject *value); // __setattr__ function - /// getter for the object handled by this class @@ -712,14 +712,8 @@ PyObject *@self.export.Name@::_repr(void) //-------------------------------------------------------------------------- // @self.export.Name@ Attributes //-------------------------------------------------------------------------- -PyObject *@self.export.Name@::_getattro(PyObject *attro) // __getattr__ function: note only need to handle new state +PyObject *@self.export.Name@::_getattr(char *attr) // __getattr__ function: note only need to handle new state { - char *attr; -#if PY_MAJOR_VERSION >= 3 - attr = PyUnicode_AsUTF8(attro); -#else - attr = PyString_AsString(attro); -#endif try { // getter method for special Attributes (e.g. dynamic ones) PyObject *r = getCustomAttributes(attr); @@ -781,18 +775,11 @@ PyObject *@self.export.Name@::_getattro(PyObject *attro) // __getattr__ funct } PyErr_Clear(); - return @self.export.Father@::_getattro(attro); + return @self.export.Father@::_getattr(attr); } -int @self.export.Name@::_setattro(PyObject *attro, PyObject *value) // __setattr__ function: note only need to handle new state - +int @self.export.Name@::_setattr(char *attr, PyObject *value) // __setattr__ function: note only need to handle new state { - char *attr; -#if PY_MAJOR_VERSION >= 3 - attr = PyUnicode_AsUTF8(attro); -#else - attr = PyString_AsString(attro); -#endif try { // setter for special Attributes (e.g. dynamic ones) int r = setCustomAttributes(attr, value); @@ -852,7 +839,7 @@ int @self.export.Name@::_setattro(PyObject *attro, PyObject *value) // __setatt } #endif // DONT_CATCH_CXX_EXCEPTIONS - return @self.export.Father@::_setattro(attro, value); + return @self.export.Father@::_setattr(attr, value); } -