[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [19347] branches/blender2.5/blender/source /blender/python: - lazy subtype initialization rna, was initializing every type in bpy.types at startup, which is slow and doesn't allow access to dynamically added types.

Campbell Barton ideasman42 at gmail.com
Sat Mar 21 07:55:30 CET 2009


Revision: 19347
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=19347
Author:   campbellbarton
Date:     2009-03-21 07:55:30 +0100 (Sat, 21 Mar 2009)

Log Message:
-----------
- lazy subtype initialization rna, was initializing every type in bpy.types at startup, which is slow and doesn't allow access to dynamically added types.
- bpy.types isnt a module anymore, defined as its own PyType, getattr looks up the rna collection each time.
- refcounting fixes
- fixe epydoc generation with undefined values
 

Modified Paths:
--------------
    branches/blender2.5/blender/source/blender/python/epy_doc_gen.py
    branches/blender2.5/blender/source/blender/python/intern/bpy_operator.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_opwrapper.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
    branches/blender2.5/blender/source/blender/python/rna_dump.py

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-21 04:51:51 UTC (rev 19346)
+++ branches/blender2.5/blender/source/blender/python/epy_doc_gen.py	2009-03-21 06:55:30 UTC (rev 19347)
@@ -41,8 +41,6 @@
 
 def rna2epy(target_path):
 	
-
-	
 	def write_struct(rna_struct, structs, ident):
 		identifier = rna_struct.identifier
 		
@@ -131,8 +129,11 @@
 	for rna_type_name in dir(bpy.types):
 		rna_type = getattr(bpy.types, rna_type_name)
 		if hasattr(rna_type, '__rna__'):
+			#if not rna_type_name.startswith('__'):
 			rna_struct = rna_type.__rna__
 			structs.append( (base_id(rna_struct), rna_struct.identifier, rna_struct) )	
+		else:
+			print("Ignoring", rna_type_name)
 	
 	
 	
@@ -160,7 +161,7 @@
 					i+=1
 					
 				if not ok:
-					print('Dependancy "%s"could not be found for "%s"' % (identifier, rna_base))
+					print('Dependancy "%s" could not be found for "%s"' % (identifier, rna_base))
 				
 				break
 	
@@ -199,7 +200,9 @@
 		kw_args = [] # "foo = 1", "bar=0.5", "spam='ENUM'"
 		kw_arg_attrs = [] # "@type mode: int"
 		
-		rna = getattr(bpy.types, op).__rna__
+		# rna = getattr(bpy.types, op).__rna__
+		rna = bpy.ops.__rna__(op)
+		
 		rna_struct = rna.rna_type
 		# print (dir(rna))
 		# print (dir(rna_struct))
@@ -217,14 +220,18 @@
 			
 			try:
 				val = getattr(rna, rna_prop_identifier)
+				val_error = False
 			except:
-				val = '<UNDEFINED>'
+				val = "'<UNDEFINED>'"
+				val_error = True
 			
 			kw_type_str= "@type %s: %s%s" % (rna_prop_identifier, rna_prop_type, array_str)
 			kw_param_str= "@param %s: %s" % (rna_prop_identifier, rna_prop.description)
 			kw_param_set = False
 			
-			if rna_prop_type=='float':
+			if val_error:
+				val_str = val
+			elif rna_prop_type=='float':
 				if length==0:
 					val_str= '%g' % val
 					if '.' not in val_str:

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-21 04:51:51 UTC (rev 19346)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_operator.c	2009-03-21 06:55:30 UTC (rev 19347)
@@ -108,8 +108,10 @@
 }
 
 static PyObject *pyop_base_dir(PyObject *self);
+static PyObject *pyop_base_rna(PyObject *self, PyObject *pyname);
 static struct PyMethodDef pyop_base_methods[] = {
 	{"__dir__", (PyCFunction)pyop_base_dir, METH_NOARGS, ""},
+	{"__rna__", (PyCFunction)pyop_base_rna, METH_O, ""},
 	{"add", (PyCFunction)PYOP_wrap_add, METH_O, ""},
 	{"remove", (PyCFunction)PYOP_wrap_remove, METH_O, ""},
 	{NULL, NULL, 0, NULL}
@@ -199,8 +201,9 @@
 {
 	char *name = _PyUnicode_AsString(pyname);
 	PyObject *ret;
+	wmOperatorType *ot;
 	
-	if ((WM_operatortype_find(name))) {
+	if ((ot= WM_operatortype_find(name))) {
 		ret = PyCFunction_New( pyop_base_call_meth, pyname); /* set the name string as self, PyCFunction_New incref's self */
 	}
 	else if ((ret = PyObject_GenericGetAttr((PyObject *)self, pyname))) {
@@ -235,6 +238,28 @@
 	return list;
 }
 
+static PyObject *pyop_base_rna(PyObject *self, PyObject *pyname)
+{
+	char *name = _PyUnicode_AsString(pyname);
+	wmOperatorType *ot;
+	
+	if ((ot= WM_operatortype_find(name))) {
+		BPy_StructRNA *pyrna;
+		PointerRNA ptr;
+		
+		/* XXX POINTER - if this 'ot' is python generated, it could be free'd */
+		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 pyrna;
+	}
+	else {
+		PyErr_SetString(PyExc_AttributeError, "Operator not found");
+		return NULL;
+	}
+}
+
 PyTypeObject pyop_base_Type = {NULL};
 
 PyObject *BPY_operator_module( bContext *C )

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_opwrapper.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_opwrapper.c	2009-03-21 04:51:51 UTC (rev 19346)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_opwrapper.c	2009-03-21 06:55:30 UTC (rev 19347)
@@ -384,7 +384,8 @@
 	//PyObject *optype = PyObject_GetAttrString(PyObject_GetAttrString(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), "types"), "Operator");
 	optype = PyObject_GetAttrStringArgs(PyDict_GetItemString(PyEval_GetGlobals(), "bpy"), 2, "types", "Operator");
 	Py_DECREF(optype);
-	
+
+
 	if (!PyObject_IsSubclass(value, optype)) {
 		PyErr_SetString( PyExc_AttributeError, "expected Operator subclass of bpy.types.Operator");
 		return NULL;
@@ -450,7 +451,6 @@
 		} else {
 			PyErr_Clear();
 		}
-		Py_XDECREF(item);
 	}
 	
 	/* If we have properties set, check its a list of dicts */

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-21 04:51:51 UTC (rev 19346)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_rna.c	2009-03-21 06:55:30 UTC (rev 19347)
@@ -574,22 +574,28 @@
 static PyObject *pyrna_struct_dir(BPy_StructRNA * self)
 {
 	PyObject *ret, *dict;
-	PyObject *pystring = PyUnicode_FromString("__dict__");
+	PyObject *pystring;
 	
 	/* 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
 	 * */
-	dict = PyObject_GenericGetAttr((PyObject *)self, pystring);
-	Py_DECREF(pystring);
-	
-	if (dict==NULL) {
-		PyErr_Clear();
+
+	if (BPy_StructRNA_CheckExact(self)) {
 		ret = PyList_New(0);
+	} else {
+		pystring = PyUnicode_FromString("__dict__");
+		dict = PyObject_GenericGetAttr((PyObject *)self, pystring);
+		Py_DECREF(pystring);
+
+		if (dict==NULL) {
+			PyErr_Clear();
+			ret = PyList_New(0);
+		}
+		else {
+			ret = PyDict_Keys(dict);
+			Py_DECREF(dict);
+		}
 	}
-	else {
-		ret = PyDict_Keys(dict);
-		Py_DECREF(dict);
-	}
 	
 	/* Collect RNA items*/
 	{
@@ -629,12 +635,12 @@
 	
 	/* 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
 	 * */
-	if (BPy_StructRNA_CheckExact(self) == 0) {
-		ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
-		if (ret)	return ret;
-		else		PyErr_Clear();
-	}
+	ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
+	if (ret)	return ret;
+	else		PyErr_Clear();
 	/* done with subtypes */
 
 	prop = RNA_struct_find_property(&self->ptr, name);
@@ -1061,6 +1067,8 @@
 
 	if (ptr->type==NULL) {
 		newclass= NULL; /* Nothing to do */
+	} else if ((newclass= BPy_RNA_PYTYPE(ptr->data))) {
+		Py_INCREF(newclass);
 	} else if ((nameprop = RNA_struct_name_property(ptr))) {
 		/* for now, return the base RNA type rather then a real module */
 		
@@ -1076,7 +1084,6 @@
 		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));
 		
@@ -1087,6 +1094,7 @@
 		// 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 
@@ -1100,9 +1108,11 @@
 		newclass = PyObject_CallObject((PyObject *)&PyType_Type, args);
 		// Set this later
 		
+
 		if (newclass) {
+			PyObject *rna;
 			BPy_RNA_PYTYPE(ptr->data) = (void *)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);
@@ -1110,6 +1120,7 @@
 			Py_DECREF(rna);
 			/* done with rna instance */
 		}
+		
 		Py_DECREF(args);
 		
 		if ((char *)&name != nameptr)
@@ -1123,15 +1134,23 @@
 /*-----------------------CreatePyObject---------------------------------*/
 PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr )
 {
-	BPy_StructRNA *pyrna;
+	BPy_StructRNA *pyrna= NULL;
+	int tp_init= 0;
 	
 	if (ptr->data==NULL && ptr->type==NULL) { /* Operator RNA has NULL data */
 		Py_RETURN_NONE;
 	}
 	
-	if (ptr->type && BPy_RNA_PYTYPE(ptr->type)) {
-		PyTypeObject *tp = BPy_RNA_PYTYPE(ptr->type);
-		pyrna = (BPy_StructRNA *) tp->tp_alloc(tp, 0);
+	if (ptr->type == &RNA_Struct) { /* always return a python subtype from rna struct types */
+		PyTypeObject *tp = pyrna_struct_Subtype(ptr);
+		
+		if (tp) {
+			pyrna = (BPy_StructRNA *) tp->tp_alloc(tp, 0);
+		}
+		else {
+			fprintf(stderr, "Could not make type\n");
+			pyrna = ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, &pyrna_struct_Type );
+		}
 	}
 	else {
 		pyrna = ( BPy_StructRNA * ) PyObject_NEW( BPy_StructRNA, &pyrna_struct_Type );
@@ -1144,7 +1163,6 @@
 	
 	pyrna->ptr= *ptr;
 	pyrna->freeptr= 0;
-	
 	return ( PyObject * ) pyrna;
 }
 
@@ -1201,51 +1219,75 @@
 }
 #endif
 
- PyObject *BPY_rna_types(void)
- {
-	/* Now initialize new subtypes based on pyrna_struct_Type */
-	PointerRNA ptr;
 
-	CollectionPropertyIterator iter;
-	PropertyRNA *prop;
-
-	PyObject *mod, *dict, *type, *name;
- 
-	mod = PyModule_New("types");
-	dict = PyModule_GetDict(mod);
+/* pyrna_basetype_* - BPy_BaseTypeRNA is just a BPy_PropertyRNA struct with a differnt type
+ * the self->ptr and self->prop are always set to the "structs" collection */
+//---------------getattr--------------------------------------------
+static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA * self, PyObject *pyname )
+{
+	PointerRNA newptr;
+	PyObject *ret;
 	
-	/* 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");
+	ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
+	if (ret)	return ret;
+	else		PyErr_Clear();
 	
-	RNA_property_collection_begin(&ptr, prop, &iter);
-	for(; iter.valid; RNA_property_collection_next(&iter)) {
-		if(iter.ptr.data) {
-			type = (PyObject *)BPy_RNA_PYTYPE(iter.ptr.data);
-			if (type==NULL) {
-				type = pyrna_struct_Subtype(&iter.ptr);
-			}
-			if (type) {
-				name = PyObject_GetAttrString(type, "__name__"); /* myClass.__name__ */
-				if (name) {
-					Py_DECREF(name);
-					PyDict_SetItem(dict, name, type);
-				}
-				else {

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list