From ffe7bde02c5725993e9c1986bbc8a83174adbbb8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 1 Feb 2011 12:37:53 +0000 Subject: 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. --- source/blender/blenkernel/intern/report.c | 2 +- source/blender/python/generic/py_capi_utils.c | 18 ++++++++++++++++++ source/blender/python/generic/py_capi_utils.h | 3 +++ source/blender/python/intern/bpy_interface.c | 21 +++++++++++++++------ 4 files changed, 37 insertions(+), 7 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index e623c095ac7..044e1350be1 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -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); diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index d29587a084b..9f7a9f2cabe 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -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, ...) diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index f786fd80269..ccdbde5cecb 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -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 diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 444cda0cc88..776f2da8507 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -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(""); 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(""); 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; -- cgit v1.2.3