1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17 /** \file
18 * \ingroup pythonintern
19 */
20
21 #include <stdio.h>
22
23 #include <Python.h>
24
25 #include "MEM_guardedalloc.h"
26
27 #include "BLI_fileops.h"
28 #include "BLI_listbase.h"
29 #include "BLI_path_util.h"
30 #include "BLI_string.h"
31
32 #include "BKE_context.h"
33 #include "BKE_main.h"
34 #include "BKE_text.h"
35
36 #include "DNA_text_types.h"
37
38 #include "BPY_extern.h"
39 #include "BPY_extern_run.h"
40
41 #include "bpy_capi_utils.h"
42 #include "bpy_intern_string.h"
43 #include "bpy_traceback.h"
44
45 #include "../generic/py_capi_utils.h"
46
47 /* -------------------------------------------------------------------- */
48 /** \name Private Utilities
49 * \{ */
50
python_script_error_jump_text(Text * text)51 static void python_script_error_jump_text(Text *text)
52 {
53 int lineno;
54 int offset;
55 python_script_error_jump(text->id.name + 2, &lineno, &offset);
56 if (lineno != -1) {
57 /* select the line with the error */
58 txt_move_to(text, lineno - 1, INT_MAX, false);
59 txt_move_to(text, lineno - 1, offset, true);
60 }
61 }
62
63 /* returns a dummy filename for a textblock so we can tell what file a text block comes from */
bpy_text_filename_get(char * fn,const Main * bmain,size_t fn_len,const Text * text)64 static void bpy_text_filename_get(char *fn, const Main *bmain, size_t fn_len, const Text *text)
65 {
66 BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bmain, &text->id), SEP, text->id.name + 2);
67 }
68
69 /* Very annoying! Undo #_PyModule_Clear(), see T23871. */
70 #define PYMODULE_CLEAR_WORKAROUND
71
72 #ifdef PYMODULE_CLEAR_WORKAROUND
73 /* bad!, we should never do this, but currently only safe way I could find to keep namespace.
74 * from being cleared. - campbell */
75 typedef struct {
76 PyObject_HEAD PyObject *md_dict;
77 /* omit other values, we only want the dict. */
78 } PyModuleObject;
79 #endif
80
python_script_exec(bContext * C,const char * fn,struct Text * text,struct ReportList * reports,const bool do_jump)81 static bool python_script_exec(
82 bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const bool do_jump)
83 {
84 Main *bmain_old = CTX_data_main(C);
85 PyObject *main_mod = NULL;
86 PyObject *py_dict = NULL, *py_result = NULL;
87 PyGILState_STATE gilstate;
88
89 BLI_assert(fn || text);
90
91 if (fn == NULL && text == NULL) {
92 return 0;
93 }
94
95 bpy_context_set(C, &gilstate);
96
97 PyC_MainModule_Backup(&main_mod);
98
99 if (text) {
100 char fn_dummy[FILE_MAXDIR];
101 bpy_text_filename_get(fn_dummy, bmain_old, sizeof(fn_dummy), text);
102
103 if (text->compiled == NULL) { /* if it wasn't already compiled, do it now */
104 char *buf;
105 PyObject *fn_dummy_py;
106
107 fn_dummy_py = PyC_UnicodeFromByte(fn_dummy);
108
109 buf = txt_to_buf(text, NULL);
110 text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1);
111 MEM_freeN(buf);
112
113 Py_DECREF(fn_dummy_py);
114
115 if (PyErr_Occurred()) {
116 if (do_jump) {
117 python_script_error_jump_text(text);
118 }
119 BPY_text_free_code(text);
120 }
121 }
122
123 if (text->compiled) {
124 py_dict = PyC_DefaultNameSpace(fn_dummy);
125 py_result = PyEval_EvalCode(text->compiled, py_dict, py_dict);
126 }
127 }
128 else {
129 FILE *fp = BLI_fopen(fn, "r");
130
131 if (fp) {
132 py_dict = PyC_DefaultNameSpace(fn);
133
134 #ifdef _WIN32
135 /* Previously we used PyRun_File to run directly the code on a FILE
136 * object, but as written in the Python/C API Ref Manual, chapter 2,
137 * 'FILE structs for different C libraries can be different and
138 * incompatible'.
139 * So now we load the script file data to a buffer.
140 *
141 * Note on use of 'globals()', it's important not copy the dictionary because
142 * tools may inspect 'sys.modules["__main__"]' for variables defined in the code
143 * where using a copy of 'globals()' causes code execution
144 * to leave the main namespace untouched. see: T51444
145 *
146 * This leaves us with the problem of variables being included,
147 * currently this is worked around using 'dict.__del__' it's ugly but works.
148 */
149 {
150 const char *pystring =
151 "with open(__file__, 'rb') as f:"
152 "exec(compile(f.read(), __file__, 'exec'), globals().__delitem__('f') or globals())";
153
154 fclose(fp);
155
156 py_result = PyRun_String(pystring, Py_file_input, py_dict, py_dict);
157 }
158 #else
159 py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict);
160 fclose(fp);
161 #endif
162 }
163 else {
164 PyErr_Format(
165 PyExc_IOError, "Python file \"%s\" could not be opened: %s", fn, strerror(errno));
166 py_result = NULL;
167 }
168 }
169
170 if (!py_result) {
171 if (text) {
172 if (do_jump) {
173 /* ensure text is valid before use, the script may have freed its self */
174 Main *bmain_new = CTX_data_main(C);
175 if ((bmain_old == bmain_new) && (BLI_findindex(&bmain_new->texts, text) != -1)) {
176 python_script_error_jump_text(text);
177 }
178 }
179 }
180 BPy_errors_to_report(reports);
181 }
182 else {
183 Py_DECREF(py_result);
184 }
185
186 if (py_dict) {
187 #ifdef PYMODULE_CLEAR_WORKAROUND
188 PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItem(PyImport_GetModuleDict(),
189 bpy_intern_str___main__);
190 PyObject *dict_back = mmod->md_dict;
191 /* freeing the module will clear the namespace,
192 * gives problems running classes defined in this namespace being used later. */
193 mmod->md_dict = NULL;
194 Py_DECREF(dict_back);
195 #endif
196
197 #undef PYMODULE_CLEAR_WORKAROUND
198 }
199
200 PyC_MainModule_Restore(main_mod);
201
202 bpy_context_clear(C, &gilstate);
203
204 return (py_result != NULL);
205 }
206
207 /** \} */
208
209 /* -------------------------------------------------------------------- */
210 /** \name Run Text / Filename / String
211 * \{ */
212
213 /* Can run a file or text block */
BPY_run_filepath(bContext * C,const char * filepath,struct ReportList * reports)214 bool BPY_run_filepath(bContext *C, const char *filepath, struct ReportList *reports)
215 {
216 return python_script_exec(C, filepath, NULL, reports, false);
217 }
218
BPY_run_text(bContext * C,struct Text * text,struct ReportList * reports,const bool do_jump)219 bool BPY_run_text(bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump)
220 {
221 return python_script_exec(C, NULL, text, reports, do_jump);
222 }
223
224 /**
225 * \param mode: Passed to #PyRun_String, matches Python's `compile` functions mode argument.
226 * #Py_eval_input for `eval`, #Py_file_input for `exec`.
227 */
bpy_run_string_impl(bContext * C,const char * imports[],const char * expr,const int mode)228 static bool bpy_run_string_impl(bContext *C,
229 const char *imports[],
230 const char *expr,
231 const int mode)
232 {
233 BLI_assert(expr);
234 PyGILState_STATE gilstate;
235 PyObject *main_mod = NULL;
236 PyObject *py_dict, *retval;
237 bool ok = true;
238
239 if (expr[0] == '\0') {
240 return ok;
241 }
242
243 bpy_context_set(C, &gilstate);
244
245 PyC_MainModule_Backup(&main_mod);
246
247 py_dict = PyC_DefaultNameSpace("<blender string>");
248
249 if (imports && (!PyC_NameSpace_ImportArray(py_dict, imports))) {
250 Py_DECREF(py_dict);
251 retval = NULL;
252 }
253 else {
254 retval = PyRun_String(expr, mode, py_dict, py_dict);
255 }
256
257 if (retval == NULL) {
258 ok = false;
259 BPy_errors_to_report(CTX_wm_reports(C));
260 }
261 else {
262 Py_DECREF(retval);
263 }
264
265 PyC_MainModule_Restore(main_mod);
266
267 bpy_context_clear(C, &gilstate);
268
269 return ok;
270 }
271
272 /**
273 * Run an expression, matches: `exec(compile(..., "eval"))`
274 */
BPY_run_string_eval(bContext * C,const char * imports[],const char * expr)275 bool BPY_run_string_eval(bContext *C, const char *imports[], const char *expr)
276 {
277 return bpy_run_string_impl(C, imports, expr, Py_eval_input);
278 }
279
280 /**
281 * Run an entire script, matches: `exec(compile(..., "exec"))`
282 */
BPY_run_string_exec(bContext * C,const char * imports[],const char * expr)283 bool BPY_run_string_exec(bContext *C, const char *imports[], const char *expr)
284 {
285 return bpy_run_string_impl(C, imports, expr, Py_file_input);
286 }
287
288 /** \} */
289
290 /* -------------------------------------------------------------------- */
291 /** \name Run Python & Evaluate Utilities
292 *
293 * Return values as plain C types, useful to run Python scripts
294 * in code that doesn't deal with Python data-types.
295 * \{ */
296
297 /**
298 * \return success
299 */
BPY_run_string_as_number(bContext * C,const char * imports[],const char * expr,const char * report_prefix,double * r_value)300 bool BPY_run_string_as_number(bContext *C,
301 const char *imports[],
302 const char *expr,
303 const char *report_prefix,
304 double *r_value)
305 {
306 PyGILState_STATE gilstate;
307 bool ok = true;
308
309 if (!r_value || !expr) {
310 return -1;
311 }
312
313 if (expr[0] == '\0') {
314 *r_value = 0.0;
315 return ok;
316 }
317
318 bpy_context_set(C, &gilstate);
319
320 ok = PyC_RunString_AsNumber(imports, expr, "<expr as number>", r_value);
321
322 if (ok == false) {
323 if (report_prefix != NULL) {
324 BPy_errors_to_report_ex(CTX_wm_reports(C), report_prefix, false, false);
325 }
326 else {
327 PyErr_Clear();
328 }
329 }
330
331 bpy_context_clear(C, &gilstate);
332
333 return ok;
334 }
335
336 /**
337 * \return success
338 */
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)339 bool BPY_run_string_as_string_and_size(bContext *C,
340 const char *imports[],
341 const char *expr,
342 const char *report_prefix,
343 char **r_value,
344 size_t *r_value_size)
345 {
346 BLI_assert(r_value && expr);
347 PyGILState_STATE gilstate;
348 bool ok = true;
349
350 if (expr[0] == '\0') {
351 *r_value = NULL;
352 return ok;
353 }
354
355 bpy_context_set(C, &gilstate);
356
357 ok = PyC_RunString_AsStringAndSize(imports, expr, "<expr as str>", r_value, r_value_size);
358
359 if (ok == false) {
360 if (report_prefix != NULL) {
361 BPy_errors_to_report_ex(CTX_wm_reports(C), false, false, report_prefix);
362 }
363 else {
364 PyErr_Clear();
365 }
366 }
367
368 bpy_context_clear(C, &gilstate);
369
370 return ok;
371 }
372
BPY_run_string_as_string(bContext * C,const char * imports[],const char * expr,const char * report_prefix,char ** r_value)373 bool BPY_run_string_as_string(bContext *C,
374 const char *imports[],
375 const char *expr,
376 const char *report_prefix,
377 char **r_value)
378 {
379 size_t value_dummy_size;
380 return BPY_run_string_as_string_and_size(
381 C, imports, expr, report_prefix, r_value, &value_dummy_size);
382 }
383
384 /**
385 * Support both int and pointers.
386 *
387 * \return success
388 */
BPY_run_string_as_intptr(bContext * C,const char * imports[],const char * expr,const char * report_prefix,intptr_t * r_value)389 bool BPY_run_string_as_intptr(bContext *C,
390 const char *imports[],
391 const char *expr,
392 const char *report_prefix,
393 intptr_t *r_value)
394 {
395 BLI_assert(r_value && expr);
396 PyGILState_STATE gilstate;
397 bool ok = true;
398
399 if (expr[0] == '\0') {
400 *r_value = 0;
401 return ok;
402 }
403
404 bpy_context_set(C, &gilstate);
405
406 ok = PyC_RunString_AsIntPtr(imports, expr, "<expr as intptr>", r_value);
407
408 if (ok == false) {
409 if (report_prefix != NULL) {
410 BPy_errors_to_report_ex(CTX_wm_reports(C), report_prefix, false, false);
411 }
412 else {
413 PyErr_Clear();
414 }
415 }
416
417 bpy_context_clear(C, &gilstate);
418
419 return ok;
420 }
421
422 /** \} */
423