Cleanup: move Python script execution into BPY_extern_run.h
This commit renames 'execute' to 'run' because: - This follows Python's "PyRun" which these functions wrap. - Execution functions can use either exec/eval modes, making naming awkward (for future API refactoring).
This commit is contained in:
@@ -69,7 +69,9 @@
|
|||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
|
|
||||||
#include "BPY_extern.h"
|
#ifdef WITH_PYTHON
|
||||||
|
# include "BPY_extern_run.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ED_numinput.h"
|
#include "ED_numinput.h"
|
||||||
#include "ED_screen.h"
|
#include "ED_screen.h"
|
||||||
@@ -2812,7 +2814,7 @@ char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report a generic error prefix when evaluating a string with #BPY_execute_string_as_number
|
* Report a generic error prefix when evaluating a string with #BPY_run_string_as_number
|
||||||
* as the Python error on it's own doesn't provide enough context.
|
* as the Python error on it's own doesn't provide enough context.
|
||||||
*/
|
*/
|
||||||
#define UI_NUMBER_EVAL_ERROR_PREFIX IFACE_("Error evaluating number, see Info editor for details")
|
#define UI_NUMBER_EVAL_ERROR_PREFIX IFACE_("Error evaluating number, see Info editor for details")
|
||||||
@@ -2837,7 +2839,7 @@ static bool ui_number_from_string(bContext *C, const char *str, double *r_value)
|
|||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
ok = BPY_execute_string_as_number(C, NULL, str, UI_NUMBER_EVAL_ERROR_PREFIX, r_value);
|
ok = BPY_run_string_as_number(C, NULL, str, UI_NUMBER_EVAL_ERROR_PREFIX, r_value);
|
||||||
#else
|
#else
|
||||||
UNUSED_VARS(C);
|
UNUSED_VARS(C);
|
||||||
*r_value = atof(str);
|
*r_value = atof(str);
|
||||||
|
|||||||
@@ -47,7 +47,10 @@
|
|||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
|
|
||||||
#include "BPY_extern.h"
|
#ifdef WITH_PYTHON
|
||||||
|
# include "BPY_extern.h"
|
||||||
|
# include "BPY_extern_run.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "WM_api.h"
|
#include "WM_api.h"
|
||||||
#include "WM_types.h"
|
#include "WM_types.h"
|
||||||
@@ -407,7 +410,7 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
|
|||||||
"'%s').label",
|
"'%s').label",
|
||||||
idname);
|
idname);
|
||||||
char *expr_result = NULL;
|
char *expr_result = NULL;
|
||||||
if (BPY_execute_string_as_string(C, expr_imports, expr, __func__, &expr_result)) {
|
if (BPY_run_string_as_string(C, expr_imports, expr, __func__, &expr_result)) {
|
||||||
STRNCPY(drawstr, expr_result);
|
STRNCPY(drawstr, expr_result);
|
||||||
MEM_freeN(expr_result);
|
MEM_freeN(expr_result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
#include "BLT_translation.h"
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
# include "BPY_extern.h"
|
# include "BPY_extern_run.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ED_screen.h"
|
#include "ED_screen.h"
|
||||||
@@ -433,7 +433,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
|
|||||||
if (has_valid_context == false) {
|
if (has_valid_context == false) {
|
||||||
expr_result = BLI_strdup(has_valid_context_error);
|
expr_result = BLI_strdup(has_valid_context_error);
|
||||||
}
|
}
|
||||||
else if (BPY_execute_string_as_string(C, expr_imports, expr, __func__, &expr_result)) {
|
else if (BPY_run_string_as_string(C, expr_imports, expr, __func__, &expr_result)) {
|
||||||
if (STREQ(expr_result, "")) {
|
if (STREQ(expr_result, "")) {
|
||||||
MEM_freeN(expr_result);
|
MEM_freeN(expr_result);
|
||||||
expr_result = NULL;
|
expr_result = NULL;
|
||||||
@@ -490,7 +490,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
|
|||||||
if (has_valid_context == false) {
|
if (has_valid_context == false) {
|
||||||
expr_result = BLI_strdup(has_valid_context_error);
|
expr_result = BLI_strdup(has_valid_context_error);
|
||||||
}
|
}
|
||||||
else if (BPY_execute_string_as_string(C, expr_imports, expr, __func__, &expr_result)) {
|
else if (BPY_run_string_as_string(C, expr_imports, expr, __func__, &expr_result)) {
|
||||||
if (STREQ(expr_result, ".")) {
|
if (STREQ(expr_result, ".")) {
|
||||||
MEM_freeN(expr_result);
|
MEM_freeN(expr_result);
|
||||||
expr_result = NULL;
|
expr_result = NULL;
|
||||||
@@ -594,7 +594,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
|
|||||||
if (has_valid_context == false) {
|
if (has_valid_context == false) {
|
||||||
shortcut = BLI_strdup(has_valid_context_error);
|
shortcut = BLI_strdup(has_valid_context_error);
|
||||||
}
|
}
|
||||||
else if (BPY_execute_string_as_intptr(C, expr_imports, expr, __func__, &expr_result)) {
|
else if (BPY_run_string_as_intptr(C, expr_imports, expr, __func__, &expr_result)) {
|
||||||
if (expr_result != 0) {
|
if (expr_result != 0) {
|
||||||
wmKeyMap *keymap = (wmKeyMap *)expr_result;
|
wmKeyMap *keymap = (wmKeyMap *)expr_result;
|
||||||
LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
|
LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) {
|
||||||
@@ -658,7 +658,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
|
|||||||
if (has_valid_context == false) {
|
if (has_valid_context == false) {
|
||||||
/* pass */
|
/* pass */
|
||||||
}
|
}
|
||||||
else if (BPY_execute_string_as_string_and_size(
|
else if (BPY_run_string_as_string_and_size(
|
||||||
C, expr_imports, expr, __func__, &expr_result, &expr_result_len)) {
|
C, expr_imports, expr, __func__, &expr_result, &expr_result_len)) {
|
||||||
/* pass. */
|
/* pass. */
|
||||||
}
|
}
|
||||||
@@ -736,7 +736,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
|
|||||||
if (has_valid_context == false) {
|
if (has_valid_context == false) {
|
||||||
/* pass */
|
/* pass */
|
||||||
}
|
}
|
||||||
else if (BPY_execute_string_as_intptr(C, expr_imports, expr, __func__, &expr_result)) {
|
else if (BPY_run_string_as_intptr(C, expr_imports, expr, __func__, &expr_result)) {
|
||||||
if (expr_result != 0) {
|
if (expr_result != 0) {
|
||||||
{
|
{
|
||||||
uiTooltipField *field = text_field_add(data,
|
uiTooltipField *field = text_field_add(data,
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
#include "script_intern.h" // own include
|
#include "script_intern.h" // own include
|
||||||
|
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
# include "BPY_extern.h" /* BPY_script_exec */
|
# include "BPY_extern_run.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int run_pyfile_exec(bContext *C, wmOperator *op)
|
static int run_pyfile_exec(bContext *C, wmOperator *op)
|
||||||
@@ -50,7 +50,7 @@ static int run_pyfile_exec(bContext *C, wmOperator *op)
|
|||||||
char path[512];
|
char path[512];
|
||||||
RNA_string_get(op->ptr, "filepath", path);
|
RNA_string_get(op->ptr, "filepath", path);
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
if (BPY_execute_filepath(C, path, op->reports)) {
|
if (BPY_run_filepath(C, path, op->reports)) {
|
||||||
ARegion *region = CTX_wm_region(C);
|
ARegion *region = CTX_wm_region(C);
|
||||||
ED_region_tag_redraw(region);
|
ED_region_tag_redraw(region);
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
@@ -120,8 +120,7 @@ static int script_reload_exec(bContext *C, wmOperator *op)
|
|||||||
/* TODO, this crashes on netrender and keying sets, need to look into why
|
/* TODO, this crashes on netrender and keying sets, need to look into why
|
||||||
* disable for now unless running in debug mode */
|
* disable for now unless running in debug mode */
|
||||||
WM_cursor_wait(1);
|
WM_cursor_wait(1);
|
||||||
BPY_execute_string(
|
BPY_run_string(C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)");
|
||||||
C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)");
|
|
||||||
WM_cursor_wait(0);
|
WM_cursor_wait(0);
|
||||||
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
|
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
# include "BPY_extern.h"
|
# include "BPY_extern.h"
|
||||||
|
# include "BPY_extern_run.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "text_format.h"
|
#include "text_format.h"
|
||||||
@@ -756,7 +757,7 @@ static int text_run_script(bContext *C, ReportList *reports)
|
|||||||
void *curl_prev = text->curl;
|
void *curl_prev = text->curl;
|
||||||
int curc_prev = text->curc;
|
int curc_prev = text->curc;
|
||||||
|
|
||||||
if (BPY_execute_text(C, text, reports, !is_live)) {
|
if (BPY_run_text(C, text, reports, !is_live)) {
|
||||||
if (is_live) {
|
if (is_live) {
|
||||||
/* for nice live updates */
|
/* for nice live updates */
|
||||||
WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL);
|
WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
#include "WM_types.h"
|
#include "WM_types.h"
|
||||||
|
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
# include "BPY_extern.h"
|
# include "BPY_extern_run.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ED_numinput.h"
|
#include "ED_numinput.h"
|
||||||
@@ -294,10 +294,10 @@ bool user_string_to_number(bContext *C,
|
|||||||
bUnit_ReplaceString(
|
bUnit_ReplaceString(
|
||||||
str_unit_convert, sizeof(str_unit_convert), str, unit_scale, unit->system, type);
|
str_unit_convert, sizeof(str_unit_convert), str, unit_scale, unit->system, type);
|
||||||
|
|
||||||
return BPY_execute_string_as_number(C, NULL, str_unit_convert, error_prefix, r_value);
|
return BPY_run_string_as_number(C, NULL, str_unit_convert, error_prefix, r_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
int success = BPY_execute_string_as_number(C, NULL, str, error_prefix, r_value);
|
int success = BPY_run_string_as_number(C, NULL, str, error_prefix, r_value);
|
||||||
*r_value *= bUnit_PreferredInputUnitScalar(unit, type);
|
*r_value *= bUnit_PreferredInputUnitScalar(unit, type);
|
||||||
*r_value /= unit_scale;
|
*r_value /= unit_scale;
|
||||||
return success;
|
return success;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ extern "C" {
|
|||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
#include "BKE_text.h"
|
#include "BKE_text.h"
|
||||||
|
|
||||||
#include "BPY_extern.h"
|
#include "BPY_extern_run.h"
|
||||||
|
|
||||||
#include "bpy_capi_utils.h"
|
#include "bpy_capi_utils.h"
|
||||||
|
|
||||||
@@ -68,12 +68,12 @@ class PythonInterpreter : public Interpreter {
|
|||||||
BKE_reports_clear(reports);
|
BKE_reports_clear(reports);
|
||||||
char *fn = const_cast<char *>(filename.c_str());
|
char *fn = const_cast<char *>(filename.c_str());
|
||||||
#if 0
|
#if 0
|
||||||
bool ok = BPY_execute_filepath(_context, fn, reports);
|
bool ok = BPY_run_filepath(_context, fn, reports);
|
||||||
#else
|
#else
|
||||||
bool ok;
|
bool ok;
|
||||||
Text *text = BKE_text_load(&_freestyle_bmain, fn, G_MAIN->name);
|
Text *text = BKE_text_load(&_freestyle_bmain, fn, G_MAIN->name);
|
||||||
if (text) {
|
if (text) {
|
||||||
ok = BPY_execute_text(_context, text, reports, false);
|
ok = BPY_run_text(_context, text, reports, false);
|
||||||
BKE_id_delete(&_freestyle_bmain, text);
|
BKE_id_delete(&_freestyle_bmain, text);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -102,7 +102,7 @@ class PythonInterpreter : public Interpreter {
|
|||||||
|
|
||||||
BKE_reports_clear(reports);
|
BKE_reports_clear(reports);
|
||||||
|
|
||||||
if (!BPY_execute_string(_context, NULL, str.c_str())) {
|
if (!BPY_run_string(_context, NULL, str.c_str())) {
|
||||||
BPy_errors_to_report(reports);
|
BPy_errors_to_report(reports);
|
||||||
cerr << "\nError executing Python script from PythonInterpreter::interpretString" << endl;
|
cerr << "\nError executing Python script from PythonInterpreter::interpretString" << endl;
|
||||||
cerr << "Name: " << name << endl;
|
cerr << "Name: " << name << endl;
|
||||||
@@ -122,7 +122,7 @@ class PythonInterpreter : public Interpreter {
|
|||||||
|
|
||||||
BKE_reports_clear(reports);
|
BKE_reports_clear(reports);
|
||||||
|
|
||||||
if (!BPY_execute_text(_context, text, reports, false)) {
|
if (!BPY_run_text(_context, text, reports, false)) {
|
||||||
cerr << "\nError executing Python script from PythonInterpreter::interpretText" << endl;
|
cerr << "\nError executing Python script from PythonInterpreter::interpretText" << endl;
|
||||||
cerr << "Name: " << name << endl;
|
cerr << "Name: " << name << endl;
|
||||||
cerr << "Errors: " << endl;
|
cerr << "Errors: " << endl;
|
||||||
|
|||||||
@@ -67,40 +67,6 @@ void BPY_thread_restore(BPy_ThreadStatePtr tstate);
|
|||||||
} \
|
} \
|
||||||
(void)0
|
(void)0
|
||||||
|
|
||||||
bool BPY_execute_filepath(struct bContext *C, const char *filepath, struct ReportList *reports);
|
|
||||||
bool BPY_execute_text(struct bContext *C,
|
|
||||||
struct Text *text,
|
|
||||||
struct ReportList *reports,
|
|
||||||
const bool do_jump);
|
|
||||||
|
|
||||||
bool BPY_execute_string_as_number(struct bContext *C,
|
|
||||||
const char *imports[],
|
|
||||||
const char *expr,
|
|
||||||
const char *report_prefix,
|
|
||||||
double *r_value);
|
|
||||||
bool BPY_execute_string_as_intptr(struct bContext *C,
|
|
||||||
const char *imports[],
|
|
||||||
const char *expr,
|
|
||||||
const char *report_prefix,
|
|
||||||
intptr_t *r_value);
|
|
||||||
bool BPY_execute_string_as_string_and_size(struct bContext *C,
|
|
||||||
const char *imports[],
|
|
||||||
const char *expr,
|
|
||||||
const char *report_prefix,
|
|
||||||
char **r_value,
|
|
||||||
size_t *r_value_size);
|
|
||||||
bool BPY_execute_string_as_string(struct bContext *C,
|
|
||||||
const char *imports[],
|
|
||||||
const char *expr,
|
|
||||||
const char *report_prefix,
|
|
||||||
char **r_value);
|
|
||||||
|
|
||||||
bool BPY_execute_string_ex(struct bContext *C,
|
|
||||||
const char *imports[],
|
|
||||||
const char *expr,
|
|
||||||
bool use_eval);
|
|
||||||
bool BPY_execute_string(struct bContext *C, const char *imports[], const char *expr);
|
|
||||||
|
|
||||||
void BPY_text_free_code(struct Text *text);
|
void BPY_text_free_code(struct Text *text);
|
||||||
void BPY_modules_update(
|
void BPY_modules_update(
|
||||||
struct bContext *C); // XXX - annoying, need this for pointers that get out of date
|
struct bContext *C); // XXX - annoying, need this for pointers that get out of date
|
||||||
|
|||||||
68
source/blender/python/BPY_extern_run.h
Normal file
68
source/blender/python/BPY_extern_run.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup python
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "BLI_sys_types.h"
|
||||||
|
|
||||||
|
struct ReportList;
|
||||||
|
struct Text;
|
||||||
|
struct bContext;
|
||||||
|
|
||||||
|
/* bpy_interface_run.c */
|
||||||
|
bool BPY_run_filepath(struct bContext *C, const char *filepath, struct ReportList *reports);
|
||||||
|
bool BPY_run_text(struct bContext *C,
|
||||||
|
struct Text *text,
|
||||||
|
struct ReportList *reports,
|
||||||
|
const bool do_jump);
|
||||||
|
|
||||||
|
bool BPY_run_string_as_number(struct bContext *C,
|
||||||
|
const char *imports[],
|
||||||
|
const char *expr,
|
||||||
|
const char *report_prefix,
|
||||||
|
double *r_value);
|
||||||
|
bool BPY_run_string_as_intptr(struct bContext *C,
|
||||||
|
const char *imports[],
|
||||||
|
const char *expr,
|
||||||
|
const char *report_prefix,
|
||||||
|
intptr_t *r_value);
|
||||||
|
bool BPY_run_string_as_string_and_size(struct bContext *C,
|
||||||
|
const char *imports[],
|
||||||
|
const char *expr,
|
||||||
|
const char *report_prefix,
|
||||||
|
char **r_value,
|
||||||
|
size_t *r_value_size);
|
||||||
|
bool BPY_run_string_as_string(struct bContext *C,
|
||||||
|
const char *imports[],
|
||||||
|
const char *expr,
|
||||||
|
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
|
||||||
@@ -62,6 +62,7 @@ set(SRC
|
|||||||
bpy_gizmo_wrap.c
|
bpy_gizmo_wrap.c
|
||||||
bpy_interface.c
|
bpy_interface.c
|
||||||
bpy_interface_atexit.c
|
bpy_interface_atexit.c
|
||||||
|
bpy_interface_run.c
|
||||||
bpy_intern_string.c
|
bpy_intern_string.c
|
||||||
bpy_library_load.c
|
bpy_library_load.c
|
||||||
bpy_library_write.c
|
bpy_library_write.c
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
|
|
||||||
#include "BPY_extern.h"
|
#include "BPY_extern.h"
|
||||||
#include "BPY_extern_python.h"
|
#include "BPY_extern_python.h"
|
||||||
|
#include "BPY_extern_run.h"
|
||||||
|
|
||||||
#include "../generic/py_capi_utils.h"
|
#include "../generic/py_capi_utils.h"
|
||||||
|
|
||||||
@@ -428,18 +429,6 @@ void BPY_python_use_system_env(void)
|
|||||||
py_use_system_env = true;
|
py_use_system_env = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void python_script_error_jump_text(struct Text *text)
|
|
||||||
{
|
|
||||||
int lineno;
|
|
||||||
int offset;
|
|
||||||
python_script_error_jump(text->id.name + 2, &lineno, &offset);
|
|
||||||
if (lineno != -1) {
|
|
||||||
/* select the line with the error */
|
|
||||||
txt_move_to(text, lineno - 1, INT_MAX, false);
|
|
||||||
txt_move_to(text, lineno - 1, offset, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BPY_python_backtrace(FILE *fp)
|
void BPY_python_backtrace(FILE *fp)
|
||||||
{
|
{
|
||||||
fputs("\n# Python backtrace\n", fp);
|
fputs("\n# Python backtrace\n", fp);
|
||||||
@@ -467,152 +456,6 @@ typedef struct {
|
|||||||
} PyModuleObject;
|
} PyModuleObject;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* returns a dummy filename for a textblock so we can tell what file a text block comes from */
|
|
||||||
static void bpy_text_filename_get(char *fn, const Main *bmain, size_t fn_len, const Text *text)
|
|
||||||
{
|
|
||||||
BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bmain, &text->id), SEP, text->id.name + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool python_script_exec(
|
|
||||||
bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const bool do_jump)
|
|
||||||
{
|
|
||||||
Main *bmain_old = CTX_data_main(C);
|
|
||||||
PyObject *main_mod = NULL;
|
|
||||||
PyObject *py_dict = NULL, *py_result = NULL;
|
|
||||||
PyGILState_STATE gilstate;
|
|
||||||
|
|
||||||
BLI_assert(fn || text);
|
|
||||||
|
|
||||||
if (fn == NULL && text == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bpy_context_set(C, &gilstate);
|
|
||||||
|
|
||||||
PyC_MainModule_Backup(&main_mod);
|
|
||||||
|
|
||||||
if (text) {
|
|
||||||
char fn_dummy[FILE_MAXDIR];
|
|
||||||
bpy_text_filename_get(fn_dummy, bmain_old, sizeof(fn_dummy), text);
|
|
||||||
|
|
||||||
if (text->compiled == NULL) { /* if it wasn't already compiled, do it now */
|
|
||||||
char *buf;
|
|
||||||
PyObject *fn_dummy_py;
|
|
||||||
|
|
||||||
fn_dummy_py = PyC_UnicodeFromByte(fn_dummy);
|
|
||||||
|
|
||||||
buf = txt_to_buf(text, NULL);
|
|
||||||
text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1);
|
|
||||||
MEM_freeN(buf);
|
|
||||||
|
|
||||||
Py_DECREF(fn_dummy_py);
|
|
||||||
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
if (do_jump) {
|
|
||||||
python_script_error_jump_text(text);
|
|
||||||
}
|
|
||||||
BPY_text_free_code(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (text->compiled) {
|
|
||||||
py_dict = PyC_DefaultNameSpace(fn_dummy);
|
|
||||||
py_result = PyEval_EvalCode(text->compiled, py_dict, py_dict);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FILE *fp = BLI_fopen(fn, "r");
|
|
||||||
|
|
||||||
if (fp) {
|
|
||||||
py_dict = PyC_DefaultNameSpace(fn);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
/* Previously we used PyRun_File to run directly the code on a FILE
|
|
||||||
* object, but as written in the Python/C API Ref Manual, chapter 2,
|
|
||||||
* 'FILE structs for different C libraries can be different and
|
|
||||||
* incompatible'.
|
|
||||||
* So now we load the script file data to a buffer.
|
|
||||||
*
|
|
||||||
* Note on use of 'globals()', it's important not copy the dictionary because
|
|
||||||
* tools may inspect 'sys.modules["__main__"]' for variables defined in the code
|
|
||||||
* where using a copy of 'globals()' causes code execution
|
|
||||||
* to leave the main namespace untouched. see: T51444
|
|
||||||
*
|
|
||||||
* This leaves us with the problem of variables being included,
|
|
||||||
* currently this is worked around using 'dict.__del__' it's ugly but works.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
const char *pystring =
|
|
||||||
"with open(__file__, 'rb') as f:"
|
|
||||||
"exec(compile(f.read(), __file__, 'exec'), globals().__delitem__('f') or globals())";
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
py_result = PyRun_String(pystring, Py_file_input, py_dict, py_dict);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict);
|
|
||||||
fclose(fp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyErr_Format(
|
|
||||||
PyExc_IOError, "Python file \"%s\" could not be opened: %s", fn, strerror(errno));
|
|
||||||
py_result = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!py_result) {
|
|
||||||
if (text) {
|
|
||||||
if (do_jump) {
|
|
||||||
/* ensure text is valid before use, the script may have freed its self */
|
|
||||||
Main *bmain_new = CTX_data_main(C);
|
|
||||||
if ((bmain_old == bmain_new) && (BLI_findindex(&bmain_new->texts, text) != -1)) {
|
|
||||||
python_script_error_jump_text(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BPy_errors_to_report(reports);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Py_DECREF(py_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (py_dict) {
|
|
||||||
#ifdef PYMODULE_CLEAR_WORKAROUND
|
|
||||||
PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItem(PyImport_GetModuleDict(),
|
|
||||||
bpy_intern_str___main__);
|
|
||||||
PyObject *dict_back = mmod->md_dict;
|
|
||||||
/* freeing the module will clear the namespace,
|
|
||||||
* gives problems running classes defined in this namespace being used later. */
|
|
||||||
mmod->md_dict = NULL;
|
|
||||||
Py_DECREF(dict_back);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef PYMODULE_CLEAR_WORKAROUND
|
|
||||||
}
|
|
||||||
|
|
||||||
PyC_MainModule_Restore(main_mod);
|
|
||||||
|
|
||||||
bpy_context_clear(C, &gilstate);
|
|
||||||
|
|
||||||
return (py_result != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Can run a file or text block */
|
|
||||||
bool BPY_execute_filepath(bContext *C, const char *filepath, struct ReportList *reports)
|
|
||||||
{
|
|
||||||
return python_script_exec(C, filepath, NULL, reports, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BPY_execute_text(bContext *C,
|
|
||||||
struct Text *text,
|
|
||||||
struct ReportList *reports,
|
|
||||||
const bool do_jump)
|
|
||||||
{
|
|
||||||
return python_script_exec(C, NULL, text, reports, do_jump);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BPY_DECREF(void *pyob_ptr)
|
void BPY_DECREF(void *pyob_ptr)
|
||||||
{
|
{
|
||||||
PyGILState_STATE gilstate = PyGILState_Ensure();
|
PyGILState_STATE gilstate = PyGILState_Ensure();
|
||||||
@@ -631,177 +474,6 @@ void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr)
|
|||||||
PyGILState_Release(gilstate);
|
PyGILState_Release(gilstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* \return success
|
|
||||||
*/
|
|
||||||
bool BPY_execute_string_as_number(bContext *C,
|
|
||||||
const char *imports[],
|
|
||||||
const char *expr,
|
|
||||||
const char *report_prefix,
|
|
||||||
double *r_value)
|
|
||||||
{
|
|
||||||
PyGILState_STATE gilstate;
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (!r_value || !expr) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expr[0] == '\0') {
|
|
||||||
*r_value = 0.0;
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bpy_context_set(C, &gilstate);
|
|
||||||
|
|
||||||
ok = PyC_RunString_AsNumber(imports, expr, "<expr as number>", r_value);
|
|
||||||
|
|
||||||
if (ok == false) {
|
|
||||||
if (report_prefix != NULL) {
|
|
||||||
BPy_errors_to_report_ex(CTX_wm_reports(C), report_prefix, false, false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bpy_context_clear(C, &gilstate);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \return success
|
|
||||||
*/
|
|
||||||
bool BPY_execute_string_as_string_and_size(bContext *C,
|
|
||||||
const char *imports[],
|
|
||||||
const char *expr,
|
|
||||||
const char *report_prefix,
|
|
||||||
char **r_value,
|
|
||||||
size_t *r_value_size)
|
|
||||||
{
|
|
||||||
BLI_assert(r_value && expr);
|
|
||||||
PyGILState_STATE gilstate;
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (expr[0] == '\0') {
|
|
||||||
*r_value = NULL;
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bpy_context_set(C, &gilstate);
|
|
||||||
|
|
||||||
ok = PyC_RunString_AsStringAndSize(imports, expr, "<expr as str>", r_value, r_value_size);
|
|
||||||
|
|
||||||
if (ok == false) {
|
|
||||||
if (report_prefix != NULL) {
|
|
||||||
BPy_errors_to_report_ex(CTX_wm_reports(C), false, false, report_prefix);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bpy_context_clear(C, &gilstate);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BPY_execute_string_as_string(bContext *C,
|
|
||||||
const char *imports[],
|
|
||||||
const char *expr,
|
|
||||||
const char *report_prefix,
|
|
||||||
char **r_value)
|
|
||||||
{
|
|
||||||
size_t value_dummy_size;
|
|
||||||
return BPY_execute_string_as_string_and_size(
|
|
||||||
C, imports, expr, report_prefix, r_value, &value_dummy_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Support both int and pointers.
|
|
||||||
*
|
|
||||||
* \return success
|
|
||||||
*/
|
|
||||||
bool BPY_execute_string_as_intptr(bContext *C,
|
|
||||||
const char *imports[],
|
|
||||||
const char *expr,
|
|
||||||
const char *report_prefix,
|
|
||||||
intptr_t *r_value)
|
|
||||||
{
|
|
||||||
BLI_assert(r_value && expr);
|
|
||||||
PyGILState_STATE gilstate;
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (expr[0] == '\0') {
|
|
||||||
*r_value = 0;
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bpy_context_set(C, &gilstate);
|
|
||||||
|
|
||||||
ok = PyC_RunString_AsIntPtr(imports, expr, "<expr as intptr>", r_value);
|
|
||||||
|
|
||||||
if (ok == false) {
|
|
||||||
if (report_prefix != NULL) {
|
|
||||||
BPy_errors_to_report_ex(CTX_wm_reports(C), report_prefix, false, false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bpy_context_clear(C, &gilstate);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BPY_execute_string_ex(bContext *C, const char *imports[], const char *expr, bool use_eval)
|
|
||||||
{
|
|
||||||
BLI_assert(expr);
|
|
||||||
PyGILState_STATE gilstate;
|
|
||||||
PyObject *main_mod = NULL;
|
|
||||||
PyObject *py_dict, *retval;
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (expr[0] == '\0') {
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bpy_context_set(C, &gilstate);
|
|
||||||
|
|
||||||
PyC_MainModule_Backup(&main_mod);
|
|
||||||
|
|
||||||
py_dict = PyC_DefaultNameSpace("<blender string>");
|
|
||||||
|
|
||||||
if (imports && (!PyC_NameSpace_ImportArray(py_dict, imports))) {
|
|
||||||
Py_DECREF(py_dict);
|
|
||||||
retval = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
retval = PyRun_String(expr, use_eval ? Py_eval_input : Py_file_input, py_dict, py_dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval == NULL) {
|
|
||||||
ok = false;
|
|
||||||
BPy_errors_to_report(CTX_wm_reports(C));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Py_DECREF(retval);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyC_MainModule_Restore(main_mod);
|
|
||||||
|
|
||||||
bpy_context_clear(C, &gilstate);
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BPY_execute_string(bContext *C, const char *imports[], const char *expr)
|
|
||||||
{
|
|
||||||
return BPY_execute_string_ex(C, imports, expr, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BPY_modules_load_user(bContext *C)
|
void BPY_modules_load_user(bContext *C)
|
||||||
{
|
{
|
||||||
PyGILState_STATE gilstate;
|
PyGILState_STATE gilstate;
|
||||||
@@ -834,7 +506,7 @@ void BPY_modules_load_user(bContext *C)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BPY_execute_text(C, text, NULL, false);
|
BPY_run_text(C, text, NULL, false);
|
||||||
|
|
||||||
/* Check if the script loaded a new file. */
|
/* Check if the script loaded a new file. */
|
||||||
if (bmain != CTX_data_main(C)) {
|
if (bmain != CTX_data_main(C)) {
|
||||||
|
|||||||
391
source/blender/python/intern/bpy_interface_run.c
Normal file
391
source/blender/python/intern/bpy_interface_run.c
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup pythonintern
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "BLI_fileops.h"
|
||||||
|
#include "BLI_listbase.h"
|
||||||
|
#include "BLI_path_util.h"
|
||||||
|
#include "BLI_string.h"
|
||||||
|
|
||||||
|
#include "BKE_context.h"
|
||||||
|
#include "BKE_main.h"
|
||||||
|
#include "BKE_text.h"
|
||||||
|
|
||||||
|
#include "DNA_text_types.h"
|
||||||
|
|
||||||
|
#include "BPY_extern.h"
|
||||||
|
#include "BPY_extern_run.h"
|
||||||
|
|
||||||
|
#include "bpy_capi_utils.h"
|
||||||
|
#include "bpy_traceback.h"
|
||||||
|
|
||||||
|
#include "../generic/py_capi_utils.h"
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Private Utilities
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
static void python_script_error_jump_text(Text *text)
|
||||||
|
{
|
||||||
|
int lineno;
|
||||||
|
int offset;
|
||||||
|
python_script_error_jump(text->id.name + 2, &lineno, &offset);
|
||||||
|
if (lineno != -1) {
|
||||||
|
/* select the line with the error */
|
||||||
|
txt_move_to(text, lineno - 1, INT_MAX, false);
|
||||||
|
txt_move_to(text, lineno - 1, offset, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns a dummy filename for a textblock so we can tell what file a text block comes from */
|
||||||
|
static void bpy_text_filename_get(char *fn, const Main *bmain, size_t fn_len, const Text *text)
|
||||||
|
{
|
||||||
|
BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bmain, &text->id), SEP, text->id.name + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool python_script_exec(
|
||||||
|
bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const bool do_jump)
|
||||||
|
{
|
||||||
|
Main *bmain_old = CTX_data_main(C);
|
||||||
|
PyObject *main_mod = NULL;
|
||||||
|
PyObject *py_dict = NULL, *py_result = NULL;
|
||||||
|
PyGILState_STATE gilstate;
|
||||||
|
|
||||||
|
BLI_assert(fn || text);
|
||||||
|
|
||||||
|
if (fn == NULL && text == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpy_context_set(C, &gilstate);
|
||||||
|
|
||||||
|
PyC_MainModule_Backup(&main_mod);
|
||||||
|
|
||||||
|
if (text) {
|
||||||
|
char fn_dummy[FILE_MAXDIR];
|
||||||
|
bpy_text_filename_get(fn_dummy, bmain_old, sizeof(fn_dummy), text);
|
||||||
|
|
||||||
|
if (text->compiled == NULL) { /* if it wasn't already compiled, do it now */
|
||||||
|
char *buf;
|
||||||
|
PyObject *fn_dummy_py;
|
||||||
|
|
||||||
|
fn_dummy_py = PyC_UnicodeFromByte(fn_dummy);
|
||||||
|
|
||||||
|
buf = txt_to_buf(text, NULL);
|
||||||
|
text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1);
|
||||||
|
MEM_freeN(buf);
|
||||||
|
|
||||||
|
Py_DECREF(fn_dummy_py);
|
||||||
|
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
if (do_jump) {
|
||||||
|
python_script_error_jump_text(text);
|
||||||
|
}
|
||||||
|
BPY_text_free_code(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text->compiled) {
|
||||||
|
py_dict = PyC_DefaultNameSpace(fn_dummy);
|
||||||
|
py_result = PyEval_EvalCode(text->compiled, py_dict, py_dict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FILE *fp = BLI_fopen(fn, "r");
|
||||||
|
|
||||||
|
if (fp) {
|
||||||
|
py_dict = PyC_DefaultNameSpace(fn);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* Previously we used PyRun_File to run directly the code on a FILE
|
||||||
|
* object, but as written in the Python/C API Ref Manual, chapter 2,
|
||||||
|
* 'FILE structs for different C libraries can be different and
|
||||||
|
* incompatible'.
|
||||||
|
* So now we load the script file data to a buffer.
|
||||||
|
*
|
||||||
|
* Note on use of 'globals()', it's important not copy the dictionary because
|
||||||
|
* tools may inspect 'sys.modules["__main__"]' for variables defined in the code
|
||||||
|
* where using a copy of 'globals()' causes code execution
|
||||||
|
* to leave the main namespace untouched. see: T51444
|
||||||
|
*
|
||||||
|
* This leaves us with the problem of variables being included,
|
||||||
|
* currently this is worked around using 'dict.__del__' it's ugly but works.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
const char *pystring =
|
||||||
|
"with open(__file__, 'rb') as f:"
|
||||||
|
"exec(compile(f.read(), __file__, 'exec'), globals().__delitem__('f') or globals())";
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
py_result = PyRun_String(pystring, Py_file_input, py_dict, py_dict);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict);
|
||||||
|
fclose(fp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_Format(
|
||||||
|
PyExc_IOError, "Python file \"%s\" could not be opened: %s", fn, strerror(errno));
|
||||||
|
py_result = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!py_result) {
|
||||||
|
if (text) {
|
||||||
|
if (do_jump) {
|
||||||
|
/* ensure text is valid before use, the script may have freed its self */
|
||||||
|
Main *bmain_new = CTX_data_main(C);
|
||||||
|
if ((bmain_old == bmain_new) && (BLI_findindex(&bmain_new->texts, text) != -1)) {
|
||||||
|
python_script_error_jump_text(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BPy_errors_to_report(reports);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_DECREF(py_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (py_dict) {
|
||||||
|
#ifdef PYMODULE_CLEAR_WORKAROUND
|
||||||
|
PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItem(PyImport_GetModuleDict(),
|
||||||
|
bpy_intern_str___main__);
|
||||||
|
PyObject *dict_back = mmod->md_dict;
|
||||||
|
/* freeing the module will clear the namespace,
|
||||||
|
* gives problems running classes defined in this namespace being used later. */
|
||||||
|
mmod->md_dict = NULL;
|
||||||
|
Py_DECREF(dict_back);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef PYMODULE_CLEAR_WORKAROUND
|
||||||
|
}
|
||||||
|
|
||||||
|
PyC_MainModule_Restore(main_mod);
|
||||||
|
|
||||||
|
bpy_context_clear(C, &gilstate);
|
||||||
|
|
||||||
|
return (py_result != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Run Text / Filename / String
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
/* Can run a file or text block */
|
||||||
|
bool BPY_run_filepath(bContext *C, const char *filepath, struct ReportList *reports)
|
||||||
|
{
|
||||||
|
return python_script_exec(C, filepath, NULL, reports, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BPY_run_text(bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
BLI_assert(expr);
|
||||||
|
PyGILState_STATE gilstate;
|
||||||
|
PyObject *main_mod = NULL;
|
||||||
|
PyObject *py_dict, *retval;
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if (expr[0] == '\0') {
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpy_context_set(C, &gilstate);
|
||||||
|
|
||||||
|
PyC_MainModule_Backup(&main_mod);
|
||||||
|
|
||||||
|
py_dict = PyC_DefaultNameSpace("<blender string>");
|
||||||
|
|
||||||
|
if (imports && (!PyC_NameSpace_ImportArray(py_dict, imports))) {
|
||||||
|
Py_DECREF(py_dict);
|
||||||
|
retval = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
retval = PyRun_String(expr, use_eval ? Py_eval_input : Py_file_input, py_dict, py_dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval == NULL) {
|
||||||
|
ok = false;
|
||||||
|
BPy_errors_to_report(CTX_wm_reports(C));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_DECREF(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyC_MainModule_Restore(main_mod);
|
||||||
|
|
||||||
|
bpy_context_clear(C, &gilstate);
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BPY_run_string(bContext *C, const char *imports[], const char *expr)
|
||||||
|
{
|
||||||
|
return BPY_run_string_ex(C, imports, expr, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Run Python & Evaluate Utilities
|
||||||
|
*
|
||||||
|
* Return values as plain C types, useful to run Python scripts
|
||||||
|
* in code that doesn't deal with Python data-types.
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \return success
|
||||||
|
*/
|
||||||
|
bool BPY_run_string_as_number(bContext *C,
|
||||||
|
const char *imports[],
|
||||||
|
const char *expr,
|
||||||
|
const char *report_prefix,
|
||||||
|
double *r_value)
|
||||||
|
{
|
||||||
|
PyGILState_STATE gilstate;
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if (!r_value || !expr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expr[0] == '\0') {
|
||||||
|
*r_value = 0.0;
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpy_context_set(C, &gilstate);
|
||||||
|
|
||||||
|
ok = PyC_RunString_AsNumber(imports, expr, "<expr as number>", r_value);
|
||||||
|
|
||||||
|
if (ok == false) {
|
||||||
|
if (report_prefix != NULL) {
|
||||||
|
BPy_errors_to_report_ex(CTX_wm_reports(C), report_prefix, false, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bpy_context_clear(C, &gilstate);
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \return success
|
||||||
|
*/
|
||||||
|
bool BPY_run_string_as_string_and_size(bContext *C,
|
||||||
|
const char *imports[],
|
||||||
|
const char *expr,
|
||||||
|
const char *report_prefix,
|
||||||
|
char **r_value,
|
||||||
|
size_t *r_value_size)
|
||||||
|
{
|
||||||
|
BLI_assert(r_value && expr);
|
||||||
|
PyGILState_STATE gilstate;
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if (expr[0] == '\0') {
|
||||||
|
*r_value = NULL;
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpy_context_set(C, &gilstate);
|
||||||
|
|
||||||
|
ok = PyC_RunString_AsStringAndSize(imports, expr, "<expr as str>", r_value, r_value_size);
|
||||||
|
|
||||||
|
if (ok == false) {
|
||||||
|
if (report_prefix != NULL) {
|
||||||
|
BPy_errors_to_report_ex(CTX_wm_reports(C), false, false, report_prefix);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bpy_context_clear(C, &gilstate);
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BPY_run_string_as_string(bContext *C,
|
||||||
|
const char *imports[],
|
||||||
|
const char *expr,
|
||||||
|
const char *report_prefix,
|
||||||
|
char **r_value)
|
||||||
|
{
|
||||||
|
size_t value_dummy_size;
|
||||||
|
return BPY_run_string_as_string_and_size(
|
||||||
|
C, imports, expr, report_prefix, r_value, &value_dummy_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support both int and pointers.
|
||||||
|
*
|
||||||
|
* \return success
|
||||||
|
*/
|
||||||
|
bool BPY_run_string_as_intptr(bContext *C,
|
||||||
|
const char *imports[],
|
||||||
|
const char *expr,
|
||||||
|
const char *report_prefix,
|
||||||
|
intptr_t *r_value)
|
||||||
|
{
|
||||||
|
BLI_assert(r_value && expr);
|
||||||
|
PyGILState_STATE gilstate;
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if (expr[0] == '\0') {
|
||||||
|
*r_value = 0;
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpy_context_set(C, &gilstate);
|
||||||
|
|
||||||
|
ok = PyC_RunString_AsIntPtr(imports, expr, "<expr as intptr>", r_value);
|
||||||
|
|
||||||
|
if (ok == false) {
|
||||||
|
if (report_prefix != NULL) {
|
||||||
|
BPy_errors_to_report_ex(CTX_wm_reports(C), report_prefix, false, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bpy_context_clear(C, &gilstate);
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
@@ -66,6 +66,7 @@
|
|||||||
|
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
# include "BPY_extern.h"
|
# include "BPY_extern.h"
|
||||||
|
# include "BPY_extern_run.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ****************************************************** */
|
/* ****************************************************** */
|
||||||
@@ -270,7 +271,7 @@ void WM_keyconfig_reload(bContext *C)
|
|||||||
{
|
{
|
||||||
if (CTX_py_init_get(C) && !G.background) {
|
if (CTX_py_init_get(C) && !G.background) {
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
BPY_execute_string(C, (const char *[]){"bpy", NULL}, "bpy.utils.keyconfig_init()");
|
BPY_run_string(C, (const char *[]){"bpy", NULL}, "bpy.utils.keyconfig_init()");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,8 +121,8 @@
|
|||||||
#include "RE_engine.h"
|
#include "RE_engine.h"
|
||||||
|
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
# include "BPY_extern.h"
|
|
||||||
# include "BPY_extern_python.h"
|
# include "BPY_extern_python.h"
|
||||||
|
# include "BPY_extern_run.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
@@ -580,14 +580,14 @@ static void wm_file_read_post(bContext *C,
|
|||||||
if (use_userdef || reset_app_template) {
|
if (use_userdef || reset_app_template) {
|
||||||
/* Only run when we have a template path found. */
|
/* Only run when we have a template path found. */
|
||||||
if (BKE_appdir_app_template_any()) {
|
if (BKE_appdir_app_template_any()) {
|
||||||
BPY_execute_string(
|
BPY_run_string(
|
||||||
C, (const char *[]){"bl_app_template_utils", NULL}, "bl_app_template_utils.reset()");
|
C, (const char *[]){"bl_app_template_utils", NULL}, "bl_app_template_utils.reset()");
|
||||||
reset_all = true;
|
reset_all = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reset_all) {
|
if (reset_all) {
|
||||||
/* sync addons, these may have changed from the defaults */
|
/* sync addons, these may have changed from the defaults */
|
||||||
BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()");
|
BPY_run_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()");
|
||||||
}
|
}
|
||||||
if (use_data) {
|
if (use_data) {
|
||||||
BPY_python_reset(C);
|
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
|
* Note that this fits into 'wm_file_read_pre' function but gets messy
|
||||||
* since we need to know if 'reset_app_template' is true. */
|
* since we need to know if 'reset_app_template' is true. */
|
||||||
BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.disable_all()");
|
BPY_run_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.disable_all()");
|
||||||
}
|
}
|
||||||
#endif /* WITH_PYTHON */
|
#endif /* WITH_PYTHON */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,8 +61,8 @@
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef WITH_PYTHON
|
# ifdef WITH_PYTHON
|
||||||
# include "BPY_extern.h"
|
|
||||||
# include "BPY_extern_python.h"
|
# include "BPY_extern_python.h"
|
||||||
|
# include "BPY_extern_run.h"
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# include "RE_engine.h"
|
# include "RE_engine.h"
|
||||||
@@ -1780,7 +1780,7 @@ static int arg_handle_python_file_run(int argc, const char **argv, void *data)
|
|||||||
BLI_path_abs_from_cwd(filename, sizeof(filename));
|
BLI_path_abs_from_cwd(filename, sizeof(filename));
|
||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
BPY_CTX_SETUP(ok = BPY_execute_filepath(C, filename, NULL));
|
BPY_CTX_SETUP(ok = BPY_run_filepath(C, filename, NULL));
|
||||||
if (!ok && app_state.exit_code_on_error.python) {
|
if (!ok && app_state.exit_code_on_error.python) {
|
||||||
printf("\nError: script failed, file: '%s', exiting.\n", argv[1]);
|
printf("\nError: script failed, file: '%s', exiting.\n", argv[1]);
|
||||||
BPY_python_end();
|
BPY_python_end();
|
||||||
@@ -1815,7 +1815,7 @@ static int arg_handle_python_text_run(int argc, const char **argv, void *data)
|
|||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
if (text) {
|
if (text) {
|
||||||
BPY_CTX_SETUP(ok = BPY_execute_text(C, text, NULL, false));
|
BPY_CTX_SETUP(ok = BPY_run_text(C, text, NULL, false));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("\nError: text block not found %s.\n", argv[1]);
|
printf("\nError: text block not found %s.\n", argv[1]);
|
||||||
@@ -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 */
|
/* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
bool ok;
|
bool ok;
|
||||||
BPY_CTX_SETUP(ok = BPY_execute_string_ex(C, NULL, argv[1], false));
|
BPY_CTX_SETUP(ok = BPY_run_string_ex(C, NULL, argv[1], false));
|
||||||
if (!ok && app_state.exit_code_on_error.python) {
|
if (!ok && app_state.exit_code_on_error.python) {
|
||||||
printf("\nError: script failed, expr: '%s', exiting.\n", argv[1]);
|
printf("\nError: script failed, expr: '%s', exiting.\n", argv[1]);
|
||||||
BPY_python_end();
|
BPY_python_end();
|
||||||
@@ -1879,7 +1879,7 @@ static int arg_handle_python_console_run(int UNUSED(argc), const char **argv, vo
|
|||||||
# ifdef WITH_PYTHON
|
# ifdef WITH_PYTHON
|
||||||
bContext *C = data;
|
bContext *C = data;
|
||||||
|
|
||||||
BPY_CTX_SETUP(BPY_execute_string(C, (const char *[]){"code", NULL}, "code.interact()"));
|
BPY_CTX_SETUP(BPY_run_string(C, (const char *[]){"code", NULL}, "code.interact()"));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
# else
|
# 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_snprintf(str, slen, script_str, argv[1]);
|
||||||
|
|
||||||
BLI_assert(strlen(str) + 1 == slen);
|
BLI_assert(strlen(str) + 1 == slen);
|
||||||
BPY_CTX_SETUP(BPY_execute_string_ex(C, NULL, str, false));
|
BPY_CTX_SETUP(BPY_run_string_ex(C, NULL, str, false));
|
||||||
free(str);
|
free(str);
|
||||||
# else
|
# else
|
||||||
UNUSED_VARS(argv, data);
|
UNUSED_VARS(argv, data);
|
||||||
|
|||||||
Reference in New Issue
Block a user