Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-09-07 16:53:02 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-09-07 17:02:09 +0300
commite44bf43f6cadd89bb37c472f27839a8cea034b3d (patch)
tree00ca7debd06fb49bc1b9bafc7499cea061dbb223 /source/blender/python/intern
parentaccc94dd73a793a681245bf9eaa0b6f474075995 (diff)
PyAPI: add function to get an RNA subclass
This is inconvenient in regular Python, add a class-method to perform the operation, eg: bpy.types.Node.bl_rna_find_subclass("CustomNodeType")
Diffstat (limited to 'source/blender/python/intern')
-rw-r--r--source/blender/python/intern/bpy_rna.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index dfd643319e5..6a1016584af 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -3707,6 +3707,66 @@ static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self)
return pyrna_struct_CreatePyObject(&r_ptr);
}
+/**
+ * \note Return value is borrowed, caller must incref.
+ */
+static PyObject *pyrna_struct_bl_rna_find_subclass_recursive(PyObject *cls, const char *id)
+{
+ PyObject *ret_test = NULL;
+ PyObject *subclasses = ((PyTypeObject *)cls)->tp_subclasses;
+ if (subclasses) {
+ /* Unfortunately we can't use the dict key because Python class names
+ * don't match the bl_idname used internally. */
+ BLI_assert(PyDict_CheckExact(subclasses));
+ PyObject *key = NULL;
+ Py_ssize_t pos = 0;
+ PyObject *value = NULL;
+ while (PyDict_Next(subclasses, &pos, &key, &value)) {
+ BLI_assert(PyWeakref_CheckRef(value));
+ PyObject *subcls = PyWeakref_GET_OBJECT(value);
+ if (subcls != Py_None) {
+ BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(
+ ((PyTypeObject *)subcls)->tp_dict, bpy_intern_str_bl_rna);
+ if (py_srna) {
+ StructRNA *srna = py_srna->ptr.data;
+ if (STREQ(id, RNA_struct_identifier(srna))) {
+ ret_test = subcls;
+ break;
+ }
+ }
+ ret_test = pyrna_struct_bl_rna_find_subclass_recursive(subcls, id);
+ if (ret_test) {
+ break;
+ }
+ }
+ }
+ }
+ return ret_test;
+}
+
+PyDoc_STRVAR(pyrna_struct_bl_rna_get_subclass_doc,
+".. classmethod:: bl_rna_get_subclass(id, default=None)\n"
+"\n"
+" :arg id: The RNA type identifier.\n"
+" :type vector: string\n"
+" :return: The class or default when not found.\n"
+" :rtype: type\n"
+);
+static PyObject *pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args)
+{
+ char *id;
+ PyObject *ret_default = Py_None;
+
+ if (!PyArg_ParseTuple(args, "s|O:bl_rna_find_subclass", &id, &ret_default)) {
+ return NULL;
+ }
+ PyObject *ret = pyrna_struct_bl_rna_find_subclass_recursive(cls, id);
+ if (ret == NULL) {
+ ret = ret_default;
+ }
+ return Py_INCREF_RET(ret);
+}
+
static void pyrna_dir_members_py__add_keys(PyObject *list, PyObject *dict)
{
PyObject *list_tmp;
@@ -5005,6 +5065,7 @@ static struct PyMethodDef pyrna_struct_methods[] = {
{"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc},
{"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc},
{"type_recast", (PyCFunction)pyrna_struct_type_recast, METH_NOARGS, pyrna_struct_type_recast_doc},
+ {"bl_rna_get_subclass", (PyCFunction) pyrna_struct_bl_rna_get_subclass, METH_VARARGS | METH_CLASS, pyrna_struct_bl_rna_get_subclass_doc},
{"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL},
/* experimental */