[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [19259] branches/blender2.5/blender/source /blender: WIP PyAPI from winter camp discussions, make subtypes of the base RNA python type, eventually allowing us to have python defined RNA classes in

Campbell Barton ideasman42 at gmail.com
Wed Mar 11 18:28:37 CET 2009


Revision: 19259
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=19259
Author:   campbellbarton
Date:     2009-03-11 18:28:37 +0100 (Wed, 11 Mar 2009)

Log Message:
-----------
WIP PyAPI from winter camp discussions, make subtypes of the base RNA python type, eventually allowing us to have python defined RNA classes in 
python - lux/pov/renderman materials, lamps etc as well as operators.

At the moment there are 2 ways to do this, The first is like subclassing from python, another (disabled) method copies the base PyTypeObject struct 
and makes some changes.

The PyType is stored in the RNA Struct for reuse, right now there are no access functions - needs to be improved.

Added a python script for printing all blend file data to the console which helps testing the api.

dir(rna) wont work for python 2.x now, use rna.__dir__() instead.

Modified Paths:
--------------
    branches/blender2.5/blender/source/blender/makesrna/intern/makesrna.c
    branches/blender2.5/blender/source/blender/makesrna/intern/rna_internal_types.h
    branches/blender2.5/blender/source/blender/python/epy_doc_gen.py
    branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_operator.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_rna.h
    branches/blender2.5/blender/source/blender/python/intern/bpy_util.c

Added Paths:
-----------
    branches/blender2.5/blender/source/blender/python/rna_dump.py
    branches/blender2.5/blender/source/blender/python/simple_enum_gen.py

Modified: branches/blender2.5/blender/source/blender/makesrna/intern/makesrna.c
===================================================================
--- branches/blender2.5/blender/source/blender/makesrna/intern/makesrna.c	2009-03-11 06:04:17 UTC (rev 19258)
+++ branches/blender2.5/blender/source/blender/makesrna/intern/makesrna.c	2009-03-11 17:28:37 UTC (rev 19259)
@@ -1201,7 +1201,9 @@
 	else fprintf(f, "\tNULL, ");
 	if(srna->prev) fprintf(f, "&RNA_%s,\n", srna->prev->identifier);
 	else fprintf(f, "NULL,\n");
-
+	
+	fprintf(f, "\tNULL,\n"); /* PyType - Cant initialize here */
+	
 	fprintf(f, "\t");
 	rna_print_c_string(f, srna->identifier);
 	fprintf(f, ", %d, ", srna->flag);

Modified: branches/blender2.5/blender/source/blender/makesrna/intern/rna_internal_types.h
===================================================================
--- branches/blender2.5/blender/source/blender/makesrna/intern/rna_internal_types.h	2009-03-11 06:04:17 UTC (rev 19258)
+++ branches/blender2.5/blender/source/blender/makesrna/intern/rna_internal_types.h	2009-03-11 17:28:37 UTC (rev 19259)
@@ -208,6 +208,10 @@
 struct StructRNA {
 	struct StructRNA *next, *prev;
 
+	/* python type, this is a subtype of pyrna_struct_Type but used so each struct can have its own type
+	 * which is useful for subclassing RNA */
+	void *py_type;
+	
 	/* unique identifier */
 	const char *identifier;
 	/* various options */

Modified: branches/blender2.5/blender/source/blender/python/epy_doc_gen.py
===================================================================
--- branches/blender2.5/blender/source/blender/python/epy_doc_gen.py	2009-03-11 06:04:17 UTC (rev 19258)
+++ branches/blender2.5/blender/source/blender/python/epy_doc_gen.py	2009-03-11 17:28:37 UTC (rev 19259)
@@ -162,6 +162,7 @@
 	
 	
 	for rna_struct in structs:
+		# print(type(rna_struct))
 		if rna_struct.nested:
 			continue
 		

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c	2009-03-11 06:04:17 UTC (rev 19258)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c	2009-03-11 17:28:37 UTC (rev 19259)
@@ -80,6 +80,8 @@
 	
 	// todo - sys paths - our own imports
 	
+	BPY_rna_init_types();
+	
 	py_tstate = PyGILState_GetThisThreadState();
 	PyEval_ReleaseThread(py_tstate);
 	
@@ -90,8 +92,11 @@
 	PyGILState_Ensure(); /* finalizing, no need to grab the state */
 	
 	// free other python data.
+	//BPY_rna_free_types();
 	
 	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;
 }
 
@@ -123,7 +128,7 @@
 
 			if( PyErr_Occurred(  ) ) {
 				BPY_free_compiled_text( text );
-				return NULL;
+				return 0;
 			}
 		}
 		py_result =  PyEval_EvalCode( text->compiled, py_dict, py_dict );

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_operator.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_operator.c	2009-03-11 06:04:17 UTC (rev 19258)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_operator.c	2009-03-11 17:28:37 UTC (rev 19259)
@@ -190,10 +190,9 @@
 		return NULL;
 	}
 
-	pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); /* were not really using &ptr, overwite next */
-
 	/* XXX POINTER - if this 'ot' is python generated, it could be free'd */
-	RNA_pointer_create(NULL, ot->srna, NULL, &pyrna->ptr);
+	RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
+	pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); /* were not really using &ptr, overwite next */
 	pyrna->freeptr= 1;
 
 	return (PyObject *)pyrna;

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c	2009-03-11 06:04:17 UTC (rev 19258)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c	2009-03-11 17:28:37 UTC (rev 19259)
@@ -30,8 +30,11 @@
 #include "MEM_guardedalloc.h"
 #include "BKE_global.h" /* evil G.* */
 
-/* floats bigger then this are displayed as inf in the docstrings */
-#define MAXFLOAT_DOC 10000000
+/* 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 )
 {
@@ -565,27 +568,28 @@
 	( objobjargproc ) pyrna_prop_assign_subscript,	/* mp_ass_subscript */
 };
 
-//---------------getattr--------------------------------------------
-static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
+static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
 {
-	char *name = _PyUnicode_AsString(pyname);
-	PyObject *ret;
-	PropertyRNA *prop;
+	PyObject *ret, *dict;
+	PyObject *pystring = PyUnicode_FromString("__dict__");
 	
 	/* 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
 	 * */
-	ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
-	if (ret)	return ret;
-	else		PyErr_Clear();
-	/* done with subtypes */
-
-	prop = RNA_struct_find_property(&self->ptr, name);
+	dict = PyObject_GenericGetAttr((PyObject *)self, pystring);
+	Py_DECREF(pystring);
 	
-	if (prop) {
-		ret = pyrna_prop_to_py(&self->ptr, prop);
+	if (dict==NULL) {
+		PyErr_Clear();
+		ret = PyList_New(0);
 	}
-	else if (strcmp(name, "__dict__")==0) { /* Not quite correct, adding this so dir() gives good feedback */
+	else {
+		ret = PyDict_Keys(dict);
+		Py_DECREF(dict);
+	}
+	
+	/* Collect RNA items*/
+	{
 		PropertyRNA *iterprop, *nameprop;
 		CollectionPropertyIterator iter;
 		char name[256], *nameptr;
@@ -593,12 +597,14 @@
 		iterprop= RNA_struct_iterator_property(&self->ptr);
 		RNA_property_collection_begin(&self->ptr, iterprop, &iter);
 
-		ret = PyDict_New();
 		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));
-				PyDict_SetItemString(ret, nameptr, Py_None);
 				
+				pystring = PyUnicode_FromString(nameptr);
+				PyList_Append(ret, pystring);
+				Py_DECREF(pystring);
+				
 				if ((char *)&name != nameptr)
 					MEM_freeN(nameptr);
 			}
@@ -606,6 +612,31 @@
 		
 		RNA_property_collection_end(&iter);
 	}
+	
+	return ret;
+}
+
+
+//---------------getattr--------------------------------------------
+static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
+{
+	char *name = _PyUnicode_AsString(pyname);
+	PyObject *ret;
+	PropertyRNA *prop;
+	
+	/* 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
+	 * */
+	ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
+	if (ret)	return ret;
+	else		PyErr_Clear();
+	/* done with subtypes */
+
+	prop = RNA_struct_find_property(&self->ptr, name);
+	
+	if (prop) {
+		ret = pyrna_prop_to_py(&self->ptr, prop);
+	}
 	else {
 		PyErr_Format( PyExc_AttributeError, "Attribute \"%s\" not found", name);
 		ret = NULL;
@@ -765,10 +796,10 @@
 	return NULL;
 }
 
-/*static struct PyMethodDef pyrna_struct_methods[] = {
+static struct PyMethodDef pyrna_struct_methods[] = {
 	{"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, ""},
 	{NULL, NULL, 0, NULL}
-};*/
+};
 
 static struct PyMethodDef pyrna_prop_methods[] = {
 	{"keys", (PyCFunction)pyrna_prop_keys, METH_NOARGS, ""},
@@ -875,7 +906,7 @@
 	NULL,                       /* iternextfunc tp_iternext; */
 
   /*** Attribute descriptor and subclassing stuff ***/
-	NULL,			/* struct PyMethodDef *tp_methods; */
+	pyrna_struct_methods,			/* struct PyMethodDef *tp_methods; */
 	NULL,                       /* struct PyMemberDef *tp_members; */
 	NULL,      					/* struct PyGetSetDef *tp_getset; */
 	NULL,                       /* struct _typeobject *tp_base; */
@@ -990,12 +1021,32 @@
 {
 	BPy_StructRNA *pyrna;
 	
-	if (ptr->data==NULL) {
+	if (ptr->data==NULL && ptr->type==NULL) {
 		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);
+		pyrna = (BPy_StructRNA *) tp->tp_alloc(tp, 0);
+	}
+	else {
+		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;
@@ -1029,16 +1080,8 @@
 {
 	PointerRNA ptr;
 	
-	if( PyType_Ready( &pyrna_struct_Type ) < 0 )
-		return NULL;
+	/* 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_prop_Type ) < 0 )
-		return NULL;
-	
 	/* for now, return the base RNA type rather then a real module */
 	RNA_main_pointer_create(G.main, &ptr);
 	
@@ -1058,4 +1101,203 @@
 	return pyrna_struct_CreatePyObject(&ptr);
 }
 
+#ifdef PY_CLASS_SUBTYPE
+void BPY_rna_init_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;
+
+	
+	/* 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;
+		
+	
+	/* for now, return the base RNA type rather then a real module */

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list