# Pastebin Vwm5es6B PyObject *BindingManager::getOverride(const void *cptr, PyObject *nameCache[], const char *methodName) { SbkObject *wrapper = retrieveWrapper(cptr); // The refcount can be 0 if the object is dieing and someone called // a virtual method from the destructor if (!wrapper || reinterpret_cast(wrapper)->ob_refcnt == 0) return nullptr; // PYSIDE-1626: Touch the type to initiate switching early. SbkObjectType_UpdateFeature(Py_TYPE(wrapper)); int flag = currentSelectId(Py_TYPE(wrapper)); int propFlag = isdigit(methodName[0]) ? methodName[0] - '0' : 0; if ((flag & 0x02) != 0 && (propFlag & 3) != 0) { // PYSIDE-1019: Handle overriding with properties. // They cannot be overridden (make that sure by the metaclass). return nullptr; } bool is_snake = flag & 0x01; PyObject *pyMethodName = nameCache[is_snake]; // borrowed if (pyMethodName == nullptr) { if (propFlag) methodName += 2; // skip the propFlag and ':' pyMethodName = Shiboken::String::getSnakeCaseName(methodName, is_snake); nameCache[is_snake] = pyMethodName; } if (wrapper->ob_dict) { PyObject *method = PyDict_GetItem(wrapper->ob_dict, pyMethodName); if (method) { Py_INCREF(method); return method; } } PyObject *method = PyObject_GetAttr(reinterpret_cast(wrapper), pyMethodName); fprintf(stderr, "%s:%d %s\n", __FUNCTION__, __LINE__, Py_TYPE(method)->tp_name); PyObject *function = nullptr; // PYSIDE-1523: PyMethod_Check is not accepting compiled methods, we do this rather // crude check for them. if (method) { if (PyMethod_Check(method)) { if (PyMethod_GET_SELF(method) == reinterpret_cast(wrapper)) { function = PyMethod_GET_FUNCTION(method); } else { Py_DECREF(method); method = nullptr; } } else if (PyObject_HasAttr(method, PyName::im_self()) && PyObject_HasAttr(method, PyName::im_func())) { PyObject *im_self = PyObject_GetAttr(method, PyName::im_self()); // Not retaining a reference inline with what PyMethod_GET_SELF does. Py_DECREF(im_self); if (im_self == reinterpret_cast(wrapper)) { function = PyObject_GetAttr(method, PyName::im_func()); // Not retaining a reference inline with what PyMethod_GET_FUNCTION does. Py_DECREF(function); } else { Py_DECREF(method); method = nullptr; } } else { Py_DECREF(method); method = nullptr; } } if (method != nullptr) { PyObject *defaultMethod; PyObject *mro = Py_TYPE(wrapper)->tp_mro; int size = PyTuple_GET_SIZE(mro); // The first class in the mro (index 0) is the class being checked and it should not be tested. // The last class in the mro (size - 1) is the base Python object class which should not be tested also. for (int idx = 1; idx < size - 1; ++idx) { auto *parent = reinterpret_cast(PyTuple_GET_ITEM(mro, idx)); if (parent->tp_dict) { defaultMethod = PyDict_GetItem(parent->tp_dict, pyMethodName); if (defaultMethod && function != defaultMethod) return method; } } Py_DECREF(method); } return nullptr; }