| 113 | } |
| 114 | |
| 115 | PyObject* ExtensionContainerPy::getCustomAttributes(const char* attr) const |
| 116 | { |
| 117 | if (Base::streq(attr, "__dict__")) { |
| 118 | PyObject* dict = PyDict_New(); |
| 119 | PyObject* props = PropertyContainerPy::getCustomAttributes("__dict__"); |
| 120 | if (props && PyDict_Check(props)) { |
| 121 | PyDict_Merge(dict, props, 0); |
| 122 | Py_DECREF(props); |
| 123 | } |
| 124 | |
| 125 | ExtensionContainer::ExtensionIterator it = |
| 126 | this->getExtensionContainerPtr()->extensionBegin(); |
| 127 | for (; it != this->getExtensionContainerPtr()->extensionEnd(); ++it) { |
| 128 | // The PyTypeObject is shared by all instances of this type and therefore |
| 129 | // we have to add new methods only once. |
| 130 | PyObject* obj = (*it).second->getExtensionPyObject(); |
| 131 | PyTypeObject* tp = Py_TYPE(obj); |
| 132 | if (tp && tp->tp_dict) { |
| 133 | Py_XINCREF(tp->tp_dict); |
| 134 | PyDict_Merge(dict, tp->tp_dict, 0); |
| 135 | Py_XDECREF(tp->tp_dict); |
| 136 | } |
| 137 | Py_DECREF(obj); |
| 138 | } |
| 139 | |
| 140 | return dict; |
| 141 | } |
| 142 | // Search for the method called 'attr' in the extensions. If the search with |
| 143 | // Py_FindMethod is successful then a PyCFunction_New instance is returned |
| 144 | // with the PyObject pointer of the extension to make sure the method will |
| 145 | // be called for the correct instance. |
| 146 | PyObject* func = nullptr; |
| 147 | ExtensionContainer::ExtensionIterator it = this->getExtensionContainerPtr()->extensionBegin(); |
| 148 | for (; it != this->getExtensionContainerPtr()->extensionEnd(); ++it) { |
| 149 | // The PyTypeObject is shared by all instances of this type and therefore |
| 150 | // we have to add new methods only once. |
| 151 | PyObject* obj = (*it).second->getExtensionPyObject(); |
| 152 | PyObject* nameobj = PyUnicode_FromString(attr); |
| 153 | func = PyObject_GenericGetAttr(obj, nameobj); |
| 154 | Py_DECREF(nameobj); |
| 155 | Py_DECREF(obj); |
| 156 | if (func && PyCFunction_Check(func)) { |
| 157 | PyCFunctionObject* cfunc = reinterpret_cast<PyCFunctionObject*>(func); |
| 158 | |
| 159 | // OK, that's what we wanted |
| 160 | if (cfunc->m_self == obj) { |
| 161 | break; |
| 162 | } |
| 163 | // otherwise cleanup the result again |
| 164 | Py_DECREF(func); |
| 165 | func = nullptr; |
| 166 | } |
| 167 | PyErr_Clear(); // clear the error set inside Py_FindMethod |
| 168 | } |
| 169 | |
| 170 | return func; |
| 171 | } |
| 172 |
nothing calls this directly
no test coverage detected