diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c index f9d7e8371b2..f739bfe367e 100644 --- a/source/blender/editors/space_script/script_edit.c +++ b/source/blender/editors/space_script/script_edit.c @@ -120,7 +120,8 @@ static int script_reload_exec(bContext *C, wmOperator *op) /* TODO, this crashes on netrender and keying sets, need to look into why * disable for now unless running in debug mode */ WM_cursor_wait(1); - BPY_run_string(C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)"); + BPY_run_string_eval( + C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)"); WM_cursor_wait(0); WM_event_add_notifier(C, NC_WINDOW, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h index e2022c1de85..50ebacbd6e8 100644 --- a/source/blender/freestyle/intern/system/PythonInterpreter.h +++ b/source/blender/freestyle/intern/system/PythonInterpreter.h @@ -102,7 +102,7 @@ class PythonInterpreter : public Interpreter { BKE_reports_clear(reports); - if (!BPY_run_string(_context, NULL, str.c_str())) { + if (!BPY_run_string_eval(_context, NULL, str.c_str())) { BPy_errors_to_report(reports); cerr << "\nError executing Python script from PythonInterpreter::interpretString" << endl; cerr << "Name: " << name << endl; diff --git a/source/blender/python/BPY_extern_run.h b/source/blender/python/BPY_extern_run.h index 67ac56f2798..5f12ada4ff2 100644 --- a/source/blender/python/BPY_extern_run.h +++ b/source/blender/python/BPY_extern_run.h @@ -37,6 +37,12 @@ bool BPY_run_text(struct bContext *C, struct ReportList *reports, const bool do_jump); +/* Use the 'eval' for simple single-line expressions, + * otherwise 'exec' for full multi-line scripts. */ +bool BPY_run_string_exec(struct bContext *C, const char *imports[], const char *expr); +bool BPY_run_string_eval(struct bContext *C, const char *imports[], const char *expr); + +/* Run, evaluating to fixed type result. */ bool BPY_run_string_as_number(struct bContext *C, const char *imports[], const char *expr, @@ -59,10 +65,6 @@ bool BPY_run_string_as_string(struct bContext *C, const char *report_prefix, char **r_value); -bool BPY_run_string_ex(struct bContext *C, const char *imports[], const char *expr, bool use_eval); - -bool BPY_run_string(struct bContext *C, const char *imports[], const char *expr); - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/source/blender/python/intern/bpy_interface_run.c b/source/blender/python/intern/bpy_interface_run.c index f936be2edbf..9f9382b633c 100644 --- a/source/blender/python/intern/bpy_interface_run.c +++ b/source/blender/python/intern/bpy_interface_run.c @@ -208,7 +208,14 @@ bool BPY_run_text(bContext *C, struct Text *text, struct ReportList *reports, co return python_script_exec(C, NULL, text, reports, do_jump); } -bool BPY_run_string_ex(bContext *C, const char *imports[], const char *expr, bool use_eval) +/** + * \param mode: Passed to #PyRun_String, matches Python's `compile` functions mode argument. + * #Py_eval_input for `eval`, #Py_file_input for `exec`. + */ +static bool bpy_run_string_impl(bContext *C, + const char *imports[], + const char *expr, + const int mode) { BLI_assert(expr); PyGILState_STATE gilstate; @@ -231,7 +238,7 @@ bool BPY_run_string_ex(bContext *C, const char *imports[], const char *expr, boo retval = NULL; } else { - retval = PyRun_String(expr, use_eval ? Py_eval_input : Py_file_input, py_dict, py_dict); + retval = PyRun_String(expr, mode, py_dict, py_dict); } if (retval == NULL) { @@ -249,9 +256,20 @@ bool BPY_run_string_ex(bContext *C, const char *imports[], const char *expr, boo return ok; } -bool BPY_run_string(bContext *C, const char *imports[], const char *expr) +/** + * Run an expression, matches: `exec(compile(..., "eval"))` + */ +bool BPY_run_string_eval(bContext *C, const char *imports[], const char *expr) { - return BPY_run_string_ex(C, imports, expr, true); + return bpy_run_string_impl(C, imports, expr, Py_eval_input); +} + +/** + * Run an entire script, matches: `exec(compile(..., "exec"))` + */ +bool BPY_run_string_exec(bContext *C, const char *imports[], const char *expr) +{ + return bpy_run_string_impl(C, imports, expr, Py_file_input); } /** \} */ diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 22210012bb6..5d0520bb674 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -271,7 +271,7 @@ void WM_keyconfig_reload(bContext *C) { if (CTX_py_init_get(C) && !G.background) { #ifdef WITH_PYTHON - BPY_run_string(C, (const char *[]){"bpy", NULL}, "bpy.utils.keyconfig_init()"); + BPY_run_string_eval(C, (const char *[]){"bpy", NULL}, "bpy.utils.keyconfig_init()"); #endif } } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 1be22b2283c..62d9c099cd5 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -580,14 +580,14 @@ static void wm_file_read_post(bContext *C, if (use_userdef || reset_app_template) { /* Only run when we have a template path found. */ if (BKE_appdir_app_template_any()) { - BPY_run_string( + BPY_run_string_eval( C, (const char *[]){"bl_app_template_utils", NULL}, "bl_app_template_utils.reset()"); reset_all = true; } } if (reset_all) { /* sync addons, these may have changed from the defaults */ - BPY_run_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()"); + BPY_run_string_eval(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()"); } if (use_data) { BPY_python_reset(C); @@ -924,7 +924,7 @@ void wm_homefile_read(bContext *C, * * Note that this fits into 'wm_file_read_pre' function but gets messy * since we need to know if 'reset_app_template' is true. */ - BPY_run_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.disable_all()"); + BPY_run_string_eval(C, (const char *[]){"addon_utils", NULL}, "addon_utils.disable_all()"); } #endif /* WITH_PYTHON */ } diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 90c01436520..164e670c444 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -1852,7 +1852,7 @@ static int arg_handle_python_expr_run(int argc, const char **argv, void *data) /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */ if (argc > 1) { bool ok; - BPY_CTX_SETUP(ok = BPY_run_string_ex(C, NULL, argv[1], false)); + BPY_CTX_SETUP(ok = BPY_run_string_exec(C, NULL, argv[1])); if (!ok && app_state.exit_code_on_error.python) { printf("\nError: script failed, expr: '%s', exiting.\n", argv[1]); BPY_python_end(); @@ -1879,7 +1879,7 @@ static int arg_handle_python_console_run(int UNUSED(argc), const char **argv, vo # ifdef WITH_PYTHON bContext *C = data; - BPY_CTX_SETUP(BPY_run_string(C, (const char *[]){"code", NULL}, "code.interact()")); + BPY_CTX_SETUP(BPY_run_string_eval(C, (const char *[]){"code", NULL}, "code.interact()")); return 0; # else @@ -1952,7 +1952,7 @@ static int arg_handle_addons_set(int argc, const char **argv, void *data) BLI_snprintf(str, slen, script_str, argv[1]); BLI_assert(strlen(str) + 1 == slen); - BPY_CTX_SETUP(BPY_run_string_ex(C, NULL, str, false)); + BPY_CTX_SETUP(BPY_run_string_exec(C, NULL, str)); free(str); # else UNUSED_VARS(argv, data);