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.
This commit is contained in:
@@ -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, ...)
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user