#! python # SPDX-License-Identifier: LGPL-2.1-or-later # (c) 2006 Juergen Riegel from . import template import os, sys import model.generateModel_Module import model.generateTools def compareFiles(file1, file2): """Compares two files and prints the differences if they are not equal.""" # Check if files exist for file in (file1, file2): if not os.path.exists(file): raise FileNotFoundError(f"File not found: {file}") # Read file contents with open(file1, "r", encoding="utf-8") as f1, open(file2, "r", encoding="utf-8") as f2: lines1 = f1.readlines() lines2 = f2.readlines() # Compare and print differences import difflib diff = list(difflib.unified_diff(lines1, lines2, fromfile=file1, tofile=file2, lineterm="")) if diff: error = "Files are not equal.\n\n" error += "Diff:\n\n" error += "".join(diff) raise ValueError(error) class TemplateClassPyExport(template.ModelTemplate): def Generate(self): # self.ParentNamespace = "Base" # self.Namespace = "Base" encoding = sys.getfilesystemencoding() exportName = self.export.Name inputDir = self.inputDir outputDir = self.outputDir def escapeString(s, indent=4): if not s: return None """Escapes a string for use as literal in C++ code""" s = s.strip() # This allows UserDocu-tags on their own lines without adding whitespace s = s.replace("\\", "\\\\") s = s.replace('"', '\\"') s = s.replace("\n", f'\\n"\n{" "*indent}"') return s print("TemplateClassPyExport", outputDir + exportName) # Create the subdir it necessary subpath = os.path.dirname(outputDir + exportName) if not os.path.exists(subpath): os.makedirs(subpath) # Imp.cpp must not exist, neither in outputDir nor in inputDir outputImp = outputDir + exportName + "Imp.cpp" if not os.path.exists(outputImp): if not os.path.exists(inputDir + exportName + "Imp.cpp"): file = open(outputImp, "wb") print("TemplateClassPyExport", "TemplateImplement", file.name) model.generateTools.replace(self.TemplateImplement, locals(), file) file.close() outputCpp = outputDir + exportName + ".cpp" with open(outputCpp, "wb") as file: print("TemplateClassPyExport", "TemplateModule", file.name) model.generateTools.replace(self.TemplateModule, locals(), file) outputHeader = outputDir + exportName + ".h" with open(outputHeader, "wb") as file: print("TemplateClassPyExport", "TemplateHeader", file.name) model.generateTools.replace(self.TemplateHeader, locals(), file) # file.write( model.generateTools.replace(self.Template,locals())) def Compare(self): """ Compares the Python generated files to the previously generated XML files. This exists temporarily while the XML files are migrated to Python to guarantee consistency. """ exportName = self.export.Name inputDir = self.inputDir outputDir = self.outputDir if not os.path.exists(inputDir + exportName + "Imp.cpp"): outputImpXml = outputDir + exportName + "Imp.cpp" outputImpPy = outputDir + exportName + "Imp.cpp" compareFiles(outputImpXml, outputImpPy) outputHeaderXml = outputDir + exportName + ".h" outputHeaderPy = outputDir + exportName + ".h" compareFiles(outputHeaderXml, outputHeaderPy) outputCppXml = outputDir + exportName + ".cpp" outputCppPy = outputDir + exportName + ".cpp" compareFiles(outputCppXml, outputCppPy) TemplateHeader = """ // This file is generated by src/Tools/generateTemplates/templateClassPyExport.py out of the XML file // Every change you make here gets lost in the next full rebuild! #ifndef @self.export.Namespace.upper().replace("::", "_")@_@self.export.Name.upper()@_H #define @self.export.Namespace.upper().replace("::", "_")@_@self.export.Name.upper()@_H #include #include <@self.export.FatherInclude@> #include <@self.export.Include@> #include + if(self.export.ForwardDeclarations != ""): // Forward declarations @self.export.ForwardDeclarations@ - namespace @self.export.Namespace.replace("::"," { namespace ")@ { //=========================================================================== // @self.export.Name@ - Python wrapper //=========================================================================== /** The python export class for @self.export.Twin@ */ class @self.export.Namespace.replace("::","_")@Export @self.export.Name@ : public @self.export.FatherNamespace@::@self.export.Father@ { protected: ~@self.export.Name@() override; public: static PyTypeObject Type; static PyMethodDef Methods[]; + if (self.export.NumberProtocol): static PyNumberMethods Number[]; - + if (self.export.Sequence): static PySequenceMethods Sequence[]; static PyMappingMethods Mapping[]; - + if (self.export.RichCompare): static PyObject * richCompare(PyObject *v, PyObject *w, int op); - + if (self.export.DescriptorGetter): static PyObject* descriptorGetter(PyObject* self, PyObject* obj, PyObject* type); - + if (self.export.DescriptorSetter): static int descriptorSetter(PyObject* self, PyObject* obj, PyObject* value); - static PyGetSetDef GetterSetter[]; PyTypeObject *GetType() const override {return &Type;} public: @self.export.Name@(@self.export.TwinPointer@ *pcObject, PyTypeObject *T = &Type); static PyObject *PyMake(PyTypeObject *, PyObject *, PyObject *); int PyInit(PyObject* args, PyObject*k) override; + if (self.export.Initialization): int initialization(); int finalization(); - using PointerType = @self.export.TwinPointer@*; PyObject *_repr() override; // the representation std::string representation() const; /** @name callbacks and implementers for the python object methods */ //@{ + for i in self.export.Methode: + if i.Keyword: /// callback for the @i.Name@() method static PyObject * staticCallback_@i.Name@ (PyObject *self, PyObject *args, PyObject *kwd); + if i.Static: /// implementer for the @i.Name@() method static PyObject* @i.Name@(PyObject *args, PyObject *kwd); = elif i.Class: /// implementer for the @i.Name@() method static PyObject* @i.Name@(PyObject *self, PyObject *args, PyObject *kwd); = elif i.Const: /// implementer for the @i.Name@() method PyObject* @i.Name@(PyObject *args, PyObject *kwd) const; = else: /// implementer for the @i.Name@() method PyObject* @i.Name@(PyObject *args, PyObject *kwd); - = elif i.NoArgs: /// callback for the @i.Name@() method static PyObject * staticCallback_@i.Name@ (PyObject *self, PyObject *args); + if i.Static: /// implementer for the @i.Name@() method static PyObject* @i.Name@(); = elif i.Class: /// implementer for the @i.Name@() method static PyObject* @i.Name@(PyObject *self); = elif i.Const: /// implementer for the @i.Name@() method PyObject* @i.Name@() const; = else: /// implementer for the @i.Name@() method PyObject* @i.Name@(); - = else: /// callback for the @i.Name@() method static PyObject * staticCallback_@i.Name@ (PyObject *self, PyObject *args); + if i.Static: /// implementer for the @i.Name@() method static PyObject* @i.Name@(PyObject *args); = elif i.Class: /// implementer for the @i.Name@() method static PyObject* @i.Name@(PyObject *self, PyObject *args); = elif i.Const: /// implementer for the @i.Name@() method PyObject* @i.Name@(PyObject *args) const; = else: /// implementer for the @i.Name@() method PyObject* @i.Name@(PyObject *args); - - - //@} + if (self.export.NumberProtocol): /** @name callbacks and implementers for the python object number protocol */ //@{ /// callback for the number_add_handler static PyObject * number_add_handler (PyObject *self, PyObject *other); /// callback for the number_subtract_handler static PyObject * number_subtract_handler (PyObject *self, PyObject *other); /// callback for the number_multiply_handler static PyObject * number_multiply_handler (PyObject *self, PyObject *other); /// callback for the number_divide_handler static PyObject * number_divide_handler (PyObject *self, PyObject *other); /// callback for the number_remainder_handler static PyObject * number_remainder_handler (PyObject *self, PyObject *other); /// callback for the number_divmod_handler static PyObject * number_divmod_handler (PyObject *self, PyObject *other); /// callback for the number_power_handler static PyObject * number_power_handler (PyObject *self, PyObject *other, PyObject *modulo); /// callback for the number_negative_handler static PyObject * number_negative_handler (PyObject *self); /// callback for the number_positive_handler static PyObject * number_positive_handler (PyObject *self); /// callback for the number_absolute_handler static PyObject * number_absolute_handler (PyObject *self); /// callback for the number_nonzero_handler static int number_nonzero_handler (PyObject *self); /// callback for the number_invert_handler static PyObject * number_invert_handler (PyObject *self); /// callback for the number_lshift_handler static PyObject * number_lshift_handler (PyObject *self, PyObject *other); /// callback for the number_rshift_handler static PyObject * number_rshift_handler (PyObject *self, PyObject *other); /// callback for the number_and_handler static PyObject * number_and_handler (PyObject *self, PyObject *other); /// callback for the number_xor_handler static PyObject * number_xor_handler (PyObject *self, PyObject *other); /// callback for the number_or_handler static PyObject * number_or_handler (PyObject *self, PyObject *other); /// callback for the number_int_handler static PyObject * number_int_handler (PyObject *self); /// callback for the number_float_handler static PyObject * number_float_handler (PyObject *self); //@} - + if (self.export.Sequence): /** @name callbacks and implementers for the python object sequence protocol */ //@{ + if (self.export.Sequence.sq_length): static Py_ssize_t sequence_length(PyObject *); - + if (self.export.Sequence.sq_concat): static PyObject* sequence_concat(PyObject *, PyObject *); - + if (self.export.Sequence.sq_repeat): static PyObject * sequence_repeat(PyObject *, Py_ssize_t); - + if (self.export.Sequence.sq_item): static PyObject * sequence_item(PyObject *, Py_ssize_t); - + if (self.export.Sequence.mp_subscript): static PyObject * mapping_subscript(PyObject *, PyObject *); - + if (self.export.Sequence.sq_ass_item): static int sequence_ass_item(PyObject *, Py_ssize_t, PyObject *); - + if (self.export.Sequence.mp_ass_subscript): static int mapping_ass_subscript(PyObject *, PyObject *, PyObject *); - + if (self.export.Sequence.sq_contains): static int sequence_contains(PyObject *, PyObject *); - + if (self.export.Sequence.sq_inplace_concat): static PyObject* sequence_inplace_concat(PyObject *, PyObject *); - + if (self.export.Sequence.sq_inplace_repeat): static PyObject * sequence_inplace_repeat(PyObject *, Py_ssize_t); - //@} - /** @name callbacks and implementers for the python object attributes */ //@{ + for i in self.export.Attribute: ///getter callback for the @i.Name@ attribute static PyObject * staticCallback_get@i.Name@ (PyObject *self, void *closure); /// getter for the @i.Name@ attribute Py::@i.Parameter.Type@ get@i.Name@() const; /// setter callback for the @i.Name@ attribute static int staticCallback_set@i.Name@ (PyObject *self, PyObject *value, void *closure); + if (i.ReadOnly): // no setter method, @i.Name@ is read only! = else: /// setter for the @i.Name@ attribute void set@i.Name@(Py::@i.Parameter.Type@ arg); - - //@} + if(self.export.CustomAttributes is not None): /// getter method for special attributes (e.g. dynamic ones) PyObject *getCustomAttributes(const char* attr) const; /// setter for special attributes (e.g. dynamic ones) /// Output: Success=1, Failure=-1, Ignore=0 int setCustomAttributes(const char* attr, PyObject *obj); PyObject *_getattr(const char *attr) override; // __getattr__ function int _setattr(const char *attr, PyObject *value) override; // __setattr__ function - /// getter for the object handled by this class @self.export.TwinPointer@ *get@self.export.Twin@Ptr() const; @self.export.TwinPointer@ *getTwinPtr() const; + if(self.export.ClassDeclarations != ""): /** @name additional declarations and methods for the wrapper class */ //@{ @self.export.ClassDeclarations@ //@} - }; @"}"*len(self.export.Namespace.split("::"))@ //namespace @self.export.Namespace@ #endif // @self.export.Namespace.upper().replace("::", "_")@_@self.export.Name.upper()@_H """ TemplateModule = """ // This file is generated by src/Tools/generateTemplates/templateClassPyExport.py out of the .XML file // Every change you make here gets lost in the next full rebuild! // This File is normally built as an include in @self.export.Name@Imp.cpp! It's not intended to be in a project! #include #include #include #include #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif using Base::streq; using namespace @self.export.Namespace@; #if defined(__GNUC__) #pragma GCC diagnostic push // Ignore -Wmissing-field-initializers (GCC only): // - C++20 guarantees omitted fields are zero-initialized. // - Python C API changes fields across versions. // - Clang does not warn; GCC does unnecessarily. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96868 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif // __GNUC__ /// Type structure of @self.export.Name@ PyTypeObject @self.export.Name@::Type = { .ob_base = PyVarObject_HEAD_INIT(&PyType_Type,0) + if (self.export.PythonName): .tp_name = "@self.export.PythonName@", = else: .tp_name = "@self.export.Namespace@.@self.export.Twin@", - .tp_basicsize = sizeof(@self.export.Name@), .tp_itemsize = 0, /* methods */ .tp_dealloc = PyDestructor, .tp_repr = __repr, + if (self.export.NumberProtocol): .tp_as_number = @self.export.Namespace@::@self.export.Name@::Number, - + if (self.export.Sequence): .tp_as_sequence = @self.export.Namespace@::@self.export.Name@::Sequence, .tp_as_mapping = @self.export.Namespace@::@self.export.Name@::Mapping, - .tp_getattro = __getattro, .tp_setattro = __setattro, /* --- Flags to define presence of optional/expanded features */ .tp_flags = Py_TPFLAGS_BASETYPE|Py_TPFLAGS_DEFAULT, .tp_doc = "@escapeString(self.export.Documentation.UserDocu, indent=4)@", + if (self.export.RichCompare): .tp_richcompare = @self.export.Namespace@::@self.export.Name@::richCompare, - .tp_methods = @self.export.Namespace@::@self.export.Name@::Methods, .tp_getset = @self.export.Namespace@::@self.export.Name@::GetterSetter, .tp_base = &@self.export.FatherNamespace@::@self.export.Father@::Type, + if (self.export.DescriptorGetter): .tp_descr_get = @self.export.Namespace@::@self.export.Name@::descriptorGetter, - + if (self.export.DescriptorSetter): .tp_descr_set = @self.export.Namespace@::@self.export.Name@::descriptorSetter, - .tp_init = __PyInit, .tp_new = @self.export.Namespace@::@self.export.Name@::PyMake }; #if defined(__GNUC__) #pragma GCC diagnostic pop #endif // __GNUC__ /// Methods structure of @self.export.Name@ PyMethodDef @self.export.Name@::Methods[] = { + for i in self.export.Methode: {"@i.Name@", + if i.Keyword: + if i.Class: reinterpret_cast(reinterpret_cast( staticCallback_@i.Name@ )), METH_VARARGS|METH_KEYWORDS|METH_CLASS, = elif i.Static: reinterpret_cast(reinterpret_cast( staticCallback_@i.Name@ )), METH_VARARGS|METH_KEYWORDS|METH_STATIC, = else: reinterpret_cast(reinterpret_cast( staticCallback_@i.Name@ )), METH_VARARGS|METH_KEYWORDS, - = elif i.NoArgs: + if i.Class: reinterpret_cast(reinterpret_cast( staticCallback_@i.Name@ )), METH_NOARGS|METH_CLASS, = elif i.Static: reinterpret_cast(reinterpret_cast( staticCallback_@i.Name@ )), METH_NOARGS|METH_STATIC, = else: reinterpret_cast( staticCallback_@i.Name@ ), METH_NOARGS, - = elif i.Class: reinterpret_cast(reinterpret_cast( staticCallback_@i.Name@ )), METH_VARARGS|METH_CLASS, = elif i.Static: reinterpret_cast(reinterpret_cast( staticCallback_@i.Name@ )), METH_VARARGS|METH_STATIC, = else: reinterpret_cast( staticCallback_@i.Name@ ), METH_VARARGS, - "@escapeString(i.Documentation.UserDocu, indent=8)@" }, - {nullptr, nullptr, 0, nullptr} /* Sentinel */ }; + if (self.export.NumberProtocol): PyNumberMethods @self.export.Name@::Number[] = { { number_add_handler, number_subtract_handler, number_multiply_handler, number_remainder_handler, number_divmod_handler, number_power_handler, number_negative_handler, number_positive_handler, number_absolute_handler, number_nonzero_handler, number_invert_handler, number_lshift_handler, number_rshift_handler, number_and_handler, number_xor_handler, number_or_handler, number_int_handler, nullptr, number_float_handler, nullptr, /*nb_inplace_add*/ nullptr, /*nb_inplace_subtract*/ nullptr, /*nb_inplace_multiply*/ nullptr, /*nb_inplace_remainder*/ nullptr, /*nb_inplace_power*/ nullptr, /*nb_inplace_lshift*/ nullptr, /*nb_inplace_rshift*/ nullptr, /*nb_inplace_and*/ nullptr, /*nb_inplace_xor*/ nullptr, /*nb_inplace_or*/ nullptr, /*nb_floor_divide*/ number_divide_handler, /*nb_true_divide*/ nullptr, /*nb_inplace_floor_divide*/ nullptr, /*nb_inplace_true_divide*/ nullptr /*nb_index*/ ,nullptr /*nb_matrix_multiply*/ ,nullptr /*nb_inplace_matrix_multiply*/ } }; - + if (self.export.Sequence): PySequenceMethods @self.export.Name@::Sequence[] = { { + if (self.export.Sequence.sq_length): sequence_length, = else: nullptr, - + if (self.export.Sequence.sq_concat): sequence_concat, = else: nullptr, - + if (self.export.Sequence.sq_repeat): sequence_repeat, = else: nullptr, - + if (self.export.Sequence.sq_item): sequence_item, = else: nullptr, - nullptr, + if (self.export.Sequence.sq_ass_item): sequence_ass_item, = else: nullptr, - nullptr, + if (self.export.Sequence.sq_contains): sequence_contains, = else: nullptr, - + if (self.export.Sequence.sq_inplace_concat): sequence_inplace_concat, = else: nullptr, - + if (self.export.Sequence.sq_inplace_repeat): sequence_inplace_repeat, = else: nullptr - } }; PyMappingMethods @self.export.Name@::Mapping[] = { { + if (self.export.Sequence.sq_length): sequence_length, = else: nullptr, - + if (self.export.Sequence.mp_subscript): mapping_subscript, = else: nullptr, - + if (self.export.Sequence.mp_ass_subscript): mapping_ass_subscript, = else: nullptr, - } }; - /// Attribute structure of @self.export.Name@ PyGetSetDef @self.export.Name@::GetterSetter[] = { + for i in self.export.Attribute: {"@i.Name@", (getter) staticCallback_get@i.Name@, (setter) staticCallback_set@i.Name@, "@escapeString(i.Documentation.UserDocu, indent=8)@", nullptr }, - {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */ }; + for i in self.export.Methode: // @i.Name@() callback and implementer // PyObject* @self.export.Name@::@i.Name@(PyObject *args){}; // has to be implemented in @self.export.Name@Imp.cpp + if i.Keyword: PyObject * @self.export.Name@::staticCallback_@i.Name@ (PyObject *self, PyObject *args, PyObject * kwd) = elif i.NoArgs: PyObject * @self.export.Name@::staticCallback_@i.Name@ (PyObject *self, PyObject * Py_UNUSED(args)) = else: PyObject * @self.export.Name@::staticCallback_@i.Name@ (PyObject *self, PyObject *args) - { + if not i.Static and not i.Class: // make sure that not a null pointer is passed if (!self) { PyErr_SetString(PyExc_TypeError, "descriptor '@i.Name@' of '@self.export.Namespace@.@self.export.Twin@' object needs an argument"); return nullptr; } // test if twin object isn't already 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 nullptr; } + if (not i.Const): // 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 nullptr; } - - try { // catches all exceptions coming up from c++ and generate a python exception + if i.Keyword: + if i.Static: (void)self; PyObject* ret = @self.export.Name@::@i.Name@(args, kwd); = elif i.Class: PyObject* ret = @self.export.Name@::@i.Name@(self, args, kwd); = else: PyObject* ret = static_cast<@self.export.Name@*>(self)->@i.Name@(args, kwd); - = elif i.NoArgs: + if i.Static: (void)self; PyObject* ret = @self.export.Name@::@i.Name@(); = elif i.Class: PyObject* ret = @self.export.Name@::@i.Name@(self); = else: PyObject* ret = static_cast<@self.export.Name@*>(self)->@i.Name@(); - = else: + if i.Static: (void)self; PyObject* ret = @self.export.Name@::@i.Name@(args); = elif i.Class: PyObject* ret = @self.export.Name@::@i.Name@(self, args); = else: PyObject* ret = static_cast<@self.export.Name@*>(self)->@i.Name@(args); - - + if not i.Static and not i.Class: + if (not i.Const): if (ret != nullptr) static_cast<@self.export.Name@*>(self)->startNotify(); - - return ret; } // Please sync the following catch implementation with PY_CATCH catch(const Base::Exception& e) { e.setPyException(); return nullptr; } catch(const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } catch(const Py::Exception&) { // The exception text is already set return nullptr; } #ifndef DONT_CATCH_CXX_EXCEPTIONS catch(...) { PyErr_SetString(Base::PyExc_FC_GeneralError, "Unknown C++ exception"); return nullptr; } #endif } - + for i in self.export.Attribute: // @i.Name@() callback and implementer // PyObject* @self.export.Name@::@i.Name@(PyObject *args){}; // has to be implemented in @self.export.Name@Imp.cpp PyObject * @self.export.Name@::staticCallback_get@i.Name@ (PyObject *self, void * /*closure*/) { 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 nullptr; } try { return Py::new_reference_to(static_cast<@self.export.Name@*>(self)->get@i.Name@()); } catch (const Py::Exception&) { // The exception text is already set return nullptr; } catch (...) { PyErr_SetString(Base::PyExc_FC_GeneralError, "Unknown exception while reading attribute '@i.Name@' of object '@self.export.Twin@'"); return nullptr; } } + if (i.ReadOnly): int @self.export.Name@::staticCallback_set@i.Name@ (PyObject *self, PyObject * /*value*/, void * /*closure*/) { 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 -1; } PyErr_SetString(PyExc_AttributeError, "Attribute '@i.Name@' of object '@self.export.Twin@' is read-only"); return -1; } = else: int @self.export.Name@::staticCallback_set@i.Name@ (PyObject *self, PyObject *value, void * /*closure*/) { 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 -1; } if (static_cast(self)->isConst()){ PyErr_SetString(PyExc_ReferenceError, "This object is immutable, you can not set any attribute or call a method"); return -1; } try { + if (i.Parameter.Type == "Float"): static_cast<@self.export.Name@*>(self)->set@i.Name@(Py::@i.Parameter.Type@(PyNumber_Float(value),true)); = else: static_cast<@self.export.Name@*>(self)->set@i.Name@(Py::@i.Parameter.Type@(value,false)); - return 0; } catch (const Py::Exception&) { // The exception text is already set return -1; } catch (...) { PyErr_SetString(Base::PyExc_FC_GeneralError, "Unknown exception while writing attribute '@i.Name@' of object '@self.export.Twin@'"); return -1; } } - - //-------------------------------------------------------------------------- // Constructor //-------------------------------------------------------------------------- @self.export.Name@::@self.export.Name@(@self.export.TwinPointer@ *pcObject, PyTypeObject *T) : @self.export.Father@(static_cast<@self.export.Father@::PointerType>(pcObject), T) { + if (self.export.Reference): pcObject->ref(); - + if (self.export.Initialization): initialization(); - + if (self.export.DisableNotify): this->setShouldNotify(false); - } + if not (self.export.Constructor): PyObject *@self.export.Name@::PyMake(PyTypeObject* /*type*/, PyObject* /*args*/, PyObject* /*kwds*/) { // never create such objects with the constructor PyErr_SetString(PyExc_RuntimeError, "You cannot create directly an instance of '@self.export.Name@'."); return nullptr; } int @self.export.Name@::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) { return 0; } - //-------------------------------------------------------------------------- // destructor //-------------------------------------------------------------------------- @self.export.Name@::~@self.export.Name@() // Everything handled in parent { + if (self.export.Reference): get@self.export.Twin@Ptr()->unref(); - + if (self.export.Delete): // delete the handled object when the PyObject dies @self.export.Name@::PointerType ptr = static_cast<@self.export.Name@::PointerType>(_pcTwinPointer); delete ptr; - + if (self.export.Initialization): finalization(); - } //-------------------------------------------------------------------------- // @self.export.Name@ representation //-------------------------------------------------------------------------- PyObject *@self.export.Name@::_repr() { return Py_BuildValue("s", representation().c_str()); } + if(self.export.CustomAttributes is not None): //-------------------------------------------------------------------------- // @self.export.Name@ Attributes //-------------------------------------------------------------------------- PyObject *@self.export.Name@::_getattr(const char *attr) // __getattr__ function: note only need to handle new state { try { // getter method for special Attributes (e.g. dynamic ones) PyObject *r = getCustomAttributes(attr); if(r) return r; } // Please sync the following catch implementation with PY_CATCH catch(const Base::Exception& e) { e.setPyException(); return nullptr; } catch(const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } catch(const Py::Exception&) { // The exception text is already set return nullptr; } #ifndef DONT_CATCH_CXX_EXCEPTIONS catch(...) { PyErr_SetString(Base::PyExc_FC_GeneralError,"Unknown C++ exception"); return nullptr; } #endif PyMethodDef *ml = Methods; for (; ml->ml_name != nullptr; 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@::_getattr(attr); } int @self.export.Name@::_setattr(const char *attr, PyObject *value) // __setattr__ function: note only need to handle new state { try { // setter for special Attributes (e.g. dynamic ones) int r = setCustomAttributes(attr, value); // r = 1: handled // r = -1: error // r = 0: ignore if (r == 1) return 0; else if (r == -1) return -1; } // Please sync the following catch implementation with PY_CATCH catch(const Base::Exception& e) { e.setPyException(); return -1; } catch(const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return -1; } catch(const Py::Exception&) { // The exception text is already set return -1; } #ifndef DONT_CATCH_CXX_EXCEPTIONS catch(...) { PyErr_SetString(Base::PyExc_FC_GeneralError, "Unknown C++ exception"); return -1; } #endif return @self.export.Father@::_setattr(attr, value); } - @self.export.TwinPointer@ *@self.export.Name@::get@self.export.Twin@Ptr() const { return static_cast<@self.export.TwinPointer@ *>(_pcTwinPointer); } @self.export.TwinPointer@ *@self.export.Name@::getTwinPtr() const { return get@self.export.Twin@Ptr(); } #if defined(__clang__) # pragma clang diagnostic pop #endif #if 0 /* From here on come the methods you have to implement, but NOT in this module. Implement in @self.export.Name@Imp.cpp! This prototypes * are just for convenience when you add a new method. */ + if (self.export.Constructor): PyObject *@self.export.Name@::PyMake(PyTypeObject* /*type*/, PyObject* /*args*/, PyObject* /*kwds*/) { // create a new instance of @self.export.Name@ and the Twin object return new @self.export.Name@(new @self.export.TwinPointer@); } // constructor method int @self.export.Name@::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) { return 0; } - + if (self.export.Initialization): int @self.export.Name@::initialization() { return 0; } int @self.export.Name@::finalization() { return 0; } - // returns a string which represents the object e.g. when printed in python std::string @self.export.Name@::representation() const { return {"<@self.export.Twin@ object>"}; } + for i in self.export.Methode: + if i.Keyword: + if i.Class: PyObject* @self.export.Name@::@i.Name@(PyObject *self, PyObject *args, PyObject *kwds) = else: PyObject* @self.export.Name@::@i.Name@(PyObject *args, PyObject *kwds) - = elif i.NoArgs: + if i.Class: PyObject* @self.export.Name@::@i.Name@(PyObject *self) = else: PyObject* @self.export.Name@::@i.Name@() - = else: + if i.Class: PyObject* @self.export.Name@::@i.Name@(PyObject *self, PyObject *args) = else: PyObject* @self.export.Name@::@i.Name@(PyObject *args) - - { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.NumberProtocol): PyObject* @self.export.Name@::number_add_handler(PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject* @self.export.Name@::number_subtract_handler(PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject* @self.export.Name@::number_multiply_handler(PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_divide_handler (PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_remainder_handler (PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_divmod_handler (PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_power_handler (PyObject* /*self*/, PyObject* /*other*/, PyObject* /*modulo*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_negative_handler (PyObject* /*self*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_positive_handler (PyObject* /*self*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_absolute_handler (PyObject* /*self*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } int @self.export.Name@::number_nonzero_handler (PyObject* /*self*/) { return 1; } PyObject * @self.export.Name@::number_invert_handler (PyObject* /*self*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_lshift_handler (PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_rshift_handler (PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_and_handler (PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_xor_handler (PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_or_handler (PyObject* /*self*/, PyObject* /*other*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } int @self.export.Name@::number_coerce_handler (PyObject** /*self*/, PyObject** /*other*/) { return 1; } PyObject * @self.export.Name@::number_int_handler (PyObject* /*self*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_long_handler (PyObject* /*self*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_float_handler (PyObject* /*self*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_oct_handler (PyObject* /*self*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_hex_handler (PyObject* /*self*/) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } - + if (self.export.Sequence): + if (self.export.Sequence.sq_length): Py_ssize_t @self.export.Name@::sequence_length(PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return -1; } - + if (self.export.Sequence.sq_concat): PyObject* @self.export.Name@::sequence_concat(PyObject *, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.Sequence.sq_repeat): PyObject * @self.export.Name@::sequence_repeat(PyObject *, Py_ssize_t) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.Sequence.sq_item): PyObject * @self.export.Name@::sequence_item(PyObject *, Py_ssize_t) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.Sequence.mp_subscript): PyObject * @self.export.Name@::mapping_subscript(PyObject *, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.Sequence.sq_ass_item): int @self.export.Name@::sequence_ass_item(PyObject *, Py_ssize_t, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return -1; } - + if (self.export.Sequence.mp_ass_subscript): int @self.export.Name@::mapping_ass_subscript(PyObject *, PyObject *, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return -1; } - + if (self.export.Sequence.sq_contains): int @self.export.Name@::sequence_contains(PyObject *, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return -1; } - + if (self.export.Sequence.sq_inplace_concat): PyObject* @self.export.Name@::sequence_inplace_concat(PyObject *, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.Sequence.sq_inplace_repeat): PyObject * @self.export.Name@::sequence_inplace_repeat(PyObject *, Py_ssize_t) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - - + if (self.export.RichCompare): PyObject* @self.export.Name@::richCompare(PyObject *v, PyObject *w, int op) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + for i in self.export.Attribute: Py::@i.Parameter.Type@ @self.export.Name@::get@i.Name@() const { //return Py::@i.Parameter.Type@(); throw Py::AttributeError("Not yet implemented"); } + if (i.ReadOnly): = else: void @self.export.Name@::set@i.Name@(Py::@i.Parameter.Type@ arg) { throw Py::AttributeError("Not yet implemented"); } - - + if(self.export.CustomAttributes is not None): PyObject *@self.export.Name@::getCustomAttributes(const char* /*attr*/) const { return nullptr; } int @self.export.Name@::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } - + if (self.export.DescriptorGetter): PyObject* @self.export.Name@::descriptorGetter(PyObject* self, PyObject* obj, PyObject* type) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.DescriptorSetter): int @self.export.Name@::descriptorSetter(PyObject* self, PyObject* obj, PyObject* value) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return -1; } - #endif """ # Here's the template for the user part of the implementation. This does NOT get overridden if it already exists. TemplateImplement = """ #include "@self.export.Include@" // inclusion of the generated files (generated out of @self.export.Name@.xml) #include "@self.export.Name@.h" #include "@self.export.Name@.cpp" using namespace @self.export.Namespace@; // returns a string which represents the object e.g. when printed in python std::string @self.export.Name@::representation() const { return {"<@self.export.Twin@ object>"}; } + if (self.export.Constructor): PyObject *@self.export.Name@::PyMake(PyTypeObject* /*type*/, PyObject* /*args*/, PyObject* /*kwds*/) { // create a new instance of @self.export.Name@ and the Twin object return new @self.export.Name@(new @self.export.TwinPointer@); } // constructor method int @self.export.Name@::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) { return 0; } - + if (self.export.Initialization): int @self.export.Name@::initialization() { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return 0; } int @self.export.Name@::finalization() { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return 0; } - + for i in self.export.Methode: + if i.Keyword: + if i.Class: PyObject* @self.export.Name@::@i.Name@(PyObject * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/) = else: PyObject* @self.export.Name@::@i.Name@(PyObject * /*args*/, PyObject * /*kwds*/) - = elif i.NoArgs: + if i.Class: PyObject* @self.export.Name@::@i.Name@(PyObject * /*self*/) = else: PyObject* @self.export.Name@::@i.Name@() - = else: + if i.Class: PyObject* @self.export.Name@::@i.Name@(PyObject * /*self*/, PyObject * /*args*/) = else: PyObject* @self.export.Name@::@i.Name@(PyObject * /*args*/) - - { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.NumberProtocol): PyObject* @self.export.Name@::number_add_handler(PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject* @self.export.Name@::number_subtract_handler(PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject* @self.export.Name@::number_multiply_handler(PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_divide_handler (PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_remainder_handler (PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_divmod_handler (PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_power_handler (PyObject *self, PyObject *other, PyObject *modulo) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_negative_handler (PyObject *self) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_positive_handler (PyObject *self) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_absolute_handler (PyObject *self) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } int @self.export.Name@::number_nonzero_handler (PyObject *self) { return 1; } PyObject * @self.export.Name@::number_invert_handler (PyObject *self) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_lshift_handler (PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_rshift_handler (PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_and_handler (PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_xor_handler (PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_or_handler (PyObject *self, PyObject *other) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } int @self.export.Name@::number_coerce_handler (PyObject **self, PyObject **other) { return 1; } PyObject * @self.export.Name@::number_int_handler (PyObject *self) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_long_handler (PyObject *self) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_float_handler (PyObject *self) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_oct_handler (PyObject *self) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } PyObject * @self.export.Name@::number_hex_handler (PyObject *self) { PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); return nullptr; } - + if (self.export.Sequence): + if (self.export.Sequence.sq_length): Py_ssize_t @self.export.Name@::sequence_length(PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return -1; } - + if (self.export.Sequence.sq_concat): PyObject* @self.export.Name@::sequence_concat(PyObject *, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.Sequence.sq_repeat): PyObject * @self.export.Name@::sequence_repeat(PyObject *, Py_ssize_t) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.Sequence.sq_item): PyObject * @self.export.Name@::sequence_item(PyObject *, Py_ssize_t) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.Sequence.mp_subscript): PyObject * @self.export.Name@::mapping_subscript(PyObject *, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.Sequence.sq_ass_item): int @self.export.Name@::sequence_ass_item(PyObject *, Py_ssize_t, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return -1; } - + if (self.export.Sequence.mp_ass_subscript): int @self.export.Name@::mapping_ass_subscript(PyObject *, PyObject *, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return -1; } - + if (self.export.Sequence.sq_contains): int @self.export.Name@::sequence_contains(PyObject *, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return -1; } - + if (self.export.Sequence.sq_inplace_concat): PyObject* @self.export.Name@::sequence_inplace_concat(PyObject *, PyObject *) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.Sequence.sq_inplace_repeat): PyObject * @self.export.Name@::sequence_inplace_repeat(PyObject *, Py_ssize_t) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - - + if (self.export.RichCompare): PyObject* @self.export.Name@::richCompare(PyObject *v, PyObject *w, int op) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + for i in self.export.Attribute: Py::@i.Parameter.Type@ @self.export.Name@::get@i.Name@() const { //return Py::@i.Parameter.Type@(); throw Py::AttributeError("Not yet implemented"); } + if (i.ReadOnly): = else: void @self.export.Name@::set@i.Name@(Py::@i.Parameter.Type@ /*arg*/) { throw Py::AttributeError("Not yet implemented"); } - - + if(self.export.CustomAttributes is not None): PyObject *@self.export.Name@::getCustomAttributes(const char* /*attr*/) const { return nullptr; } int @self.export.Name@::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } - + if (self.export.DescriptorGetter): PyObject* @self.export.Name@::descriptorGetter(PyObject* self, PyObject* obj, PyObject* type) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return nullptr; } - + if (self.export.DescriptorSetter): int @self.export.Name@::descriptorSetter(PyObject* self, PyObject* obj, PyObject* value) { PyErr_SetString(PyExc_NotImplementedError, "Not yet implemented"); return -1; } - """