| 141 | } |
| 142 | |
| 143 | boost::python::object WrapperGarbageCollector::methodOverride( const char *name, PyTypeObject *wrappedType ) const |
| 144 | { |
| 145 | if( !m_pyObject ) |
| 146 | { |
| 147 | return boost::python::object(); |
| 148 | } |
| 149 | |
| 150 | // lookup the method on the python instance. this may |
| 151 | // or may not be an override. a new reference is returned |
| 152 | // so we must use a handle to manage it. |
| 153 | boost::python::handle<> methodFromInstance( |
| 154 | boost::python::allow_null( |
| 155 | PyObject_GetAttrString( |
| 156 | m_pyObject, |
| 157 | const_cast<char*>( name ) |
| 158 | ) |
| 159 | ) |
| 160 | ); |
| 161 | |
| 162 | if( !methodFromInstance || !PyMethod_Check( methodFromInstance.get() ) ) |
| 163 | { |
| 164 | // if the attribute lookup failed, an error will be set, and we |
| 165 | // need to clear it before returning. |
| 166 | PyErr_Clear(); |
| 167 | return boost::python::object(); |
| 168 | } |
| 169 | |
| 170 | // lookup the method defined by our type. a borrowed reference |
| 171 | // is returned so we don't need to use a handle to manage the |
| 172 | // reference count. |
| 173 | PyObject *methodFromType = PyDict_GetItemString( |
| 174 | wrappedType->tp_dict, const_cast<char*>( name ) |
| 175 | ); |
| 176 | |
| 177 | // if they're not the same then we have an override |
| 178 | if( methodFromType != ((PyMethodObject *)methodFromInstance.get())->im_func ) |
| 179 | { |
| 180 | return boost::python::object( methodFromInstance ); |
| 181 | } |
| 182 | |
| 183 | return boost::python::object(); |
| 184 | } |
no test coverage detected