2.5 Python api
authorCampbell Barton <ideasman42@gmail.com>
Fri, 13 Mar 2009 07:50:07 +0000 (07:50 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 13 Mar 2009 07:50:07 +0000 (07:50 +0000)
- rearranged modules bpyui -> bpy.ui, bpy -> bpy.data, remove bpydoc
- new module bpy.types, stores a list of all struct types
- added __rna__ attribute to types - eg bpy.types.World.__rna__ so you can access the rna data from a type. (so bpydoc.structs isnt needed anymore)
- removed unused subtyping method (use python subclassing rather then C PyTypeObject)

source/blender/python/epy_doc_gen.py
source/blender/python/intern/bpy_interface.c
source/blender/python/intern/bpy_rna.c
source/blender/python/intern/bpy_rna.h
source/blender/python/rna_dump.py

index 6281cc66f4782154507bc1d7c7d9adc2b3541a94..7f1ad935bb49164be9a3f290df80e0f301919e75 100644 (file)
@@ -121,12 +121,19 @@ def rna2epy(target_path):
                try:            return rna_struct.base.identifier
                except: return '' # invalid id
 
-       #structs = [(base_id(rna_struct), rna_struct.identifier, rna_struct) for rna_struct in bpydoc.structs.values()]
-       
+       #structs = [(base_id(rna_struct), rna_struct.identifier, rna_struct) for rna_struct in bpy.doc.structs.values()]
+       '''
        structs = []
-       for rna_struct in bpydoc.structs.values():
+       for rna_struct in bpy.doc.structs.values():
                structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )
-               
+       '''
+       structs = []
+       for rna_type_name in dir(bpy.types):
+               rna_type = getattr(bpy.types, rna_type_name)
+               if hasattr(rna_type, '__rna__'):
+                       rna_struct = rna_type.__rna__
+                       structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )      
+       
        
        
        structs.sort() # not needed but speeds up sort below, setting items without an inheritance first
@@ -178,7 +185,7 @@ def rna2epy(target_path):
 def op2epy(target_path):
        out = open(target_path, 'w')
        
-       operators = dir(bpyoperator)
+       operators = dir(bpy.ops)
        operators.remove('add')
        operators.remove('remove')
        operators.sort()
@@ -193,7 +200,7 @@ def op2epy(target_path):
                kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'"
                kw_arg_attrs = [] # "@type mode: int"
                
-               rna = getattr(bpyoperator, op).rna
+               rna = getattr(bpy.ops, op).rna
                rna_struct = rna.rna_type
                # print (dir(rna))
                # print (dir(rna_struct))
index 19d8b79884f7da62f5d7bdbe8c45419d4383a612..fc43d7e553771c947102563e1a39c1bba754340e 100644 (file)
@@ -34,30 +34,23 @@ void BPY_free_compiled_text( struct Text *text )
 
 static PyObject *CreateGlobalDictionary( bContext *C )
 {
+       PyObject *mod;
        PyObject *dict = PyDict_New(  );
        PyObject *item = PyUnicode_FromString( "__main__" );
        PyDict_SetItemString( dict, "__builtins__", PyEval_GetBuiltins(  ) );
        PyDict_SetItemString( dict, "__name__", item );
        Py_DECREF(item);
        
-       /* Add Modules */
-       item = BPY_rna_module();
-       PyDict_SetItemString( dict, "bpy", item );
-       Py_DECREF(item);
-       
-       item = BPY_rna_doc();
-       PyDict_SetItemString( dict, "bpydoc", item );
-       Py_DECREF(item);
-
-       item = BPY_operator_module(C);
-       PyDict_SetItemString( dict, "bpyoperator", item );
-       Py_DECREF(item);
-
+       /* add bpy to global namespace */
+       mod = PyModule_New("bpy");
+       PyDict_SetItemString( dict, "bpy", mod );
+       Py_DECREF(mod);
        
-       // XXX very experemental, consiter this a test, especiall PyCObject is not meant to be perminant
-       item = BPY_ui_module();
-       PyDict_SetItemString( dict, "bpyui", item );
-       Py_DECREF(item);
+       PyModule_AddObject( mod, "data", BPY_rna_module() );
+       /* PyModule_AddObject( mod, "doc", BPY_rna_doc() ); */
+       PyModule_AddObject( mod, "types", BPY_rna_types() );
+       PyModule_AddObject( mod, "ops", BPY_operator_module(C) );
+       PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
        
        // XXX - evil, need to access context
        item = PyCObject_FromVoidPtr( C, NULL );
@@ -80,8 +73,6 @@ void BPY_start_python( void )
        
        // todo - sys paths - our own imports
        
-       BPY_rna_init_types();
-       
        py_tstate = PyGILState_GetThisThreadState();
        PyEval_ReleaseThread(py_tstate);
        
@@ -96,7 +87,6 @@ void BPY_end_python( void )
        
        Py_Finalize(  );
        
-       BPY_rna_free_types(); /* this MUST run after Py_Finalize since it frees Dynamic allocated PyTypes so we cant free them first */
        return;
 }
 
index fd6221d6ff96f30470681e3266904baaf2e0e3f8..75f0e2d63c97347118f03fe066f20d75076cba4f 100644 (file)
 #include "MEM_guardedalloc.h"
 #include "BKE_global.h" /* evil G.* */
 
-/* There are 2 ways subclassing can work, PY_CLASS_SUBTYPE - Uses pythons internal subclassing
- * - class MyClass(SomeClass): ...
- * When PY_CLASS_SUBTYPE is not defined use a C subclass which copies the PyTypeObject and makes some changes.
-*/
-#define PY_CLASS_SUBTYPE
-
 static int pyrna_struct_compare( BPy_StructRNA * a, BPy_StructRNA * b )
 {
        return (a->ptr.data==b->ptr.data) ? 0 : -1;
@@ -1016,6 +1010,72 @@ PyTypeObject pyrna_prop_Type = {
        NULL
 };
 
+PyObject* pyrna_struct_Subtype(PointerRNA *ptr)
+{
+       PyObject *newclass = NULL;
+       PropertyRNA *nameprop;
+
+       if (ptr->type==NULL) {
+               newclass= NULL; /* Nothing to do */
+       } else if ((nameprop = RNA_struct_name_property(ptr))) {
+               /* for now, return the base RNA type rather then a real module */
+               
+               /* Assume BPy_RNA_PYTYPE(ptr->data) was alredy checked */
+               
+               /* subclass equivelents
+               - class myClass(myBase):
+                       some='value' # or ...
+               - myClass = type(name='myClass', bases=(myBase,), dict={'some':'value'})
+               */
+               char name[256], *nameptr;
+
+               PyObject *args = PyTuple_New(3);
+               PyObject *bases = PyTuple_New(1);
+               PyObject *dict = PyDict_New();
+               PyObject *rna;
+               
+               nameptr= RNA_property_string_get_alloc(ptr, nameprop, name, sizeof(name));
+               
+               // arg 1
+               //PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(tp_name));
+               PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(nameptr));
+               
+               // arg 2
+               PyTuple_SET_ITEM(bases, 0, (PyObject *)&pyrna_struct_Type);
+               Py_INCREF(&pyrna_struct_Type);
+               PyTuple_SET_ITEM(args, 1, bases);
+               
+               // arg 3 - add an instance of the rna 
+               PyTuple_SET_ITEM(args, 2, dict); // fill with useful subclass things!
+               
+               if (PyErr_Occurred()) {
+                       PyErr_Print();
+                       PyErr_Clear();
+               }
+               
+               newclass = PyObject_CallObject((PyObject *)&PyType_Type, args);
+               // Set this later
+               
+               if (newclass) {
+                       BPy_RNA_PYTYPE(ptr->data) = newclass; /* Store for later use */
+                       
+                       /* Not 100% needed but useful,
+                        * having an instance within a type looks wrong however this instance IS an rna type */
+                       rna = pyrna_struct_CreatePyObject(ptr);
+                       PyDict_SetItemString(((PyTypeObject *)newclass)->tp_dict, "__rna__", rna);
+                       Py_DECREF(rna);
+                       /* done with rna instance */
+               }
+               Py_DECREF(args);
+               
+               if ((char *)&name != nameptr)
+                       MEM_freeN(nameptr);
+               
+       }
+       
+       return newclass;
+}
+
 /*-----------------------CreatePyObject---------------------------------*/
 PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
 {
@@ -1025,7 +1085,6 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
                Py_RETURN_NONE;
        }
        
-#ifdef PY_CLASS_SUBTYPE
        pyrna = ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, &pyrna_struct_Type );
        if (ptr->type && BPy_RNA_PYTYPE(ptr->type)) {
                PyTypeObject *tp = BPy_RNA_PYTYPE(ptr->type);
@@ -1035,18 +1094,6 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
                pyrna = ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, &pyrna_struct_Type );
        }
        
-#else
-       /* get subtype from RNA struct if its been set */
-       PyTypeObject *tp;
-       if (ptr->type && ptr->type)
-               tp = BPy_RNA_PYTYPE(ptr->type);
-       
-       if (tp==NULL)
-               tp= &pyrna_struct_Type;
-       
-       pyrna = ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, tp );
-#endif 
-       
        if( !pyrna ) {
                PyErr_SetString( PyExc_MemoryError, "couldn't create BPy_StructRNA object" );
                return NULL;
@@ -1080,15 +1127,24 @@ PyObject *BPY_rna_module( void )
 {
        PointerRNA ptr;
        
-       /* types init moved to BPY_rna_init_types */
+       /* This can't be set in the pytype struct because some compilers complain */
+       pyrna_prop_Type.tp_getattro = PyObject_GenericGetAttr; 
+       pyrna_prop_Type.tp_setattro = PyObject_GenericSetAttr; 
+       
+       if( PyType_Ready( &pyrna_struct_Type ) < 0 )
+               return NULL;
+       
+       if( PyType_Ready( &pyrna_prop_Type ) < 0 )
+               return NULL;
+
        
        /* for now, return the base RNA type rather then a real module */
        RNA_main_pointer_create(G.main, &ptr);
        
-       //submodule = Py_InitModule3( "rna", M_rna_methods, "rna module" );
        return pyrna_struct_CreatePyObject(&ptr);
 }
 
+#if 0
 /* This is a way we can access docstrings for RNA types
  * without having the datatypes in blender */
 PyObject *BPY_rna_doc( void )
@@ -1100,29 +1156,20 @@ PyObject *BPY_rna_doc( void )
        
        return pyrna_struct_CreatePyObject(&ptr);
 }
+#endif
 
-#ifdef PY_CLASS_SUBTYPE
-void BPY_rna_init_types(void)
-{      
+ PyObject *BPY_rna_types(void)
+ {
        /* Now initialize new subtypes based on pyrna_struct_Type */
-       char tp_name[64];
        PointerRNA ptr;
 
        CollectionPropertyIterator iter;
-       PropertyRNA *nameprop, *prop;
-       char name[256], *nameptr;
+       PropertyRNA *prop;
 
-       
-       /* This can't be set in the pytype struct because some compilers complain */
-       pyrna_prop_Type.tp_getattro = PyObject_GenericGetAttr; 
-       pyrna_prop_Type.tp_setattro = PyObject_GenericSetAttr; 
-       
-       if( PyType_Ready( &pyrna_struct_Type ) < 0 )
-               return;
-       
-       if( PyType_Ready( &pyrna_prop_Type ) < 0 )
-               return;
-               
+       PyObject *mod, *dict, *type, *name;
+       mod = PyModule_New("types");
+       dict = PyModule_GetDict(mod);
        
        /* for now, return the base RNA type rather then a real module */
        RNA_blender_rna_pointer_create(&ptr);
@@ -1130,174 +1177,27 @@ void BPY_rna_init_types(void)
        
        RNA_property_collection_begin(&ptr, prop, &iter);
        for(; iter.valid; RNA_property_collection_next(&iter)) {
-               if(iter.ptr.data && (nameprop = RNA_struct_name_property(&iter.ptr))) {
-                       
-                       /* subclass = type(name='myClass', bases=(myBase,), dict={'some':'value'}) */
-                       PyObject *args = PyTuple_New(3);
-                       PyObject *bases = PyTuple_New(1);
-                       PyObject *dict = PyDict_New();
-                       PyObject *newclass;
-                       
-                       nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
-                       snprintf(tp_name, 64, "BPyRNA_%s", nameptr);
-                       
-                       
-                       // arg 1
-                       PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(tp_name));
-                       
-                       // arg 2
-                       PyTuple_SET_ITEM(bases, 0, (PyObject *)&pyrna_struct_Type);
-                       Py_INCREF(&pyrna_struct_Type);
-                       PyTuple_SET_ITEM(args, 1, bases);
-                       
-                       // arg 3
-                       PyTuple_SET_ITEM(args, 2, dict); // fill with useful subclass things!
-                       
-                       if (PyErr_Occurred()) {
-                               PyErr_Print();
-                               PyErr_Clear();
+               if(iter.ptr.data) {
+                       type = (PyObject *)BPy_RNA_PYTYPE(iter.ptr.data);
+                       if (type==NULL) {
+                               type = pyrna_struct_Subtype(&iter.ptr);
                        }
-                       
-                       newclass = PyObject_CallObject((PyObject *)&PyType_Type, args);
-                       
-                       Py_DECREF(args);
-                       
-                       BPy_RNA_PYTYPE(iter.ptr.data) = (void *         )newclass;
-                       
-                       // printf("BPyRNA_PyTypes: %s\n", tp_name);
-                       
-                       if ((char *)&name != nameptr)
-                               MEM_freeN(nameptr);
-               }
-       }
-       RNA_property_collection_end(&iter);
-}
-
-void BPY_rna_free_types(void) {};
-       
-#else // Other method uses C defined PyTypes
-
-static void *tp_mem = NULL;
-void BPY_rna_init_types(void)
-{
-       PyTypeObject init_struct_type = pyrna_struct_Type; /* store this type to make copies from */
-       
-       /* Now initialize new subtypes based on pyrna_struct_Type */
-       typedef struct PyTypeObject_Name {PyTypeObject tp; char name[64];} PyTypeObject_Name;
-       PyTypeObject_Name *tp_mem_ptr;
-       PyTypeObject *tp;
-       char *tp_name;
-       PointerRNA ptr;
-
-       CollectionPropertyIterator iter;
-       PropertyRNA *nameprop, *prop;
-       char name[256], *nameptr;
-
-       
-       /* This can't be set in the pytype struct because some compilers complain */
-       pyrna_prop_Type.tp_getattro = PyObject_GenericGetAttr; 
-       pyrna_prop_Type.tp_setattro = PyObject_GenericSetAttr; 
-       
-       if( PyType_Ready( &pyrna_struct_Type ) < 0 )
-               return;
-       
-       if( PyType_Ready( &pyrna_prop_Type ) < 0 )
-               return;
-       
-       /* Note, making subtypes could be done by using an equivelent of 
-       class MyClass(RNA_Struct)
-       */
-       
-       
-       /* for now, return the base RNA type rather then a real module */
-       RNA_blender_rna_pointer_create(&ptr);
-       prop = RNA_struct_find_property(&ptr, "structs");
-       
-       tp_mem = tp_mem_ptr = MEM_mallocN(sizeof(PyTypeObject_Name) * RNA_property_collection_length(&ptr, prop), "BPyRNA_PyTypes");
-       
-       RNA_property_collection_begin(&ptr, prop, &iter);
-       for(; iter.valid; RNA_property_collection_next(&iter)) {
-               if(iter.ptr.data && (nameprop = RNA_struct_name_property(&iter.ptr))) {
-                       
-                       nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
-                       
-                       //tp = MEM_mallocN(sizeof(PyTypeObject_Name), "pyrna");
-                       tp = &(tp_mem_ptr->tp);
-                       tp_name = tp_mem_ptr->name;
-                       snprintf(tp_name, 64, "BPyRNA_%s", nameptr);
-                       
-                       
-                       *tp= init_struct_type; /* Copy the uninitialized pyrna_struct_Type */
-                       tp->tp_name= tp_name;
-                       tp->tp_base= &pyrna_struct_Type;
-                       
-                       /* Todo - add special tp->tp_new function that lets us subtupe rna! */
-                       
-                       if( PyType_Ready( tp ) < 0 ) {
-                               printf("PyType_Ready failed\n");
+                       if (type) {
+                               name = PyObject_GetAttrString(type, "__name__"); /* myClass.__name__ */
+                               if (name) {
+                                       PyDict_SetItem(dict, name, type);
+                                       Py_DECREF(name);
+                               }
+                               else {
+                                       printf("could not get type __name__\n");
+                               }
                        }
-                       
-                       BPy_RNA_PYTYPE(iter.ptr.data) = tp;
-                       
-                       // printf("BPyRNA_PyTypes: %s\n", tp_name);
-                       
-                       if ((char *)&name != nameptr)
-                               MEM_freeN(nameptr);
-               }
-               tp_mem_ptr++;
-       }
-       RNA_property_collection_end(&iter);
-}
-
-/* Runs after python is finished, dont use any python functions */
-void BPY_rna_free_types(void)
-{
-       if (tp_mem==NULL)
-               return;
-
-       /* We dont really have to clear each structs type but may want to, also might allocate each type on its own */
-#if 0
-       PointerRNA ptr;
-
-       CollectionPropertyIterator iter;
-       PropertyRNA *prop;
-       
-       /* for now, return the base RNA type rather then a real module */
-       RNA_blender_rna_pointer_create(&ptr);
-       prop = RNA_struct_find_property(&ptr, "structs");
-       
-       RNA_property_collection_begin(&ptr, prop, &iter);
-       for(; iter.valid; RNA_property_collection_next(&iter)) {
-               if(iter.ptr.data) {
-                       if (BPy_RNA_PYTYPE(iter.ptr.data)) {
-                               /*
-                               PyTypeObject *tp = BPy_RNA_PYTYPE(iter.ptr.data);
-                               printf("BPyRNA clear: %s %d\n", tp->tp_name, (int)(long)BPy_RNA_PYTYPE(iter.ptr.data));
-                               */
-                               
-                               /* May want to alloc each type on its own however this makes it hard to know if RNA subtypes are using the type */
-                               
-                               /* PyMem_Free( BPy_RNA_PYTYPE(iter.ptr.data) );
-                               MEM_freeN( BPy_RNA_PYTYPE(iter.ptr.data) ); */
-                               BPy_RNA_PYTYPE(iter.ptr.data)= NULL;
+                       else {
+                               printf("could not generate type\n");
                        }
                }
        }
        RNA_property_collection_end(&iter);
-#endif
-
-       MEM_freeN( tp_mem );
-       tp_mem = NULL;
+       
+       return mod;
 }
-#endif // END PYTYPE COPY METHOD
-
-
-
-
-
-
-
-
-
-
-
index 63a2be9a31a002d522f6a41ade58cf38394f3b30..1d49d4d5485d1f88822508087489cd20cf643367 100644 (file)
@@ -60,10 +60,8 @@ typedef struct {
 } BPy_PropertyRNA;
 
 PyObject *BPY_rna_module( void );
-PyObject *BPY_rna_doc( void );
-void BPY_rna_init_types( void );
-void BPY_rna_free_types( void );
-
+/*PyObject *BPY_rna_doc( void );*/
+PyObject *BPY_rna_types( void );
 
 PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr );
 PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop );
index 826051d9ceba00b08656a43417b67ea1eaeb8b8b..f587cd983b2abf597fda43d79bd1bf8e89da6aea 100644 (file)
@@ -104,7 +104,7 @@ def seek(r, txt):
                                seek(r[i], newtxt)
 
 #print (dir(bpy))
-seek(bpy, 'bpy')
+seek(bpy.data, 'bpy.data')
 
 
 #print dir(bpy)