From 8f4f3cce0393f2fdbf91133feb147096c53fee3d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 May 2020 15:05:09 +1000 Subject: Cleanup: split RNA type extension methods into it's own API This isn't so closely related to the RNA API, it's a way to use the C/Python API to extend RNA types and can be in it's own file. --- source/blender/python/intern/CMakeLists.txt | 2 + source/blender/python/intern/bpy.c | 5 +- source/blender/python/intern/bpy_rna.c | 111 ++++--------------- source/blender/python/intern/bpy_rna.h | 3 +- source/blender/python/intern/bpy_rna_types_capi.c | 129 ++++++++++++++++++++++ source/blender/python/intern/bpy_rna_types_capi.h | 26 +++++ 6 files changed, 184 insertions(+), 92 deletions(-) create mode 100644 source/blender/python/intern/bpy_rna_types_capi.c create mode 100644 source/blender/python/intern/bpy_rna_types_capi.h (limited to 'source/blender') diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 0b05a0dfcfe..769618005af 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -77,6 +77,7 @@ set(SRC bpy_rna_driver.c bpy_rna_gizmo.c bpy_rna_id_collection.c + bpy_rna_types_capi.c bpy_traceback.c bpy_utils_previews.c bpy_utils_units.c @@ -113,6 +114,7 @@ set(SRC bpy_rna_driver.h bpy_rna_gizmo.h bpy_rna_id_collection.h + bpy_rna_types_capi.h bpy_traceback.h bpy_utils_previews.h bpy_utils_units.h diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 5a36535f3e3..9d0ee0bb500 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -44,6 +44,7 @@ #include "bpy_rna.h" #include "bpy_rna_gizmo.h" #include "bpy_rna_id_collection.h" +#include "bpy_rna_types_capi.h" #include "bpy_utils_previews.h" #include "bpy_utils_units.h" @@ -406,8 +407,8 @@ void BPy_init_modules(void) PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module); - /* register bpy/rna classmethod callbacks */ - BPY_rna_register_cb(); + /* Register methods and property get/set for RNA types. */ + BPY_rna_types_extend_capi(); /* utility func's that have nowhere else to go */ PyModule_AddObject(mod, diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 2c54b9ce1e1..4da81e3380f 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -9033,6 +9033,28 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla Py_RETURN_NONE; } +/** + * Extend RNA types with C/API methods. + */ +void pyrna_struct_type_extend_capi(struct StructRNA *srna, struct PyMethodDef *method) +{ + PyObject *cls = pyrna_srna_Subtype(srna); + 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_SetAttrString(cls, method->ml_name, classmethod); + + Py_DECREF(classmethod); + Py_DECREF(args); /* Clears 'func' too. */ + } + } + Py_DECREF(cls); +} + /* Access to 'owner_id' internal global. */ static PyObject *pyrna_bl_owner_id_get(PyObject *UNUSED(self)) @@ -9076,92 +9098,3 @@ PyMethodDef meth_bpy_owner_id_set = { METH_O, NULL, }; - -/* currently this is fairly limited, we would need to make some way to split up - * pyrna_callback_classmethod_... if we want more than one callback per type */ -typedef struct BPyRNA_CallBack { - PyMethodDef py_method; - StructRNA *bpy_srna; -} PyRNA_CallBack; - -PyDoc_STRVAR( - pyrna_draw_handler_add_doc, - ".. method:: draw_handler_add(callback, args, region_type, draw_type)\n" - "\n" - " Add a new draw handler to this space type.\n" - " It will be called every time the specified region in the space type will be drawn.\n" - " Note: All arguments are positional only for now.\n" - "\n" - " :param callback:\n" - " A function that will be called when the region is drawn.\n" - " It gets the specified arguments as input.\n" - " :type callback: function\n" - " :param args: Arguments that will be passed to the callback.\n" - " :type args: tuple\n" - " :param region_type: The region type the callback draws in; usually ``WINDOW``. " - "(:class:`bpy.types.Region.type`)\n" - " :type region_type: str\n" - " :param draw_type: Usually ``POST_PIXEL`` for 2D drawing and ``POST_VIEW`` for 3D drawing. " - "In some cases ``PRE_VIEW`` can be used. ``BACKDROP`` can be used for backdrops in the node " - "editor.\n" - " :type draw_type: str\n" - " :return: Handler that can be removed later on.\n" - " :rtype: object"); - -PyDoc_STRVAR(pyrna_draw_handler_remove_doc, - ".. method:: draw_handler_remove(handler, region_type)\n" - "\n" - " Remove a draw handler that was added previously.\n" - "\n" - " :param handler: The draw handler that should be removed.\n" - " :type handler: object\n" - " :param region_type: Region type the callback was added to.\n" - " :type region_type: str\n"); - -static struct BPyRNA_CallBack pyrna_cb_methods[] = { - {{"draw_handler_add", - (PyCFunction)pyrna_callback_classmethod_add, - METH_VARARGS | METH_STATIC, - pyrna_draw_handler_add_doc}, - &RNA_Space}, - {{"draw_handler_remove", - (PyCFunction)pyrna_callback_classmethod_remove, - METH_VARARGS | METH_STATIC, - pyrna_draw_handler_remove_doc}, - &RNA_Space}, - - {{"draw_cursor_add", - (PyCFunction)pyrna_callback_classmethod_add, - METH_VARARGS | METH_STATIC, - ""}, - &RNA_WindowManager}, - {{"draw_cursor_remove", - (PyCFunction)pyrna_callback_classmethod_remove, - METH_VARARGS | METH_STATIC, - ""}, - &RNA_WindowManager}, - {{NULL, NULL, 0, NULL}, NULL}, -}; - -void BPY_rna_register_cb(void) -{ - int i; - - for (i = 0; pyrna_cb_methods[i].bpy_srna; i++) { - PyObject *cls; - PyObject *func; - PyObject *classmethod; - PyObject *args = PyTuple_New(1); - - cls = pyrna_srna_Subtype(pyrna_cb_methods[i].bpy_srna); - func = PyCFunction_New(&pyrna_cb_methods[i].py_method, NULL); - PyTuple_SET_ITEM(args, 0, func); - classmethod = PyObject_CallObject((PyObject *)&PyClassMethod_Type, args); - - PyObject_SetAttrString(cls, pyrna_cb_methods[i].py_method.ml_name, classmethod); - - Py_DECREF(classmethod); - Py_DECREF(args); /* Clears 'func' too. */ - Py_DECREF(cls); - } -} diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 5899c1659b5..3f73ea20205 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -185,7 +185,6 @@ PyObject *BPY_rna_module(void); void BPY_update_rna_module(void); /*PyObject *BPY_rna_doc(void);*/ PyObject *BPY_rna_types(void); -void BPY_rna_register_cb(void); PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr); PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop); @@ -221,6 +220,8 @@ int pyrna_enum_value_from_id(const EnumPropertyItem *item, int pyrna_deferred_register_class(struct StructRNA *srna, PyTypeObject *py_class); +void pyrna_struct_type_extend_capi(struct StructRNA *srna, struct PyMethodDef *py_method); + /* called before stopping python */ void pyrna_alloc_types(void); void pyrna_free_types(void); diff --git a/source/blender/python/intern/bpy_rna_types_capi.c b/source/blender/python/intern/bpy_rna_types_capi.c new file mode 100644 index 00000000000..1b4533224b8 --- /dev/null +++ b/source/blender/python/intern/bpy_rna_types_capi.c @@ -0,0 +1,129 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup pythonintern + * + * This file extends RNA types from `bpy.types` with C/Python API methods and attributes. + * + * We should avoid adding code here, and prefer: + * - `source/blender/makesrna/intern/rna_context.c` using the RNA C API. + * - `release/scripts/modules/bpy_types.py` when additions c an be written in Python. + * + * Otherwise functions can be added here as a last resort. + */ + +#include +#include + +#include "RNA_types.h" + +#include "BLI_utildefines.h" + +#include "bpy_rna.h" +#include "bpy_rna_callback.h" +#include "bpy_rna_types_capi.h" + +#include "../generic/py_capi_utils.h" + +#include "RNA_access.h" + +#include "MEM_guardedalloc.h" + +#include "WM_api.h" + +/* -------------------------------------------------------------------- */ +/** \name Window Manager Type + * \{ */ + +static struct PyMethodDef pyrna_windowmanager_methods[] = { + {"draw_cursor_add", + (PyCFunction)pyrna_callback_classmethod_add, + METH_VARARGS | METH_STATIC, + ""}, + {"draw_cursor_remove", + (PyCFunction)pyrna_callback_classmethod_remove, + METH_VARARGS | METH_STATIC, + ""}, + {NULL, NULL, 0, NULL}, +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Space Type + * \{ */ + +PyDoc_STRVAR( + pyrna_draw_handler_add_doc, + ".. method:: draw_handler_add(callback, args, region_type, draw_type)\n" + "\n" + " Add a new draw handler to this space type.\n" + " It will be called every time the specified region in the space type will be drawn.\n" + " Note: All arguments are positional only for now.\n" + "\n" + " :param callback:\n" + " A function that will be called when the region is drawn.\n" + " It gets the specified arguments as input.\n" + " :type callback: function\n" + " :param args: Arguments that will be passed to the callback.\n" + " :type args: tuple\n" + " :param region_type: The region type the callback draws in; usually ``WINDOW``. " + "(:class:`bpy.types.Region.type`)\n" + " :type region_type: str\n" + " :param draw_type: Usually ``POST_PIXEL`` for 2D drawing and ``POST_VIEW`` for 3D drawing. " + "In some cases ``PRE_VIEW`` can be used. ``BACKDROP`` can be used for backdrops in the node " + "editor.\n" + " :type draw_type: str\n" + " :return: Handler that can be removed later on.\n" + " :rtype: object"); + +PyDoc_STRVAR(pyrna_draw_handler_remove_doc, + ".. method:: draw_handler_remove(handler, region_type)\n" + "\n" + " Remove a draw handler that was added previously.\n" + "\n" + " :param handler: The draw handler that should be removed.\n" + " :type handler: object\n" + " :param region_type: Region type the callback was added to.\n" + " :type region_type: str\n"); + +static struct PyMethodDef pyrna_space_methods[] = { + {"draw_handler_add", + (PyCFunction)pyrna_callback_classmethod_add, + METH_VARARGS | METH_STATIC, + pyrna_draw_handler_add_doc}, + {"draw_handler_remove", + (PyCFunction)pyrna_callback_classmethod_remove, + METH_VARARGS | METH_STATIC, + pyrna_draw_handler_remove_doc}, + {NULL, NULL, 0, NULL}, +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public API + * \{ */ + +void BPY_rna_types_extend_capi(void) +{ + pyrna_struct_type_extend_capi(&RNA_Space, pyrna_space_methods); + pyrna_struct_type_extend_capi( + &RNA_WindowManager, pyrna_windowmanager_methods); +} + +/** \} */ diff --git a/source/blender/python/intern/bpy_rna_types_capi.h b/source/blender/python/intern/bpy_rna_types_capi.h new file mode 100644 index 00000000000..1049122e468 --- /dev/null +++ b/source/blender/python/intern/bpy_rna_types_capi.h @@ -0,0 +1,26 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup pythonintern + */ + +#ifndef __BPY_RNA_TYPES_CAPI_H__ +#define __BPY_RNA_TYPES_CAPI_H__ + +void BPY_rna_types_extend_capi(void); + +#endif /* __BPY_RNA_TYPES_CAPI_H__ */ -- cgit v1.2.3