From a4793a3b4ac298a651f7bab0bafd809287647509 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 13 Mar 2009 07:50:07 +0000 Subject: 2.5 Python api - 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/intern/bpy_interface.c | 30 +-- source/blender/python/intern/bpy_rna.c | 304 +++++++++------------------ source/blender/python/intern/bpy_rna.h | 6 +- 3 files changed, 114 insertions(+), 226 deletions(-) (limited to 'source/blender/python/intern') diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 19d8b79884f..fc43d7e5537 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -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; } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index fd6221d6ff9..75f0e2d63c9 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -30,12 +30,6 @@ #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 - - - - - - - - - - - diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 63a2be9a31a..1d49d4d5485 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -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 ); -- cgit v1.2.3