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
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2009-11-08 04:13:19 +0300
committerCampbell Barton <ideasman42@gmail.com>2009-11-08 04:13:19 +0300
commitfac2ca1c7ca26b9e7019d5c3367b1cb758ba8ca4 (patch)
tree9f4b7e554ceee580d01fb22702d8b6ff01064bbf /source
parent30c4c4599dfb72b430a409648bb1407a0f197332 (diff)
bpy/rna api class feature
- python defined classes will be used when available (otherwise automaically generated metaclasses are made as before) - use properties rather then functions for python defined rna class's - call the classes getattr AFTER doing an RNA lookup, avoids setting and clearing exceptions for most attribute lookups, tested UI scripts are ~25% faster. - extending rna py classes this way is a nicer alternative to modifying the generated metaclasses in place. Example class --- snip class Object(bpy.types.ID): def _get_children(self): return [child for child in bpy.data.objects if child.parent == self] children = property(_get_children) --- snip The C initialization function looks in bpy_types.py for classes matching RNA structure names, using them when available. This means all objects in python will be instances of these classes. Python properties/funcs defined in ID py class will also be available for subclasses for eg. (Group Mesh etc)
Diffstat (limited to 'source')
-rw-r--r--source/blender/python/intern/bpy_interface.c53
-rw-r--r--source/blender/python/intern/bpy_rna.c110
-rw-r--r--source/blender/python/intern/bpy_rna.h1
3 files changed, 114 insertions, 50 deletions
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index e67df5db096..4a55c2fb6fb 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -176,35 +176,35 @@ static void bpy_init_modules( void )
{
PyObject *mod;
- mod = PyModule_New("bpy");
+ /* Needs to be first since this dir is needed for future modules */
+ char *modpath= BLI_gethome_folder("scripts/modules", BLI_GETHOME_ALL);
+ if(modpath) {
+ PyObject *sys_path= PySys_GetObject("path"); /* borrow */
+ PyObject *py_modpath= PyUnicode_FromString(modpath);
+ PyList_Insert(sys_path, 0, py_modpath); /* add first */
+ Py_DECREF(py_modpath);
+ }
- PyModule_AddObject( mod, "data", BPY_rna_module() );
+ mod = PyModule_New("bpy");
+
+ /* add the module so we can import it */
+ PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod);
+ Py_DECREF(mod);
+
+ /* run first, initializes rna types */
+ BPY_rna_init();
+
+ PyModule_AddObject( mod, "types", BPY_rna_types() ); /* needs to be first so bpy_types can run */
+ bpy_import_test("bpy_types");
+ PyModule_AddObject( mod, "data", BPY_rna_module() ); /* imports bpy_types by running this */
+ bpy_import_test("bpy_types");
/* PyModule_AddObject( mod, "doc", BPY_rna_doc() ); */
- PyModule_AddObject( mod, "types", BPY_rna_types() );
PyModule_AddObject( mod, "props", BPY_rna_props() );
PyModule_AddObject( mod, "__ops__", BPY_operator_module() ); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */
PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experimental, consider this a test, especially PyCObject is not meant to be permanent
-
- /* add the module so we can import it */
- PyDict_SetItemString(PySys_GetObject("modules"), "bpy", mod);
- Py_DECREF(mod);
- /* add our own modules dir */
- {
- char *modpath= BLI_gethome_folder("scripts/modules", BLI_GETHOME_ALL);
-
- if(modpath) {
- PyObject *sys_path= PySys_GetObject("path"); /* borrow */
- PyObject *py_modpath= PyUnicode_FromString(modpath);
- PyList_Insert(sys_path, 0, py_modpath); /* add first */
- Py_DECREF(py_modpath);
- }
-
- bpy_import_test("bpy_ops"); /* adds its self to bpy.ops */
- bpy_import_test("bpy_utils"); /* adds its self to bpy.sys */
- bpy_import_test("bpy_ext"); /* extensions to our existing types */
- }
-
+
+
/* bpy context */
{
bpy_context_module= ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, &pyrna_struct_Type );
@@ -213,11 +213,16 @@ static void bpy_init_modules( void )
PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module);
}
-
/* stand alone utility modules not related to blender directly */
Geometry_Init();
Mathutils_Init();
BGL_Init();
+
+ /* add our own modules dir */
+ {
+ bpy_import_test("bpy_ops"); /* adds its self to bpy.ops */
+ bpy_import_test("bpy_utils"); /* adds its self to bpy.sys */
+ }
}
void BPY_update_modules( void )
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 3e31e24a8e0..15c1f378cb1 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -1364,16 +1364,6 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
PropertyRNA *prop;
FunctionRNA *func;
- /* Include this incase this instance is a subtype of a python class
- * In these instances we may want to return a function or variable provided by the subtype
- *
- * Also needed to return methods when its not a subtype
- * */
- ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
- if (ret) return ret;
- else PyErr_Clear();
- /* done with subtypes */
-
if ((prop = RNA_struct_find_property(&self->ptr, name))) {
ret = pyrna_prop_to_py(&self->ptr, prop);
}
@@ -1419,8 +1409,18 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
}
}
else {
+#if 0
PyErr_Format( PyExc_AttributeError, "StructRNA - Attribute \"%.200s\" not found", name);
ret = NULL;
+#endif
+ /* Include this incase this instance is a subtype of a python class
+ * In these instances we may want to return a function or variable provided by the subtype
+ *
+ * Also needed to return methods when its not a subtype
+ * */
+
+ /* The error raised here will be displayed */
+ ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
}
return ret;
@@ -2551,6 +2551,7 @@ static PyObject* pyrna_srna_PyBase(StructRNA *srna) //, PyObject *bpy_types_dict
/* get the base type */
base= RNA_struct_base(srna);
+
if(base && base != srna) {
/*/printf("debug subtype %s %p\n", RNA_struct_identifier(srna), srna); */
py_base= pyrna_srna_Subtype(base); //, bpy_types_dict);
@@ -2564,6 +2565,56 @@ static PyObject* pyrna_srna_PyBase(StructRNA *srna) //, PyObject *bpy_types_dict
return py_base;
}
+/* check if we have a native python subclass, use it when it exists
+ * return a borrowed reference */
+static PyObject* pyrna_srna_ExternalType(StructRNA *srna)
+{
+ PyObject *bpy_types_dict= NULL;
+ const char *idname= RNA_struct_identifier(srna);
+ PyObject *newclass;
+
+ if(bpy_types_dict==NULL) {
+ PyObject *bpy_types= PyImport_ImportModuleLevel("bpy_types", NULL, NULL, NULL, 0);
+
+ if(bpy_types==NULL) {
+ PyErr_Print();
+ PyErr_Clear();
+ fprintf(stderr, "pyrna_srna_ExternalType: failed to find 'bpy_types' module\n");
+ return NULL;
+ }
+
+ bpy_types_dict = PyModule_GetDict(bpy_types); // borrow
+ Py_DECREF(bpy_types); // fairly safe to assume the dict is kept
+ }
+
+ newclass= PyDict_GetItemString(bpy_types_dict, idname);
+
+ /* sanity check, could skip this unless in debug mode */
+ if(newclass) {
+ PyObject *base_compare= pyrna_srna_PyBase(srna);
+ PyObject *bases= PyObject_GetAttrString(newclass, "__bases__");
+
+ if(PyTuple_GET_SIZE(bases)) {
+ PyObject *base= PyTuple_GET_ITEM(bases, 0);
+
+ if(base_compare != base) {
+ PyLineSpit();
+ fprintf(stderr, "pyrna_srna_ExternalType: incorrect subclassing of SRNA '%s'\n", idname);
+ PyObSpit("Expected! ", base_compare);
+ newclass= NULL;
+ }
+ else {
+ if(G.f & G_DEBUG)
+ fprintf(stderr, "SRNA Subclassed: '%s'\n", idname);
+ }
+ }
+
+ Py_DECREF(bases);
+ }
+
+ return newclass;
+}
+
static PyObject* pyrna_srna_Subtype(StructRNA *srna)
{
PyObject *newclass = NULL;
@@ -2572,6 +2623,9 @@ static PyObject* pyrna_srna_Subtype(StructRNA *srna)
newclass= NULL; /* Nothing to do */
} else if ((newclass= RNA_struct_py_type_get(srna))) {
Py_INCREF(newclass);
+ } else if ((newclass= pyrna_srna_ExternalType(srna))) {
+ pyrna_subtype_set_rna(newclass, srna);
+ Py_INCREF(newclass);
} else {
/* subclass equivelents
- class myClass(myBase):
@@ -2681,23 +2735,26 @@ PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop )
return ( PyObject * ) pyrna;
}
-/* bpy.data from python */
-static PointerRNA *rna_module_ptr= NULL;
-PyObject *BPY_rna_module( void )
+void BPY_rna_init(void)
{
- BPy_StructRNA *pyrna;
- PointerRNA ptr;
-
#ifdef USE_MATHUTILS // register mathutils callbacks, ok to run more then once.
mathutils_rna_array_cb_index= Mathutils_RegisterCallback(&mathutils_rna_array_cb);
mathutils_rna_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_rna_matrix_cb);
#endif
-
+
if( PyType_Ready( &pyrna_struct_Type ) < 0 )
- return NULL;
-
+ return;
+
if( PyType_Ready( &pyrna_prop_Type ) < 0 )
- return NULL;
+ return;
+}
+
+/* bpy.data from python */
+static PointerRNA *rna_module_ptr= NULL;
+PyObject *BPY_rna_module(void)
+{
+ BPy_StructRNA *pyrna;
+ PointerRNA ptr;
/* for now, return the base RNA type rather then a real module */
RNA_main_pointer_create(G.main, &ptr);
@@ -2735,21 +2792,22 @@ static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA * self, PyObject *pyna
PointerRNA newptr;
PyObject *ret;
- ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
- if (ret) return ret;
- else PyErr_Clear();
-
if (RNA_property_collection_lookup_string(&self->ptr, self->prop, _PyUnicode_AsString(pyname), &newptr)) {
ret= pyrna_struct_Subtype(&newptr);
if (ret==NULL) {
PyErr_Format(PyExc_SystemError, "bpy.types.%.200s subtype could not be generated, this is a bug!", _PyUnicode_AsString(pyname));
}
- return ret;
}
- else { /* Override the error */
+ else {
+#if 0
PyErr_Format(PyExc_AttributeError, "bpy.types.%.200s RNA_Struct does not exist", _PyUnicode_AsString(pyname));
return NULL;
+#endif
+ /* The error raised here will be displayed */
+ ret= PyObject_GenericGetAttr((PyObject *)self, pyname);
}
+
+ return ret;
}
static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self);
diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h
index d480fd3ec9b..fe38ddb6bd9 100644
--- a/source/blender/python/intern/bpy_rna.h
+++ b/source/blender/python/intern/bpy_rna.h
@@ -64,6 +64,7 @@ typedef struct {
/* cheap trick */
#define BPy_BaseTypeRNA BPy_PropertyRNA
+void BPY_rna_init( void );
PyObject *BPY_rna_module( void );
void BPY_update_rna_module( void );
/*PyObject *BPY_rna_doc( void );*/