Blender  V3.3
bpy_interface_run.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <stdio.h>
8 
9 #include <Python.h>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "BLI_fileops.h"
14 #include "BLI_listbase.h"
15 #include "BLI_path_util.h"
16 #include "BLI_string.h"
17 
18 #include "BKE_context.h"
19 #include "BKE_main.h"
20 #include "BKE_report.h"
21 #include "BKE_text.h"
22 
23 #include "DNA_text_types.h"
24 
25 #include "BPY_extern.h"
26 #include "BPY_extern_run.h"
27 
28 #include "bpy_capi_utils.h"
29 #include "bpy_intern_string.h"
30 #include "bpy_traceback.h"
31 
32 #include "../generic/py_capi_utils.h"
33 
34 /* -------------------------------------------------------------------- */
38 static void python_script_error_jump_text(Text *text, const char *filepath)
39 {
40  int lineno, lineno_end;
41  int offset, offset_end;
42  if (python_script_error_jump(filepath, &lineno, &offset, &lineno_end, &offset_end)) {
43  /* Start at the end so cursor motion that looses the selection,
44  * leaves the cursor from the most useful place.
45  * Also, the end can't always be set, so don't give it priority. */
46  txt_move_to(text, lineno_end - 1, offset_end - 1, false);
47  txt_move_to(text, lineno - 1, offset - 1, true);
48  }
49 }
50 
54 static void bpy_text_filepath_get(char *filepath,
55  const size_t filepath_maxlen,
56  const Main *bmain,
57  const Text *text)
58 {
59  BLI_snprintf(filepath,
60  filepath_maxlen,
61  "%s%c%s",
62  ID_BLEND_PATH(bmain, &text->id),
63  SEP,
64  text->id.name + 2);
65 }
66 
67 /* Very annoying! Undo #_PyModule_Clear(), see T23871. */
68 #define PYMODULE_CLEAR_WORKAROUND
69 
70 #ifdef PYMODULE_CLEAR_WORKAROUND
71 /* bad!, we should never do this, but currently only safe way I could find to keep namespace.
72  * from being cleared. - campbell */
73 typedef struct {
74  PyObject_HEAD
75  PyObject *md_dict;
76  /* omit other values, we only want the dict. */
78 #endif
79 
89  const char *filepath,
90  struct Text *text,
91  struct ReportList *reports,
92  const bool do_jump)
93 {
94  Main *bmain_old = CTX_data_main(C);
95  PyObject *main_mod = NULL;
96  PyObject *py_dict = NULL, *py_result = NULL;
97  PyGILState_STATE gilstate;
98 
99  char filepath_dummy[FILE_MAX];
101  const char *filepath_namespace = NULL;
102 
103  BLI_assert(filepath || text);
104 
105  if (filepath == NULL && text == NULL) {
106  return 0;
107  }
108 
109  bpy_context_set(C, &gilstate);
110 
111  PyC_MainModule_Backup(&main_mod);
112 
113  if (text) {
114  bpy_text_filepath_get(filepath_dummy, sizeof(filepath_dummy), bmain_old, text);
115  filepath_namespace = filepath_dummy;
116 
117  if (text->compiled == NULL) { /* if it wasn't already compiled, do it now */
118  char *buf;
119  PyObject *filepath_dummy_py;
120 
121  filepath_dummy_py = PyC_UnicodeFromByte(filepath_dummy);
122 
123  size_t buf_len_dummy;
124  buf = txt_to_buf(text, &buf_len_dummy);
125  text->compiled = Py_CompileStringObject(buf, filepath_dummy_py, Py_file_input, NULL, -1);
126  MEM_freeN(buf);
127 
128  Py_DECREF(filepath_dummy_py);
129 
130  if (PyErr_Occurred()) {
131  BPY_text_free_code(text);
132  }
133  }
134 
135  if (text->compiled) {
136  py_dict = PyC_DefaultNameSpace(filepath_dummy);
137  py_result = PyEval_EvalCode(text->compiled, py_dict, py_dict);
138  }
139  }
140  else {
141  FILE *fp = BLI_fopen(filepath, "r");
142  filepath_namespace = filepath;
143 
144  if (fp) {
145  py_dict = PyC_DefaultNameSpace(filepath);
146 
147 #ifdef _WIN32
148  /* Previously we used PyRun_File to run directly the code on a FILE
149  * object, but as written in the Python/C API Ref Manual, chapter 2,
150  * 'FILE structs for different C libraries can be different and
151  * incompatible'.
152  * So now we load the script file data to a buffer.
153  *
154  * Note on use of 'globals()', it's important not copy the dictionary because
155  * tools may inspect 'sys.modules["__main__"]' for variables defined in the code
156  * where using a copy of 'globals()' causes code execution
157  * to leave the main namespace untouched. see: T51444
158  *
159  * This leaves us with the problem of variables being included,
160  * currently this is worked around using 'dict.__del__' it's ugly but works.
161  */
162  {
163  const char *pystring =
164  "with open(__file__, 'rb') as f:"
165  "exec(compile(f.read(), __file__, 'exec'), globals().__delitem__('f') or globals())";
166 
167  fclose(fp);
168 
169  py_result = PyRun_String(pystring, Py_file_input, py_dict, py_dict);
170  }
171 #else
172  py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict);
173  fclose(fp);
174 #endif
175  }
176  else {
177  PyErr_Format(
178  PyExc_IOError, "Python file \"%s\" could not be opened: %s", filepath, strerror(errno));
179  py_result = NULL;
180  }
181  }
182 
183  if (!py_result) {
184  BPy_errors_to_report(reports);
185  if (text) {
186  if (do_jump) {
187  /* ensure text is valid before use, the script may have freed itself */
188  Main *bmain_new = CTX_data_main(C);
189  if ((bmain_old == bmain_new) && (BLI_findindex(&bmain_new->texts, text) != -1)) {
190  python_script_error_jump_text(text, filepath_namespace);
191  }
192  }
193  }
194  PyErr_Clear();
195  }
196  else {
197  Py_DECREF(py_result);
198  }
199 
200  if (py_dict) {
201 #ifdef PYMODULE_CLEAR_WORKAROUND
202  PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItem(PyImport_GetModuleDict(),
204  PyObject *dict_back = mmod->md_dict;
205  /* freeing the module will clear the namespace,
206  * gives problems running classes defined in this namespace being used later. */
207  mmod->md_dict = NULL;
208  Py_DECREF(dict_back);
209 #endif
210 
211 #undef PYMODULE_CLEAR_WORKAROUND
212  }
213 
214  PyC_MainModule_Restore(main_mod);
215 
216  bpy_context_clear(C, &gilstate);
217 
218  return (py_result != NULL);
219 }
220 
223 /* -------------------------------------------------------------------- */
227 bool BPY_run_filepath(bContext *C, const char *filepath, struct ReportList *reports)
228 {
229  return python_script_exec(C, filepath, NULL, reports, false);
230 }
231 
232 bool BPY_run_text(bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump)
233 {
234  return python_script_exec(C, NULL, text, reports, do_jump);
235 }
236 
242  const char *imports[],
243  const char *expr,
244  const int mode)
245 {
246  BLI_assert(expr);
247  PyGILState_STATE gilstate;
248  PyObject *main_mod = NULL;
249  PyObject *py_dict, *retval;
250  bool ok = true;
251 
252  if (expr[0] == '\0') {
253  return ok;
254  }
255 
256  bpy_context_set(C, &gilstate);
257 
258  PyC_MainModule_Backup(&main_mod);
259 
260  py_dict = PyC_DefaultNameSpace("<blender string>");
261 
262  if (imports && (!PyC_NameSpace_ImportArray(py_dict, imports))) {
263  Py_DECREF(py_dict);
264  retval = NULL;
265  }
266  else {
267  retval = PyRun_String(expr, mode, py_dict, py_dict);
268  }
269 
270  if (retval == NULL) {
271  ok = false;
272 
273  ReportList reports;
274  BKE_reports_init(&reports, RPT_STORE);
275  BPy_errors_to_report(&reports);
276  PyErr_Clear();
277 
278  /* Ensure the reports are printed. */
279  if (!BKE_reports_print_test(&reports, RPT_ERROR)) {
280  BKE_reports_print(&reports, RPT_ERROR);
281  }
282 
283  ReportList *wm_reports = CTX_wm_reports(C);
284  if (wm_reports) {
285  BLI_movelisttolist(&wm_reports->list, &reports.list);
286  }
287  else {
288  BKE_reports_clear(&reports);
289  }
290  }
291  else {
292  Py_DECREF(retval);
293  }
294 
295  PyC_MainModule_Restore(main_mod);
296 
297  bpy_context_clear(C, &gilstate);
298 
299  return ok;
300 }
301 
302 bool BPY_run_string_eval(bContext *C, const char *imports[], const char *expr)
303 {
304  return bpy_run_string_impl(C, imports, expr, Py_eval_input);
305 }
306 
307 bool BPY_run_string_exec(bContext *C, const char *imports[], const char *expr)
308 {
309  return bpy_run_string_impl(C, imports, expr, Py_file_input);
310 }
311 
314 /* -------------------------------------------------------------------- */
321 static void run_string_handle_error(struct BPy_RunErrInfo *err_info)
322 {
323  if (err_info == NULL) {
324  PyErr_Print();
325  PyErr_Clear();
326  return;
327  }
328 
329  /* Signal to do nothing. */
330  if (!(err_info->reports || err_info->r_string)) {
331  PyErr_Clear();
332  return;
333  }
334 
335  PyObject *py_err_str = err_info->use_single_line_error ? PyC_ExceptionBuffer_Simple() :
337  const char *err_str = py_err_str ? PyUnicode_AsUTF8(py_err_str) : "Unable to extract exception";
338  PyErr_Clear();
339 
340  if (err_info->reports != NULL) {
341  if (err_info->report_prefix) {
342  BKE_reportf(err_info->reports, RPT_ERROR, "%s: %s", err_info->report_prefix, err_str);
343  }
344  else {
345  BKE_report(err_info->reports, RPT_ERROR, err_str);
346  }
347  }
348 
349  /* Print the reports if they were not printed already. */
350  if ((err_info->reports == NULL) || !BKE_reports_print_test(err_info->reports, RPT_ERROR)) {
351  if (err_info->report_prefix) {
352  fprintf(stderr, "%s: ", err_info->report_prefix);
353  }
354  fprintf(stderr, "%s\n", err_str);
355  }
356 
357  if (err_info->r_string != NULL) {
358  *err_info->r_string = BLI_strdup(err_str);
359  }
360 
361  Py_XDECREF(py_err_str);
362 }
363 
365  const char *imports[],
366  const char *expr,
367  struct BPy_RunErrInfo *err_info,
368  double *r_value)
369 {
370  PyGILState_STATE gilstate;
371  bool ok = true;
372 
373  if (expr[0] == '\0') {
374  *r_value = 0.0;
375  return ok;
376  }
377 
378  bpy_context_set(C, &gilstate);
379 
380  ok = PyC_RunString_AsNumber(imports, expr, "<expr as number>", r_value);
381 
382  if (ok == false) {
383  run_string_handle_error(err_info);
384  }
385 
386  bpy_context_clear(C, &gilstate);
387 
388  return ok;
389 }
390 
392  const char *imports[],
393  const char *expr,
394  struct BPy_RunErrInfo *err_info,
395  char **r_value,
396  size_t *r_value_size)
397 {
398  PyGILState_STATE gilstate;
399  bool ok = true;
400 
401  if (expr[0] == '\0') {
402  *r_value = NULL;
403  return ok;
404  }
405 
406  bpy_context_set(C, &gilstate);
407 
408  ok = PyC_RunString_AsStringAndSize(imports, expr, "<expr as str>", r_value, r_value_size);
409 
410  if (ok == false) {
411  run_string_handle_error(err_info);
412  }
413 
414  bpy_context_clear(C, &gilstate);
415 
416  return ok;
417 }
418 
420  const char *imports[],
421  const char *expr,
422  struct BPy_RunErrInfo *err_info,
423  char **r_value)
424 {
425  size_t value_dummy_size;
426  return BPY_run_string_as_string_and_size(C, imports, expr, err_info, r_value, &value_dummy_size);
427 }
428 
430  const char *imports[],
431  const char *expr,
432  struct BPy_RunErrInfo *err_info,
433  intptr_t *r_value)
434 {
435  PyGILState_STATE gilstate;
436  bool ok = true;
437 
438  if (expr[0] == '\0') {
439  *r_value = 0;
440  return ok;
441  }
442 
443  bpy_context_set(C, &gilstate);
444 
445  ok = PyC_RunString_AsIntPtr(imports, expr, "<expr as intptr>", r_value);
446 
447  if (ok == false) {
448  run_string_handle_error(err_info);
449  }
450 
451  bpy_context_clear(C, &gilstate);
452 
453  return ok;
454 }
455 
struct ReportList * CTX_wm_reports(const bContext *C)
Definition: context.c:775
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
bool BKE_reports_print_test(const ReportList *reports, eReportType type)
Definition: report.c:259
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_reports_clear(ReportList *reports)
Definition: report.c:63
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
void BKE_reports_init(ReportList *reports, int flag)
Definition: report.c:50
void BKE_reports_print(ReportList *reports, eReportType level)
Definition: report.c:267
char * txt_to_buf(struct Text *text, size_t *r_buf_strlen) ATTR_NONNULL(1
void txt_move_to(struct Text *text, unsigned int line, unsigned int ch, bool sel)
Definition: text.c:1096
#define BLI_assert(a)
Definition: BLI_assert.h:46
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:906
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define FILE_MAX
#define SEP
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
void BPY_text_free_code(struct Text *text)
#define ID_BLEND_PATH(_bmain, _id)
Definition: DNA_ID.h:559
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
bool BPy_errors_to_report(ReportList *reports)
void bpy_context_clear(struct bContext *C, const PyGILState_STATE *gilstate)
void bpy_context_set(struct bContext *C, PyGILState_STATE *gilstate)
bool BPY_run_string_as_intptr(bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, intptr_t *r_value)
static void bpy_text_filepath_get(char *filepath, const size_t filepath_maxlen, const Main *bmain, const Text *text)
static bool python_script_exec(bContext *C, const char *filepath, struct Text *text, struct ReportList *reports, const bool do_jump)
static void python_script_error_jump_text(Text *text, const char *filepath)
bool BPY_run_string_eval(bContext *C, const char *imports[], const char *expr)
bool BPY_run_string_exec(bContext *C, const char *imports[], const char *expr)
bool BPY_run_string_as_number(bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, double *r_value)
static void run_string_handle_error(struct BPy_RunErrInfo *err_info)
bool BPY_run_string_as_string(bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, char **r_value)
bool BPY_run_filepath(bContext *C, const char *filepath, struct ReportList *reports)
bool BPY_run_string_as_string_and_size(bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, char **r_value, size_t *r_value_size)
bool BPY_run_text(bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump)
static bool bpy_run_string_impl(bContext *C, const char *imports[], const char *expr, const int mode)
PyObject * bpy_intern_str___main__
bool python_script_error_jump(const char *filepath, int *r_lineno, int *r_offset, int *r_lineno_end, int *r_offset_end)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
PyObject * PyC_DefaultNameSpace(const char *filename)
PyObject * PyC_ExceptionBuffer(void)
bool PyC_RunString_AsNumber(const char *imports[], const char *expr, const char *filename, double *r_value)
PyObject * PyC_ExceptionBuffer_Simple(void)
void PyC_MainModule_Backup(PyObject **r_main_mod)
bool PyC_RunString_AsStringAndSize(const char *imports[], const char *expr, const char *filename, char **r_value, size_t *r_value_size)
bool PyC_NameSpace_ImportArray(PyObject *py_dict, const char *imports[])
void PyC_MainModule_Restore(PyObject *main_mod)
PyObject * PyC_UnicodeFromByte(const char *str)
bool PyC_RunString_AsIntPtr(const char *imports[], const char *expr, const char *filename, intptr_t *r_value)
_W64 int intptr_t
Definition: stdint.h:118
const char * report_prefix
struct ReportList * reports
bool use_single_line_error
char name[66]
Definition: DNA_ID.h:378
Definition: BKE_main.h:121
ListBase texts
Definition: BKE_main.h:185
PyObject_HEAD PyObject * md_dict
void * compiled