correct fix for bug #23871, __main__ module was being overwritten in nested functions...
authorCampbell Barton <ideasman42@gmail.com>
Tue, 1 Feb 2011 12:37:53 +0000 (12:37 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 1 Feb 2011 12:37:53 +0000 (12:37 +0000)
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.

source/blender/blenkernel/intern/report.c
source/blender/python/generic/py_capi_utils.c
source/blender/python/generic/py_capi_utils.h
source/blender/python/intern/bpy_interface.c

index e623c095ac7b03a34bbba5bb7a3b6733a1e701b1..044e1350be1c75da490d32dd8d61fbc5be7de034 100644 (file)
@@ -124,7 +124,7 @@ void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...)
        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);
index d29587a084b79cf189501af93a1ae5f4c030b32d..9f7a9f2cabe184b435f5e0aab1b5736296e59e47 100644 (file)
@@ -282,6 +282,10 @@ PyObject *PyC_UnicodeFromByte(const char *str)
   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,6 +301,20 @@ PyObject *PyC_DefaultNameSpace(const char *filename)
        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, ...)
index f786fd80269acd4c3edeafb9fd67f06e04920a26..ccdbde5cecb67fc9b18bb8e2bdcc4927676551c0 100644 (file)
@@ -39,4 +39,7 @@ const char *  PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce); /* coerce m
 /* 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
index 444cda0cc8853916b9565f3e89c2d94a65b8eeab..776f2da8507779a8cad610b3fe220fa8933ab163 100644 (file)
@@ -328,6 +328,7 @@ typedef struct {
 
 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 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text, st
 
        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 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text, st
 #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 @@ int BPY_button_exec(bContext *C, const char *expr, double *value)
        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 @@ int BPY_button_exec(bContext *C, const char *expr, double *value)
        }
 
        bpy_context_set(C, &gilstate);
-       
+
+       PyC_MainModule_Backup(&main_mod);
+
        py_dict= PyC_DefaultNameSpace("<blender button>");
 
        mod = PyImport_ImportModule("math");
@@ -506,7 +512,7 @@ int BPY_button_exec(bContext *C, const char *expr, double *value)
                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_button_exec(bContext *C, const char *expr, double *value)
 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 @@ int BPY_string_exec(bContext *C, const char *expr)
 
        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 @@ int BPY_string_exec(bContext *C, const char *expr)
                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;