py3: change of getattr -> getattro

issue 0000995
This commit is contained in:
looooo
2017-06-02 11:53:39 +02:00
committed by wmayer
parent 3168f8ed3f
commit bc696e5ab5
5 changed files with 215 additions and 92 deletions

View File

@@ -101,10 +101,10 @@ public:
/** @name callbacks and implementers for the python object methods */
//@{
static int __setattr(PyObject *PyObj, char *attr, PyObject *value);
static int __setattro(PyObject *PyObj, PyObject *attro, PyObject *value);
//@}
PyObject *_getattr(char *attr); // __getattr__ function
int _setattr(char *attr, PyObject *value); // __setattr__ function
PyObject *_getattro(PyObject *attr); // __getattr__ function
int _setattro(PyObject *attro, PyObject *value); // __setattr__ function
protected:
PyObject * dict_methods;

View File

@@ -27,16 +27,15 @@ namespace App
/// Type structure of FeaturePythonPyT
template<class FeaturePyT>
PyTypeObject FeaturePythonPyT<FeaturePyT>::Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
PyVarObject_HEAD_INIT(&PyType_Type,0)
"FeaturePython", /*tp_name*/
sizeof(FeaturePythonPyT), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
FeaturePyT::PyDestructor, /*tp_dealloc*/
0, /*tp_print*/
FeaturePyT::__getattr, /*tp_getattr*/
__setattr, /*tp_setattr*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
@@ -45,12 +44,16 @@ PyTypeObject FeaturePythonPyT<FeaturePyT>::Type = {
0, /*tp_hash*/
0, /*tp_call */
0, /*tp_str */
0, /*tp_getattro*/
0, /*tp_setattro*/
FeaturePyT::__getattro, /*tp_getattro*/
__setattro, /*tp_setattro*/
/* --- 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
"This is the father of all Feature classes", /*tp_doc */
0, /*tp_traverse */
0, /*tp_clear */
@@ -58,7 +61,7 @@ PyTypeObject FeaturePythonPyT<FeaturePyT>::Type = {
0, /*tp_weaklistoffset */
0, /*tp_iter */
0, /*tp_iternext */
0, /*tp_methods */
App::FeaturePythonPyT<FeaturePyT>::Methods, /*tp_methods */
0, /*tp_members */
0, /*tp_getset */
&FeaturePyT::Type, /*tp_base */
@@ -78,6 +81,9 @@ PyTypeObject FeaturePythonPyT<FeaturePyT>::Type = {
0, /*tp_weaklist */
0, /*tp_del */
0 /*tp_version_tag */
#if PY_MAJOR_VERSION >= 3
,0 /*tp_finalize */
#endif
};
template<class FeaturePyT>
@@ -96,38 +102,56 @@ FeaturePythonPyT<FeaturePyT>::~FeaturePythonPyT()
}
template<class FeaturePyT>
int FeaturePythonPyT<FeaturePyT>::__setattr(PyObject *obj, char *attr, PyObject *value)
int FeaturePythonPyT<FeaturePyT>::__setattro(PyObject *obj, PyObject *attro, PyObject *value)
{
char *attr;
#if PY_MAJOR_VERSION >= 3
attr = PyUnicode_AsUTF8(attro);
#else
attr = PyString_AsString(attro);
#endif
// 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;
}
int ret = static_cast<Base::PyObjectBase*>(obj)->_setattr(attr, value);
int ret = static_cast<Base::PyObjectBase*>(obj)->_setattro(attro, value);
if (ret == 0) {
static_cast<Base::PyObjectBase*>(obj)->startNotify();
}
return ret;
}
template<class FeaturePyT>
int FeaturePythonPyT<FeaturePyT>::_setattr(char *attr, PyObject *value)
int FeaturePythonPyT<FeaturePyT>::_setattro(PyObject *attro, 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::_setattr(attr, value);
int returnValue = FeaturePyT::_setattro(attro, value);
if (returnValue == -1) {
PyObject* dict_item = value;
if (value) {
if (PyFunction_Check(value)) {
PyErr_Clear();
#if PY_MAJOR_VERSION < 3
dict_item = PyMethod_New(value, this, 0);
#else
dict_item = PyMethod_New(value, this);
#endif
returnValue = PyDict_SetItemString(dict_methods, attr, dict_item);
Py_XDECREF(dict_item);
}
@@ -144,8 +168,14 @@ int FeaturePythonPyT<FeaturePyT>::_setattr(char *attr, PyObject *value)
}
template<class FeaturePyT>
PyObject *FeaturePythonPyT<FeaturePyT>::_getattr(char *attr)
PyObject *FeaturePythonPyT<FeaturePyT>::_getattro(PyObject *attro)
{
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);
@@ -162,7 +192,7 @@ PyObject *FeaturePythonPyT<FeaturePyT>::_getattr(char *attr)
return 0;
}
PyObject* dict = FeaturePyT::_getattr(attr);
PyObject* dict = FeaturePyT::_getattro(attro);
if (dict && PyDict_CheckExact(dict)) {
PyObject* dict_old = dict;
dict = PyDict_Copy(dict_old);
@@ -182,7 +212,7 @@ PyObject *FeaturePythonPyT<FeaturePyT>::_getattr(char *attr)
// search for the attribute in the base class
PyErr_Clear();
return FeaturePyT::_getattr(attr);
return FeaturePyT::_getattro(attro);
}
} //namespace App

View File

@@ -40,7 +40,7 @@ PyObject* Base::BaseExceptionFreeCADError = 0;
PyObjectBase::PyObjectBase(void* p,PyTypeObject *T)
: _pcTwinPointer(p), attrDict(0)
{
this->ob_type = T;
Py_TYPE(this) = T;
_Py_NewReference(this);
#ifdef FC_LOGPYOBJECTS
Base::Console().Log("PyO+: %s (%p)\n",T->tp_name, this);
@@ -54,7 +54,7 @@ PyObjectBase::~PyObjectBase()
{
PyGILStateLocker lock;
#ifdef FC_LOGPYOBJECTS
Base::Console().Log("PyO-: %s (%p)\n",this->ob_type->tp_name, this);
Base::Console().Log("PyO-: %s (%p)\n",Py_TYPE(this)->tp_name, this);
#endif
Py_XDECREF(attrDict);
}
@@ -73,16 +73,15 @@ PyObjectBase::~PyObjectBase()
*/
PyTypeObject PyObjectBase::Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
PyVarObject_HEAD_INIT(&PyType_Type,0)
"PyObjectBase", /*tp_name*/
sizeof(PyObjectBase), /*tp_basicsize*/
0, /*tp_itemsize*/
/* --- methods ---------------------------------------------- */
PyDestructor, /*tp_dealloc*/
0, /*tp_print*/
__getattr, /*tp_getattr*/
__setattr, /*tp_setattr*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
__repr, /*tp_repr*/
0, /*tp_as_number*/
@@ -91,12 +90,12 @@ PyTypeObject PyObjectBase::Type = {
0, /*tp_hash*/
0, /*tp_call */
0, /*tp_str */
0, /*tp_getattro*/
0, /*tp_setattro*/
__getattro, /*tp_getattro*/
__setattro, /*tp_setattro*/
/* --- Functions to access object as input/output buffer ---------*/
0, /* tp_as_buffer */
/* --- Flags to define presence of optional/expanded features */
Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_CLASS, /*tp_flags */
Py_TPFLAGS_BASETYPE|Py_TPFLAGS_DEFAULT, /*tp_flags */
"The most base class for Python binding", /*tp_doc */
0, /*tp_traverse */
0, /*tp_clear */
@@ -124,6 +123,9 @@ PyTypeObject PyObjectBase::Type = {
0, /*tp_weaklist */
0, /*tp_del */
0 /*tp_version_tag */
#if PY_MAJOR_VERSION >= 3
,0 /*tp_finalize */
#endif
};
/*------------------------------
@@ -133,8 +135,16 @@ PyMethodDef PyObjectBase::Methods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyObject* PyObjectBase::__getattr(PyObject * obj, char *attr)
PyObject* PyObjectBase::__getattro(PyObject * obj, PyObject *attro)
{
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
// This should be the entry in Type
PyObjectBase* pyObj = static_cast<PyObjectBase*>(obj);
if (!pyObj->isValid()){
@@ -152,7 +162,7 @@ PyObject* PyObjectBase::__getattr(PyObject * obj, char *attr)
}
}
PyObject* value = pyObj->_getattr(attr);
PyObject* value = pyObj->_getattro(attro);
#if 1
if (value && PyObject_TypeCheck(value, &(PyObjectBase::Type))) {
if (!static_cast<PyObjectBase*>(value)->isConst()) {
@@ -180,10 +190,18 @@ PyObject* PyObjectBase::__getattr(PyObject * obj, char *attr)
return value;
}
int PyObjectBase::__setattr(PyObject *obj, char *attr, PyObject *value)
int PyObjectBase::__setattro(PyObject *obj, PyObject *attro, 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
//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 _setattr() of all subclasses whether value is 0.
//we must check then in _setattro() of all subclasses whether value is 0.
if ( value==0 ) {
PyErr_Format(PyExc_AttributeError, "Cannot delete attribute: '%s'", attr);
return -1;
@@ -204,7 +222,7 @@ int PyObjectBase::__setattr(PyObject *obj, char *attr, PyObject *value)
}
}
int ret = static_cast<PyObjectBase*>(obj)->_setattr(attr, value);
int ret = static_cast<PyObjectBase*>(obj)->_setattro(attro, value);
#if 1
if (ret == 0) {
static_cast<PyObjectBase*>(obj)->startNotify();
@@ -216,13 +234,21 @@ int PyObjectBase::__setattr(PyObject *obj, char *attr, PyObject *value)
/*------------------------------
* PyObjectBase attributes -- attributes
------------------------------*/
PyObject *PyObjectBase::_getattr(char *attr)
PyObject *PyObjectBase::_getattro(PyObject *attro)
{
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
Py_INCREF(this->ob_type);
return (PyObject *)(this->ob_type);
Py_INCREF(Py_TYPE(this));
return (PyObject *)(Py_TYPE(this));
}
else if (streq(attr, "__members__")) {
// Use __dict__ instead as __members__ is deprecated
@@ -230,7 +256,7 @@ PyObject *PyObjectBase::_getattr(char *attr)
}
else if (streq(attr,"__dict__")) {
// Return the default dict
PyTypeObject *tp = this->ob_type;
PyTypeObject *tp = Py_TYPE(this);
Py_XINCREF(tp->tp_dict);
return tp->tp_dict;
}
@@ -240,36 +266,39 @@ PyObject *PyObjectBase::_getattr(char *attr)
}
else {
// As fallback solution use Python's default method to get generic attributes
PyObject *w, *res;
w = PyString_InternFromString(attr);
if (w != NULL) {
res = PyObject_GenericGetAttr(this, w);
Py_XDECREF(w);
PyObject *res;
if (attro != NULL) {
res = PyObject_GenericGetAttr(this, attro);
return res;
} else {
// Throw an exception for unknown attributes
PyTypeObject *tp = this->ob_type;
PyTypeObject *tp = Py_TYPE(this);
PyErr_Format(PyExc_AttributeError, "%.50s instance has no attribute '%.400s'", tp->tp_name, attr);
return NULL;
}
}
}
int PyObjectBase::_setattr(char *attr, PyObject *value)
int PyObjectBase::_setattro(PyObject *attro, 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
w = PyString_InternFromString(attr); // new reference
if (w != NULL) {
if (attro != NULL) {
// call methods from tp_getset if defined
int res = PyObject_GenericSetAttr(this, w, value);
Py_DECREF(w);
int res = PyObject_GenericSetAttr(this, attro, value);
return res;
} else {
// Throw an exception for unknown attributes
PyTypeObject *tp = this->ob_type;
PyTypeObject *tp = Py_TYPE(this);
PyErr_Format(PyExc_AttributeError, "%.50s instance has no attribute '%.400s'", tp->tp_name, attr);
return -1;
}
@@ -293,8 +322,13 @@ void PyObjectBase::resetAttribute()
if (attrDict) {
// This is the attribute name to the parent structure
// which we search for in the dict
#if PY_MAJOR_VERSION < 3
PyObject* key1 = PyString_FromString("__attribute_of_parent__");
PyObject* key2 = PyString_FromString("__instance_of_parent__");
#else
PyObject* key1 = PyBytes_FromString("__attribute_of_parent__");
PyObject* key2 = PyBytes_FromString("__instance_of_parent__");
#endif
PyObject* attr = PyDict_GetItem(attrDict, key1);
PyObject* inst = PyDict_GetItem(attrDict, key2);
if (attr) {
@@ -313,10 +347,14 @@ void PyObjectBase::setAttributeOf(const char* attr, PyObject* par)
if (!attrDict) {
attrDict = PyDict_New();
}
#if PY_MAJOR_VERSION < 3
PyObject* key1 = PyString_FromString("__attribute_of_parent__");
PyObject* key2 = PyString_FromString("__instance_of_parent__");
PyObject* attro = PyString_FromString(attr);
#else
PyObject* key1 = PyBytes_FromString("__attribute_of_parent__");
PyObject* key2 = PyBytes_FromString("__instance_of_parent__");
#endif
PyObject* attro = PyUnicode_FromString(attr);
PyDict_SetItem(attrDict, key1, attro);
PyDict_SetItem(attrDict, key2, par);
Py_DECREF(attro);
@@ -332,8 +370,13 @@ void PyObjectBase::startNotify()
if (attrDict) {
// This is the attribute name to the parent structure
// which we search for in the dict
#if PY_MAJOR_VERSION < 3
PyObject* key1 = PyString_FromString("__attribute_of_parent__");
PyObject* key2 = PyString_FromString("__instance_of_parent__");
#else
PyObject* key1 = PyBytes_FromString("__attribute_of_parent__");
PyObject* key2 = PyBytes_FromString("__instance_of_parent__");
#endif
PyObject* attr = PyDict_GetItem(attrDict, key1);
PyObject* parent = PyDict_GetItem(attrDict, key2);
if (attr && parent) {
@@ -345,7 +388,7 @@ void PyObjectBase::startNotify()
Py_INCREF(attr);
Py_INCREF(this);
__setattr(parent, PyString_AsString(attr), this);
__setattro(parent, attr, this);
Py_DECREF(parent); // might be destroyed now
Py_DECREF(attr); // might be destroyed now

View File

@@ -222,13 +222,13 @@ 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 _gettattr() in a inheriting class you
* Note: if you reimplement _gettattro() 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 *_getattr(char *attr);
/// static wrapper for pythons _getattr()
static PyObject *__getattr(PyObject * PyObj, char *attr);
virtual PyObject *_getattro(PyObject *attro);
/// static wrapper for pythons _getattro()
static PyObject *__getattro(PyObject * PyObj, PyObject *attro);
/** SetAttribute implementation
* This method implements the setting of object attributes.
@@ -236,9 +236,9 @@ public:
* this method.
* You have to call the method of the base class.
*/
virtual int _setattr(char *attr, PyObject *value); // _setattr method
/// static wrapper for pythons _setattr(). // This should be the entry in Type.
static int __setattr(PyObject *PyObj, char *attr, PyObject *value);
virtual int _setattro(PyObject *attro, PyObject *value); // _setattro method
/// static wrapper for pythons _setattro(). // This should be the entry in Type.
static int __setattro(PyObject *PyObj, PyObject *attro, PyObject *value);
/** _repr method
* Override this method to return a string object with some

View File

@@ -2,7 +2,9 @@
# -*- coding: utf-8 -*-
# (c) 2006 Juergen Riegel
import template,os,sys
from __future__ import print_function # this allows py2 to print(str1,str2) correctly
from . import template
import os,sys
import generateBase.generateModel_Module
import generateBase.generateTools
@@ -11,20 +13,29 @@ class TemplateClassPyExport (template.ModelTemplate):
#self.ParentNamespace = "Base"
#self.Namespace = "Base"
encoding = sys.getfilesystemencoding()
path = self.path.decode(encoding)
exportName = self.export.Name.decode(encoding)
dirname = self.dirname.decode(encoding)
print "TemplateClassPyExport",path + exportName
path = self.path
if hasattr(path,"decode"): # this is python2. Otherwise this is unicode already
path = path.decode(encoding)
exportName = self.export.Name
if hasattr(exportName,"decode"): # this is python2. Otherwise this is unicode already
exportName = exportName.decode(encoding)
dirname = self.dirname
if hasattr(dirname,"decode"): # this is python2. Otherwise this is unicode already
dirname = dirname.decode(encoding)
print("TemplateClassPyExport",path + exportName)
# Imp.cpp must not exist, neither in path nor in dirname
if(not os.path.exists(path + exportName + "Imp.cpp")):
if(not os.path.exists(dirname + exportName + "Imp.cpp")):
file = open(path + exportName + "Imp.cpp",'w')
file = open(path + exportName + "Imp.cpp",'wb')
generateBase.generateTools.replace(self.TemplateImplement,locals(),file)
file = open(path + exportName + ".cpp",'w')
file.close()
file = open(path + exportName + ".cpp",'wb')
generateBase.generateTools.replace(self.TemplateModule,locals(),file)
file = open(path + exportName + ".h",'w')
file.close()
file = open(path + exportName + ".h",'wb')
generateBase.generateTools.replace(self.TemplateHeader,locals(),file)
#file.write( generateBase.generateTools.replace(self.Template,locals()))
file.close()
TemplateHeader = """
// This file is generated by src/Tools/generateTemaplates/templateClassPyExport.py out of the XML file
@@ -104,8 +115,10 @@ public:
static PyObject * number_subtract_handler (PyObject *self, PyObject *other);
/// callback for the number_multiply_handler
static PyObject * number_multiply_handler (PyObject *self, PyObject *other);
#if PY_MAJOR_VERSION < 3
/// callback for the number_divide_handler
static PyObject * number_divide_handler (PyObject *self, PyObject *other);
#endif
/// callback for the number_remainder_handler
static PyObject * number_remainder_handler (PyObject *self, PyObject *other);
/// callback for the number_divmod_handler
@@ -132,18 +145,24 @@ public:
static PyObject * number_xor_handler (PyObject *self, PyObject *other);
/// callback for the number_or_handler
static PyObject * number_or_handler (PyObject *self, PyObject *other);
#if PY_MAJOR_VERSION < 3
/// callback for the number_coerce_handler
static int number_coerce_handler (PyObject **self, PyObject **other);
#endif
/// callback for the number_int_handler
static PyObject * number_int_handler (PyObject *self);
#if PY_MAJOR_VERSION < 3
/// callback for the number_long_handler
static PyObject * number_long_handler (PyObject *self);
#endif
/// callback for the number_float_handler
static PyObject * number_float_handler (PyObject *self);
#if PY_MAJOR_VERSION < 3
/// callback for the number_oct_handler
static PyObject * number_oct_handler (PyObject *self);
/// callback for the number_hex_handler
static PyObject * number_hex_handler (PyObject *self);
#endif
//@}
-
+ if (self.export.Sequence):
@@ -206,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 *_getattr(char *attr); // __getattr__ function
int _setattr(char *attr, PyObject *value); // __setattr__ function
PyObject *_getattro(PyObject *attro); // __getattr__ function
int _setattro(PyObject *attro, PyObject *value); // __setattr__ function
-
/// getter for the object handled by this class
@@ -245,8 +264,7 @@ using namespace @self.export.Namespace@;
/// Type structure of @self.export.Name@
PyTypeObject @self.export.Name@::Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
PyVarObject_HEAD_INIT(&PyType_Type,0)
+ if (self.export.PythonName):
"@self.export.PythonName@", /*tp_name*/
= else:
@@ -257,8 +275,8 @@ PyTypeObject @self.export.Name@::Type = {
/* methods */
PyDestructor, /*tp_dealloc*/
0, /*tp_print*/
__getattr, /*tp_getattr*/
__setattr, /*tp_setattr*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
__repr, /*tp_repr*/
+ if (self.export.NumberProtocol):
@@ -275,20 +293,24 @@ PyTypeObject @self.export.Name@::Type = {
0, /*tp_hash*/
0, /*tp_call */
0, /*tp_str */
0, /*tp_getattro*/
0, /*tp_setattro*/
__getattro, /*tp_getattro*/
__setattro, /*tp_setattro*/
/* --- 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
+ if (self.export.RichCompare and self.export.NumberProtocol):
Py_TPFLAGS_HAVE_CLASS|Py_TPFLAGS_HAVE_RICHCOMPARE|Py_TPFLAGS_CHECKTYPES, /*tp_flags */
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_RICHCOMPARE|Py_TPFLAGS_CHECKTYPES, /*tp_flags */
= elif (self.export.RichCompare):
Py_TPFLAGS_HAVE_CLASS|Py_TPFLAGS_HAVE_RICHCOMPARE, /*tp_flags */
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_RICHCOMPARE, /*tp_flags */
= elif (self.export.NumberProtocol):
Py_TPFLAGS_HAVE_CLASS|Py_TPFLAGS_CHECKTYPES, /*tp_flags */
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES, /*tp_flags */
= else:
Py_TPFLAGS_HAVE_CLASS, /*tp_flags */
Py_TPFLAGS_DEFAULT, /*tp_flags */
-
#endif
"@self.export.Documentation.UserDocu.replace('\\n','\\\\n\\"\\n \\"')@", /*tp_doc */
0, /*tp_traverse */
0, /*tp_clear */
@@ -320,6 +342,9 @@ PyTypeObject @self.export.Name@::Type = {
0, /*tp_weaklist */
0, /*tp_del */
0 /*tp_version_tag */
#if PY_MAJOR_VERSION >= 3
,0 /*tp_finalize */
#endif
};
/// Methods structure of @self.export.Name@
@@ -343,7 +368,9 @@ PyNumberMethods @self.export.Name@::Number[] = { {
number_add_handler,
number_subtract_handler,
number_multiply_handler,
#if PY_MAJOR_VERSION < 3
number_divide_handler,
#endif
number_remainder_handler,
number_divmod_handler,
number_power_handler,
@@ -357,12 +384,20 @@ PyNumberMethods @self.export.Name@::Number[] = { {
number_and_handler,
number_xor_handler,
number_or_handler,
#if PY_MAJOR_VERSION < 3
number_coerce_handler,
#endif
number_int_handler,
#if PY_MAJOR_VERSION < 3
number_long_handler,
#else
0,
#endif
number_float_handler,
#if PY_MAJOR_VERSION < 3
number_oct_handler,
number_hex_handler,
#endif
NULL,
NULL,
NULL,
@@ -379,6 +414,9 @@ PyNumberMethods @self.export.Name@::Number[] = { {
NULL,
NULL,
NULL
#if PY_MAJOR_VERSION >= 3
,NULL /*nb_inplace_matrix_multiply*/
#endif
} };
-
@@ -674,8 +712,14 @@ PyObject *@self.export.Name@::_repr(void)
//--------------------------------------------------------------------------
// @self.export.Name@ Attributes
//--------------------------------------------------------------------------
PyObject *@self.export.Name@::_getattr(char *attr) // __getattr__ function: note only need to handle new state
PyObject *@self.export.Name@::_getattro(PyObject *attro) // __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);
@@ -694,7 +738,7 @@ PyObject *@self.export.Name@::_getattr(char *attr) // __getattr__ function: n
catch(const std::exception& e) // catch other c++ exceptions
{
std::string str;
str += "FC++ exception thrown (";
str += "C++ exception thrown (";
str += e.what();
str += ")";
Base::Console().Error(str.c_str());
@@ -729,20 +773,26 @@ PyObject *@self.export.Name@::_getattr(char *attr) // __getattr__ function: n
}
#endif // DONT_CATCH_CXX_EXCEPTIONS
PyObject *rvalue = Py_FindMethod(Methods, this, attr);
if (rvalue == NULL)
{
PyErr_Clear();
return @self.export.Father@::_getattr(attr);
}
else
{
return rvalue;
PyMethodDef *ml = Methods;
for (; ml->ml_name != NULL; ml++) {
if (attr[0] == ml->ml_name[0] &&
strcmp(attr+1, ml->ml_name+1) == 0)
return PyCFunction_New(ml, this);
}
PyErr_Clear();
return @self.export.Father@::_getattro(attro);
}
int @self.export.Name@::_setattr(char *attr, PyObject *value) // __setattr__ function: note only need to handle new state
int @self.export.Name@::_setattro(PyObject *attro, 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);
@@ -768,7 +818,7 @@ int @self.export.Name@::_setattr(char *attr, PyObject *value) // __setattr__ fun
catch(const std::exception& e) // catch other c++ exceptions
{
std::string str;
str += "FC++ exception thrown (";
str += "C++ exception thrown (";
str += e.what();
str += ")";
Base::Console().Error(str.c_str());
@@ -802,7 +852,7 @@ int @self.export.Name@::_setattr(char *attr, PyObject *value) // __setattr__ fun
}
#endif // DONT_CATCH_CXX_EXCEPTIONS
return @self.export.Father@::_setattr(attr, value);
return @self.export.Father@::_setattro(attro, value);
}
-