PyAPI: support static & class methods for C RNA API methods

Previously the static/class flag was ignored,
always using class methods.
This commit is contained in:
Campbell Barton 2020-05-29 14:14:43 +10:00
parent 5510d5825b
commit e115b7b06d
2 changed files with 24 additions and 15 deletions

View File

@ -9040,32 +9040,41 @@ void pyrna_struct_type_extend_capi(struct StructRNA *srna,
struct PyMethodDef *method,
struct PyGetSetDef *getset)
{
PyObject *cls = pyrna_srna_Subtype(srna);
/* See 'add_methods' in Python's 'typeobject.c'. */
PyTypeObject *type = (PyTypeObject *)pyrna_srna_Subtype(srna);
PyObject *dict = type->tp_dict;
if (method != NULL) {
for (; method->ml_name != NULL; method++) {
PyObject *func = PyCFunction_New(method, NULL);
PyObject *args = PyTuple_New(1);
PyTuple_SET_ITEM(args, 0, func);
PyObject *classmethod = PyObject_CallObject((PyObject *)&PyClassMethod_Type, args);
PyObject *py_method;
PyObject_SetAttrString(cls, method->ml_name, classmethod);
if (method->ml_flags & METH_CLASS) {
PyObject *cfunc = PyCFunction_New(method, (PyObject *)type);
py_method = PyClassMethod_New(cfunc);
Py_DECREF(cfunc);
}
else {
/* Currently only static and class methods are used. */
BLI_assert(method->ml_flags & METH_STATIC);
py_method = PyCFunction_New(method, NULL);
}
Py_DECREF(classmethod);
Py_DECREF(args); /* Clears 'func' too. */
int err = PyDict_SetItemString(dict, method->ml_name, py_method);
Py_DECREF(py_method);
BLI_assert(!(err < 0));
UNUSED_VARS_NDEBUG(err);
}
}
if (getset != NULL) {
PyObject *dict = ((PyTypeObject *)cls)->tp_dict;
for (; getset->name != NULL; getset++) {
PyObject *descr = PyDescr_NewGetSet((PyTypeObject *)cls, getset);
PyObject *descr = PyDescr_NewGetSet(type, getset);
/* Ensure we're not overwriting anything that already exists. */
BLI_assert(PyDict_GetItem(dict, PyDescr_NAME(descr)) == NULL);
PyDict_SetItem(dict, PyDescr_NAME(descr), descr);
Py_DECREF(descr);
}
}
Py_DECREF(cls);
Py_DECREF(type);
}
/* Access to 'owner_id' internal global. */

View File

@ -86,11 +86,11 @@ static int pyrna_WindowManager_clipboard_set(PyObject *UNUSED(self),
static struct PyMethodDef pyrna_windowmanager_methods[] = {
{"draw_cursor_add",
(PyCFunction)pyrna_callback_classmethod_add,
METH_VARARGS | METH_STATIC,
METH_VARARGS | METH_CLASS,
""},
{"draw_cursor_remove",
(PyCFunction)pyrna_callback_classmethod_remove,
METH_VARARGS | METH_STATIC,
METH_VARARGS | METH_CLASS,
""},
{NULL, NULL, 0, NULL},
};
@ -147,11 +147,11 @@ PyDoc_STRVAR(pyrna_draw_handler_remove_doc,
static struct PyMethodDef pyrna_space_methods[] = {
{"draw_handler_add",
(PyCFunction)pyrna_callback_classmethod_add,
METH_VARARGS | METH_STATIC,
METH_VARARGS | METH_CLASS,
pyrna_draw_handler_add_doc},
{"draw_handler_remove",
(PyCFunction)pyrna_callback_classmethod_remove,
METH_VARARGS | METH_STATIC,
METH_VARARGS | METH_CLASS,
pyrna_draw_handler_remove_doc},
{NULL, NULL, 0, NULL},
};