[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [34603] trunk/blender/source/blender: correct fix for bug #23871, __main__ module was being overwritten in nested functions, so on returning from calling operators the __main__ module could be cleared and imported modules turn into None

Campbell Barton ideasman42 at gmail.com
Tue Feb 1 13:37:54 CET 2011


Revision: 34603
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=34603
Author:   campbellbarton
Date:     2011-02-01 12:37:53 +0000 (Tue, 01 Feb 2011)
Log Message:
-----------
correct fix for bug #23871, __main__ module was being overwritten in nested functions, so on returning from calling operators the __main__ module could be cleared and imported modules turn into None

calling
  bpy.ops.wm.read_factory_settings()
... would clear a scripts namespace if running directly, not in a module.


Fix by backing up and restoring the __main__ module.

Also found BKE_reportf wasnt printing all reports in background mode as BKE_report() was doing.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/report.c
    trunk/blender/source/blender/python/generic/py_capi_utils.c
    trunk/blender/source/blender/python/generic/py_capi_utils.h
    trunk/blender/source/blender/python/intern/bpy_interface.c

Modified: trunk/blender/source/blender/blenkernel/intern/report.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/report.c	2011-02-01 11:54:05 UTC (rev 34602)
+++ trunk/blender/source/blender/blenkernel/intern/report.c	2011-02-01 12:37:53 UTC (rev 34603)
@@ -124,7 +124,7 @@
 	Report *report;
 	va_list args;
 
-	if(!reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
+	if(G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
 		va_start(args, format);
 		vprintf(format, args);
 		va_end(args);

Modified: trunk/blender/source/blender/python/generic/py_capi_utils.c
===================================================================
--- trunk/blender/source/blender/python/generic/py_capi_utils.c	2011-02-01 11:54:05 UTC (rev 34602)
+++ trunk/blender/source/blender/python/generic/py_capi_utils.c	2011-02-01 12:37:53 UTC (rev 34603)
@@ -282,6 +282,10 @@
   for 'pickle' to work as well as strings like this...
  >> foo = 10
  >> print(__import__("__main__").foo)
+*
+* note: this overwrites __main__ which gives problems with nested calles.
+* be sure to run PyC_MainModule_Backup & PyC_MainModule_Restore if there is
+* any chance that python is in the call stack.
 *****************************************************************************/
 PyObject *PyC_DefaultNameSpace(const char *filename)
 {
@@ -297,7 +301,21 @@
 	return PyModule_GetDict(mod_main);
 }
 
+/* restore MUST be called after this */
+void PyC_MainModule_Backup(PyObject **main_mod)
+{
+	PyInterpreterState *interp= PyThreadState_GET()->interp;
+	*main_mod= PyDict_GetItemString(interp->modules, "__main__");
+	Py_XINCREF(*main_mod); /* dont free */
+}
 
+void PyC_MainModule_Restore(PyObject *main_mod)
+{
+	PyInterpreterState *interp= PyThreadState_GET()->interp;
+	PyDict_SetItemString(interp->modules, "__main__", main_mod);
+	Py_XDECREF(main_mod);
+}
+
 /* Would be nice if python had this built in */
 void PyC_RunQuicky(const char *filepath, int n, ...)
 {

Modified: trunk/blender/source/blender/python/generic/py_capi_utils.h
===================================================================
--- trunk/blender/source/blender/python/generic/py_capi_utils.h	2011-02-01 11:54:05 UTC (rev 34602)
+++ trunk/blender/source/blender/python/generic/py_capi_utils.h	2011-02-01 12:37:53 UTC (rev 34603)
@@ -39,4 +39,7 @@
 /* name namespace function for bpy & bge */
 PyObject *		PyC_DefaultNameSpace(const char *filename);
 void			PyC_RunQuicky(const char *filepath, int n, ...);
+
+void PyC_MainModule_Backup(PyObject **main_mod);
+void PyC_MainModule_Restore(PyObject *main_mod);
 #endif // PY_CAPI_UTILS_H

Modified: trunk/blender/source/blender/python/intern/bpy_interface.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_interface.c	2011-02-01 11:54:05 UTC (rev 34602)
+++ trunk/blender/source/blender/python/intern/bpy_interface.c	2011-02-01 12:37:53 UTC (rev 34603)
@@ -328,6 +328,7 @@
 
 static int python_script_exec(bContext *C, const char *fn, struct Text *text, struct ReportList *reports)
 {
+	PyObject *main_mod= NULL;
 	PyObject *py_dict= NULL, *py_result= NULL;
 	PyGILState_STATE gilstate;
 
@@ -339,6 +340,8 @@
 
 	bpy_context_set(C, &gilstate);
 
+	PyC_MainModule_Backup(&main_mod);
+
 	if (text) {
 		char fn_dummy[FILE_MAXDIR];
 		bpy_text_filename_get(fn_dummy, text);
@@ -413,10 +416,10 @@
 #endif
 
 #undef PYMODULE_CLEAR_WORKAROUND
-		/* normal */
-		PyDict_SetItemString(PyThreadState_GET()->interp->modules, "__main__", Py_None);
 	}
 
+	PyC_MainModule_Restore(main_mod);
+
 	bpy_context_clear(C, &gilstate);
 
 	return (py_result != NULL);
@@ -446,6 +449,7 @@
 	PyGILState_STATE gilstate;
 	PyObject *py_dict, *mod, *retval;
 	int error_ret = 0;
+	PyObject *main_mod= NULL;
 	
 	if (!value || !expr) return -1;
 
@@ -455,7 +459,9 @@
 	}
 
 	bpy_context_set(C, &gilstate);
-	
+
+	PyC_MainModule_Backup(&main_mod);
+
 	py_dict= PyC_DefaultNameSpace("<blender button>");
 
 	mod = PyImport_ImportModule("math");
@@ -506,7 +512,7 @@
 		BPy_errors_to_report(CTX_wm_reports(C));
 	}
 
-	PyDict_SetItemString(PyThreadState_GET()->interp->modules, "__main__", Py_None);
+	PyC_MainModule_Backup(&main_mod);
 	
 	bpy_context_clear(C, &gilstate);
 	
@@ -516,6 +522,7 @@
 int BPY_string_exec(bContext *C, const char *expr)
 {
 	PyGILState_STATE gilstate;
+	PyObject *main_mod= NULL;
 	PyObject *py_dict, *retval;
 	int error_ret = 0;
 
@@ -527,6 +534,8 @@
 
 	bpy_context_set(C, &gilstate);
 
+	PyC_MainModule_Backup(&main_mod);
+
 	py_dict= PyC_DefaultNameSpace("<blender string>");
 
 	retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
@@ -540,8 +549,8 @@
 		Py_DECREF(retval);
 	}
 
-	PyDict_SetItemString(PyThreadState_GET()->interp->modules, "__main__", Py_None);
-	
+	PyC_MainModule_Restore(main_mod);
+
 	bpy_context_clear(C, &gilstate);
 	
 	return error_ret;




More information about the Bf-blender-cvs mailing list