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