[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [20991] branches/blender2.5/blender: 2. 5 Python

Brecht Van Lommel brecht at blender.org
Thu Jun 18 21:51:22 CEST 2009


Revision: 20991
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20991
Author:   blendix
Date:     2009-06-18 21:51:22 +0200 (Thu, 18 Jun 2009)

Log Message:
-----------
2.5 Python

Merging changes made by Arystanbek in the soc-2009-kazanbas branch,
plus some things modified and added by me.

* Operator exec is called execute in python now, due to conflicts
  with python exec keyword.
* Operator invoke/execute now get context argument.
* Fix crash executing operators due to bpy_import_main_set not being
  set with Main pointer.
* The bpy.props module now has the FloatProperty/IntProperty/
  StringProperty/BoolProperty functions to define RNA properties for
  operators.
* Operators now have an __operator__ property to get the actual RNA
  operator pointers, this is only temporary though.
* bpy.ops.add now allows the operator to be already registered, it
  will simply overwrite the existing one.
* Both the ui and io directories are now scanned and run on startup.

Modified Paths:
--------------
    branches/blender2.5/blender/SConstruct
    branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_operator_wrap.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

Modified: branches/blender2.5/blender/SConstruct
===================================================================
--- branches/blender2.5/blender/SConstruct	2009-06-18 19:48:55 UTC (rev 20990)
+++ branches/blender2.5/blender/SConstruct	2009-06-18 19:51:22 UTC (rev 20991)
@@ -468,28 +468,18 @@
 			dotblenderinstall.append(env.Install(dir=td, source=srcfile))
 		
 		if env['WITH_BF_PYTHON']:
-			#-- .blender/scripts	
-			scriptpath='release/scripts'
-			for dp, dn, df in os.walk(scriptpath):
-				if 'CVS' in dn:
-					dn.remove('CVS')
-				if '.svn' in dn:
-					dn.remove('.svn')
-				dir=env['BF_INSTALLDIR']+'/.blender/scripts'+dp[len(scriptpath):]
-				source=[dp+os.sep+f for f in df]
-				scriptinstall.append(env.Install(dir=dir,source=source))
+			#-- .blender/scripts, .blender/ui, .blender/io
+			scriptpaths=['release/scripts', 'release/ui', 'release/io']
+			for scriptpath in scriptpaths:
+				for dp, dn, df in os.walk(scriptpath):
+					if 'CVS' in dn:
+						dn.remove('CVS')
+					if '.svn' in dn:
+						dn.remove('.svn')
+					dir=env['BF_INSTALLDIR']+'/.blender/'+os.path.basename(scriptpath)+dp[len(scriptpath):]
+					source=[dp+os.sep+f for f in df]
+					scriptinstall.append(env.Install(dir=dir,source=source))
 
-			#-- .blender/ui	
-			scriptpath='release/ui'
-			for dp, dn, df in os.walk(scriptpath):
-				if 'CVS' in dn:
-					dn.remove('CVS')
-				if '.svn' in dn:
-					dn.remove('.svn')
-				dir=env['BF_INSTALLDIR']+'/.blender/ui'+dp[len(scriptpath):]
-				source=[dp+os.sep+f for f in df]
-				scriptinstall.append(env.Install(dir=dir,source=source))
-
 #-- icons
 if env['OURPLATFORM']=='linux2':
 	iconlist = []

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c	2009-06-18 19:48:55 UTC (rev 20990)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c	2009-06-18 19:51:22 UTC (rev 20991)
@@ -59,6 +59,7 @@
 	PyModule_AddObject( mod, "data", BPY_rna_module() );
 	/* 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() );
 	PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
 	
@@ -103,6 +104,7 @@
 			{"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""},
 			{"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""},
 			{"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""},
+			{"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS|METH_KEYWORDS, ""},
 			{NULL, NULL, 0, NULL}
 		};
 		
@@ -369,71 +371,77 @@
 	DIR *dir; 
 	struct dirent *de;
 	char *file_extension;
+	char *dirname;
 	char path[FILE_MAX];
-	char *dirname= BLI_gethome_folder("ui");
-	int filelen; /* filename length */
+	char *dirs[] = {"io", "ui", NULL};
+	int a, filelen; /* filename length */
 	
 	PyGILState_STATE gilstate;
 	PyObject *mod;
 	PyObject *sys_path_orig;
 	PyObject *sys_path_new;
-	
-	if(!dirname)
-		return;
-	
-	dir = opendir(dirname);
 
-	if(!dir)
-		return;
-	
 	gilstate = PyGILState_Ensure();
 	
-	/* backup sys.path */
-	sys_path_orig= PySys_GetObject("path");
-	Py_INCREF(sys_path_orig); /* dont free it */
-	
-	sys_path_new= PyList_New(1);
-	PyList_SET_ITEM(sys_path_new, 0, PyUnicode_FromString(dirname));
-	PySys_SetObject("path", sys_path_new);
-	Py_DECREF(sys_path_new);
-	
 	// XXX - evil, need to access context
 	BPy_SetContext(C);
 	bpy_import_main_set(CTX_data_main(C));
-	
-	while((de = readdir(dir)) != NULL) {
-		/* We could stat the file but easier just to let python
-		 * import it and complain if theres a problem */
+
+	for(a=0; dirs[a]; a++) {
+		dirname= BLI_gethome_folder(dirs[a]);
+
+		if(!dirname)
+			continue;
+
+		dir = opendir(dirname);
+
+		if(!dir)
+			continue;
+
+		/* backup sys.path */
+		sys_path_orig= PySys_GetObject("path");
+		Py_INCREF(sys_path_orig); /* dont free it */
 		
-		file_extension = strstr(de->d_name, ".py");
-		
-		if(file_extension && *(file_extension + 3) == '\0') {
-			filelen = strlen(de->d_name);
-			BLI_strncpy(path, de->d_name, filelen-2); /* cut off the .py on copy */
+		sys_path_new= PyList_New(1);
+		PyList_SET_ITEM(sys_path_new, 0, PyUnicode_FromString(dirname));
+		PySys_SetObject("path", sys_path_new);
+		Py_DECREF(sys_path_new);
 			
-			mod= PyImport_ImportModuleLevel(path, NULL, NULL, NULL, 0);
-			if (mod) {
-				if (reload) {
-					PyObject *mod_orig= mod;
-					mod= PyImport_ReloadModule(mod);
-					Py_DECREF(mod_orig);
+		while((de = readdir(dir)) != NULL) {
+			/* We could stat the file but easier just to let python
+			 * import it and complain if theres a problem */
+			
+			file_extension = strstr(de->d_name, ".py");
+			
+			if(file_extension && *(file_extension + 3) == '\0') {
+				filelen = strlen(de->d_name);
+				BLI_strncpy(path, de->d_name, filelen-2); /* cut off the .py on copy */
+				
+				mod= PyImport_ImportModuleLevel(path, NULL, NULL, NULL, 0);
+				if (mod) {
+					if (reload) {
+						PyObject *mod_orig= mod;
+						mod= PyImport_ReloadModule(mod);
+						Py_DECREF(mod_orig);
+					}
 				}
+				
+				if(mod) {
+					Py_DECREF(mod); /* could be NULL from reloading */
+				} else {
+					BPy_errors_to_report(NULL); // TODO - reports
+					fprintf(stderr, "unable to import \"%s\"  %s/%s\n", path, dirname, de->d_name);
+				}
+
 			}
-			
-			if(mod) {
-				Py_DECREF(mod); /* could be NULL from reloading */
-			} else {
-				BPy_errors_to_report(NULL); // TODO - reports
-				fprintf(stderr, "unable to import \"%s\"  %s/%s\n", path, dirname, de->d_name);
-			}
 		}
+
+		closedir(dir);
+
+		PySys_SetObject("path", sys_path_orig);
+		Py_DECREF(sys_path_orig);
 	}
-
-	closedir(dir);
 	
-	PySys_SetObject("path", sys_path_orig);
-	Py_DECREF(sys_path_orig);
-	
 	bpy_import_main_set(NULL);
 	
 	PyGILState_Release(gilstate);

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_operator_wrap.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_operator_wrap.c	2009-06-18 19:48:55 UTC (rev 20990)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_operator_wrap.c	2009-06-18 19:51:22 UTC (rev 20991)
@@ -40,6 +40,8 @@
 #include "bpy_compat.h"
 #include "bpy_util.h"
 
+#include "../generic/bpy_internal_import.h" // our own imports
+
 #define PYOP_ATTR_PROP			"__props__"
 #define PYOP_ATTR_UINAME		"__label__"
 #define PYOP_ATTR_IDNAME		"__name__"	/* use pythons class name */
@@ -177,9 +179,12 @@
 	PyObject *ret= NULL, *py_class_instance, *item= NULL;
 	int ret_flag= (mode==PYOP_POLL ? 0:OPERATOR_CANCELLED);
 	PointerRNA ptr_context;
-	PyObject *py_context;
+	PointerRNA ptr_operator;
+	PyObject *py_operator;
 
 	PyGILState_STATE gilstate = PyGILState_Ensure();
+
+	bpy_import_main_set(CTX_data_main(C));
 	
 	BPY_update_modules(); // XXX - the RNA pointers can change so update before running, would like a nicer solutuon for this.
 
@@ -213,20 +218,29 @@
 
 			RNA_property_collection_end(&iter);
 		}
+
+		/* set operator pointer RNA as instance "__operator__" attribute */
+		RNA_pointer_create(NULL, &RNA_Operator, op, &ptr_operator);
+		py_operator= pyrna_struct_CreatePyObject(&ptr_operator);
+		PyObject_SetAttrString(py_class_instance, "__operator__", py_operator);
+		Py_DECREF(py_operator);
+
+		RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
 		
-		
 		if (mode==PYOP_INVOKE) {
 			item= PyObject_GetAttrString(py_class, "invoke");
-			args = PyTuple_New(2);
-			PyTuple_SET_ITEM(args, 1, pyop_dict_from_event(event));
+			args = PyTuple_New(3);
+
+			// PyTuple_SET_ITEM "steals" object reference, it is
+			// an object passed shouldn't be DECREF'ed
+			PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
+			PyTuple_SET_ITEM(args, 2, pyop_dict_from_event(event));
 		}
 		else if (mode==PYOP_EXEC) {
-			item= PyObject_GetAttrString(py_class, "exec");
+			item= PyObject_GetAttrString(py_class, "execute");
 			args = PyTuple_New(2);
 			
-			RNA_pointer_create(NULL, &RNA_Context, C, &ptr_context);
-			py_context = pyrna_struct_CreatePyObject(&ptr_context);
-			PyTuple_SET_ITEM(args, 1, py_context);
+			PyTuple_SET_ITEM(args, 1, pyrna_struct_CreatePyObject(&ptr_context));
 		}
 		else if (mode==PYOP_POLL) {
 			item= PyObject_GetAttrString(py_class, "poll");
@@ -258,7 +272,8 @@
 		} else if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) {
 			 /* the returned value could not be converted into a flag */
 			BPy_errors_to_report(op->reports);
-			
+
+			ret_flag = OPERATOR_CANCELLED;
 		}
 		/* there is no need to copy the py keyword dict modified by
 		 * pyot->py_invoke(), back to the operator props since they are just
@@ -271,7 +286,34 @@
 		Py_DECREF(ret);
 	}
 
+	/* print operator return value */
+	if (mode != PYOP_POLL) {
+		char flag_str[100];
+		char class_name[100];
+		BPY_flag_def *flag_def = pyop_ret_flags;
+
+		strcpy(flag_str, "");
+		
+		while(flag_def->name) {
+			if (ret_flag & flag_def->flag) {
+				if(flag_str[1])
+					sprintf(flag_str, "%s | %s", flag_str, flag_def->name);
+				else
+					strcpy(flag_str, flag_def->name);
+			}
+			flag_def++;
+		}
+
+		/* get class name */
+		item= PyObject_GetAttrString(py_class, PYOP_ATTR_IDNAME);
+		Py_DECREF(item);
+		strcpy(class_name, _PyUnicode_AsString(item));
+
+		fprintf(stderr, "%s's %s returned %s\n", class_name, mode == PYOP_EXEC ? "execute" : "invoke", flag_str);
+	}
+
 	PyGILState_Release(gilstate);
+	bpy_import_main_set(NULL);
 
 	return ret_flag;
 }
@@ -321,7 +363,7 @@
 	/* api callbacks, detailed checks dont on adding */ 
 	if (PyObject_HasAttrString(py_class, "invoke"))
 		ot->invoke= PYTHON_OT_invoke;
-	if (PyObject_HasAttrString(py_class, "exec"))
+	if (PyObject_HasAttrString(py_class, "execute"))
 		ot->exec= PYTHON_OT_exec;
 	if (PyObject_HasAttrString(py_class, "poll"))
 		ot->poll= PYTHON_OT_poll;
@@ -374,6 +416,7 @@
 PyObject *PYOP_wrap_add(PyObject *self, PyObject *py_class)
 {	
 	PyObject *base_class, *item;
+	wmOperatorType *ot;
 	
 	
 	char *idname= NULL;
@@ -384,8 +427,8 @@
 		{PYOP_ATTR_UINAME,		's', 0,	BPY_CLASS_ATTR_OPTIONAL},
 		{PYOP_ATTR_PROP,		'l', 0,	BPY_CLASS_ATTR_OPTIONAL},
 		{PYOP_ATTR_DESCRIPTION,	's', 0,	BPY_CLASS_ATTR_NONE_OK},

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list