Python API: restore bpy.app.autoexec_fail variables, some scripts use it.
[blender.git] / source / blender / python / intern / bpy_app.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/python/intern/bpy_app.c
24  *  \ingroup pythonintern
25  *
26  * This file defines a 'PyStructSequence' accessed via 'bpy.app', mostly
27  * exposing static applications variables such as version and buildinfo
28  * however some writable variables have been added such as 'debug' and 'tempdir'
29  */
30
31
32 #include <Python.h>
33
34 #include "bpy_app.h"
35
36 #include "bpy_app_alembic.h"
37 #include "bpy_app_ffmpeg.h"
38 #include "bpy_app_ocio.h"
39 #include "bpy_app_oiio.h"
40 #include "bpy_app_opensubdiv.h"
41 #include "bpy_app_openvdb.h"
42 #include "bpy_app_sdl.h"
43 #include "bpy_app_build_options.h"
44
45 #include "bpy_app_translations.h"
46
47 #include "bpy_app_handlers.h"
48 #include "bpy_driver.h"
49
50 /* modules */
51 #include "bpy_app_icons.h"
52
53 #include "BLI_utildefines.h"
54
55 #include "BKE_appdir.h"
56 #include "BKE_blender_version.h"
57 #include "BKE_global.h"
58 #include "BKE_library_override.h"
59
60 #include "DNA_ID.h"
61
62 #include "UI_interface_icons.h"
63
64 /* for notifiers */
65 #include "WM_api.h"
66 #include "WM_types.h"
67
68 #include "../generic/py_capi_utils.h"
69 #include "../generic/python_utildefines.h"
70
71 #ifdef BUILD_DATE
72 extern char build_date[];
73 extern char build_time[];
74 extern unsigned long build_commit_timestamp;
75 extern char build_commit_date[];
76 extern char build_commit_time[];
77 extern char build_hash[];
78 extern char build_branch[];
79 extern char build_platform[];
80 extern char build_type[];
81 extern char build_cflags[];
82 extern char build_cxxflags[];
83 extern char build_linkflags[];
84 extern char build_system[];
85 #endif
86
87 static PyTypeObject BlenderAppType;
88
89 static PyStructSequence_Field app_info_fields[] = {
90         {(char *)"version", (char *)"The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"},
91         {(char *)"version_string", (char *)"The Blender version formatted as a string"},
92         {(char *)"version_char", (char *)"The Blender version character (for minor releases)"},
93         {(char *)"version_cycle", (char *)"The release status of this build alpha/beta/rc/release"},
94         {(char *)"binary_path", (char *)"The location of blenders executable, useful for utilities that spawn new instances"},
95         {(char *)"background", (char *)"Boolean, True when blender is running without a user interface (started with -b)"},
96         {(char *)"factory_startup", (char *)"Boolean, True when blender is running with --factory-startup)"},
97
98         /* buildinfo */
99         {(char *)"build_date", (char *)"The date this blender instance was built"},
100         {(char *)"build_time", (char *)"The time this blender instance was built"},
101         {(char *)"build_commit_timestamp", (char *)"The unix timestamp of commit this blender instance was built"},
102         {(char *)"build_commit_date", (char *)"The date of commit this blender instance was built"},
103         {(char *)"build_commit_time", (char *)"The time of commit this blender instance was built"},
104         {(char *)"build_hash", (char *)"The commit hash this blender instance was built with"},
105         {(char *)"build_branch", (char *)"The branch this blender instance was built from"},
106         {(char *)"build_platform", (char *)"The platform this blender instance was built for"},
107         {(char *)"build_type", (char *)"The type of build (Release, Debug)"},
108         {(char *)"build_cflags", (char *)"C compiler flags"},
109         {(char *)"build_cxxflags", (char *)"C++ compiler flags"},
110         {(char *)"build_linkflags", (char *)"Binary linking flags"},
111         {(char *)"build_system", (char *)"Build system used"},
112
113         /* submodules */
114         {(char *)"alembic", (char *)"Alembic library information backend"},
115         {(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
116         {(char *)"ocio", (char *)"OpenColorIO library information backend"},
117         {(char *)"oiio", (char *)"OpenImageIO library information backend"},
118         {(char *)"opensubdiv", (char *)"OpenSubdiv library information backend"},
119         {(char *)"openvdb", (char *)"OpenVDB library information backend"},
120         {(char *)"sdl", (char *)"SDL library information backend"},
121         {(char *)"build_options", (char *)"A set containing most important enabled optional build features"},
122         {(char *)"handlers", (char *)"Application handler callbacks"},
123         {(char *)"translations", (char *)"Application and addons internationalization API"},
124
125         /* Modules (not struct sequence). */
126         {(char *)"icons", (char *)"Manage custom icons"},
127         {NULL},
128 };
129
130 PyDoc_STRVAR(bpy_app_doc,
131 "This module contains application values that remain unchanged during runtime.\n"
132 "\n"
133 "Submodules:\n"
134 "\n"
135 ".. toctree::\n"
136 "   :maxdepth: 1\n"
137 "\n"
138 "   bpy.app.handlers.rst\n"
139 "   bpy.app.icons.rst\n"
140 "   bpy.app.translations.rst\n"
141 );
142
143 static PyStructSequence_Desc app_info_desc = {
144         (char *)"bpy.app",     /* name */
145         bpy_app_doc,    /* doc */
146         app_info_fields,    /* fields */
147         ARRAY_SIZE(app_info_fields) - 1
148 };
149
150 static PyObject *make_app_info(void)
151 {
152         PyObject *app_info;
153         int pos = 0;
154
155         app_info = PyStructSequence_New(&BlenderAppType);
156         if (app_info == NULL) {
157                 return NULL;
158         }
159 #define SetIntItem(flag) \
160         PyStructSequence_SET_ITEM(app_info, pos++, PyLong_FromLong(flag))
161 #define SetStrItem(str) \
162         PyStructSequence_SET_ITEM(app_info, pos++, PyUnicode_FromString(str))
163 #define SetBytesItem(str) \
164         PyStructSequence_SET_ITEM(app_info, pos++, PyBytes_FromString(str))
165 #define SetObjItem(obj) \
166         PyStructSequence_SET_ITEM(app_info, pos++, obj)
167
168         SetObjItem(PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
169         SetObjItem(PyUnicode_FromFormat("%d.%02d (sub %d)",
170                                         BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
171
172         SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR));
173         SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE));
174         SetStrItem(BKE_appdir_program_path());
175         SetObjItem(PyBool_FromLong(G.background));
176         SetObjItem(PyBool_FromLong(G.factory_startup));
177
178         /* build info, use bytes since we can't assume _any_ encoding:
179          * see patch [#30154] for issue */
180 #ifdef BUILD_DATE
181         SetBytesItem(build_date);
182         SetBytesItem(build_time);
183         SetIntItem(build_commit_timestamp);
184         SetBytesItem(build_commit_date);
185         SetBytesItem(build_commit_time);
186         SetBytesItem(build_hash);
187         SetBytesItem(build_branch);
188         SetBytesItem(build_platform);
189         SetBytesItem(build_type);
190         SetBytesItem(build_cflags);
191         SetBytesItem(build_cxxflags);
192         SetBytesItem(build_linkflags);
193         SetBytesItem(build_system);
194 #else
195         SetBytesItem("Unknown");
196         SetBytesItem("Unknown");
197         SetIntItem(0);
198         SetBytesItem("Unknown");
199         SetBytesItem("Unknown");
200         SetBytesItem("Unknown");
201         SetBytesItem("Unknown");
202         SetBytesItem("Unknown");
203         SetBytesItem("Unknown");
204         SetBytesItem("Unknown");
205         SetBytesItem("Unknown");
206         SetBytesItem("Unknown");
207         SetBytesItem("Unknown");
208 #endif
209
210         SetObjItem(BPY_app_alembic_struct());
211         SetObjItem(BPY_app_ffmpeg_struct());
212         SetObjItem(BPY_app_ocio_struct());
213         SetObjItem(BPY_app_oiio_struct());
214         SetObjItem(BPY_app_opensubdiv_struct());
215         SetObjItem(BPY_app_openvdb_struct());
216         SetObjItem(BPY_app_sdl_struct());
217         SetObjItem(BPY_app_build_options_struct());
218         SetObjItem(BPY_app_handlers_struct());
219         SetObjItem(BPY_app_translations_struct());
220
221         /* modules */
222         SetObjItem(BPY_app_icons_module());
223
224 #undef SetIntItem
225 #undef SetStrItem
226 #undef SetBytesItem
227 #undef SetObjItem
228
229         if (PyErr_Occurred()) {
230                 Py_CLEAR(app_info);
231                 return NULL;
232         }
233         return app_info;
234 }
235
236 /* a few getsets because it makes sense for them to be in bpy.app even though
237  * they are not static */
238
239 PyDoc_STRVAR(bpy_app_debug_doc,
240 "Boolean, for debug info (started with --debug / --debug_* matching this attribute name)"
241 );
242 static PyObject *bpy_app_debug_get(PyObject *UNUSED(self), void *closure)
243 {
244         const int flag = POINTER_AS_INT(closure);
245         return PyBool_FromLong(G.debug & flag);
246 }
247
248 static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *closure)
249 {
250         const int flag = POINTER_AS_INT(closure);
251         const int param = PyObject_IsTrue(value);
252
253         if (param == -1) {
254                 PyErr_SetString(PyExc_TypeError, "bpy.app.debug can only be True/False");
255                 return -1;
256         }
257
258         if (param)  G.debug |=  flag;
259         else        G.debug &= ~flag;
260
261         return 0;
262 }
263
264 #define BROKEN_BINARY_PATH_PYTHON_HACK
265
266 PyDoc_STRVAR(bpy_app_binary_path_python_doc,
267 "String, the path to the python executable (read-only)"
268 );
269 static PyObject *bpy_app_binary_path_python_get(PyObject *self, void *UNUSED(closure))
270 {
271         /* refcount is held in BlenderAppType.tp_dict */
272         static PyObject *ret = NULL;
273
274         if (ret == NULL) {
275                 /* only run once */
276                 char fullpath[1024];
277                 BKE_appdir_program_python_search(
278                         fullpath, sizeof(fullpath),
279                         PY_MAJOR_VERSION, PY_MINOR_VERSION);
280                 ret = PyC_UnicodeFromByte(fullpath);
281 #ifdef BROKEN_BINARY_PATH_PYTHON_HACK
282                 Py_INCREF(ret);
283                 UNUSED_VARS(self);
284 #else
285                 PyDict_SetItem(BlenderAppType.tp_dict, /* XXX BAAAADDDDDD! self is not a PyDescr at all! it's bpy.app!!! */ PyDescr_NAME(self), ret);
286 #endif
287         }
288         else {
289                 Py_INCREF(ret);
290         }
291
292         return ret;
293 }
294
295 PyDoc_STRVAR(bpy_app_debug_value_doc,
296 "Int, number which can be set to non-zero values for testing purposes"
297 );
298 static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(closure))
299 {
300         return PyLong_FromLong(G.debug_value);
301 }
302
303 static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
304 {
305         int param = PyC_Long_AsI32(value);
306
307         if (param == -1 && PyErr_Occurred()) {
308                 PyErr_SetString(PyExc_TypeError, "bpy.app.debug_value can only be set to a whole number");
309                 return -1;
310         }
311
312         G.debug_value = param;
313
314         WM_main_add_notifier(NC_WINDOW, NULL);
315
316         return 0;
317 }
318
319 static PyObject *bpy_app_global_flag_get(PyObject *UNUSED(self), void *closure)
320 {
321         const int flag = POINTER_AS_INT(closure);
322         return PyBool_FromLong(G.f & flag);
323 }
324
325 PyDoc_STRVAR(bpy_app_tempdir_doc,
326 "String, the temp directory used by blender (read-only)"
327 );
328 static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closure))
329 {
330         return PyC_UnicodeFromByte(BKE_tempdir_session());
331 }
332
333 PyDoc_STRVAR(bpy_app_driver_dict_doc,
334 "Dictionary for drivers namespace, editable in-place, reset on file load (read-only)"
335 );
336 static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(closure))
337 {
338         if (bpy_pydriver_Dict == NULL) {
339                 if (bpy_pydriver_create_dict() != 0) {
340                         PyErr_SetString(PyExc_RuntimeError, "bpy.app.driver_namespace failed to create dictionary");
341                         return NULL;
342                 }
343         }
344
345         return Py_INCREF_RET(bpy_pydriver_Dict);
346 }
347
348 PyDoc_STRVAR(bpy_app_preview_render_size_doc,
349 "Reference size for icon/preview renders (read-only)"
350 );
351 static PyObject *bpy_app_preview_render_size_get(PyObject *UNUSED(self), void *closure)
352 {
353         return PyLong_FromLong((long)UI_preview_render_size(POINTER_AS_INT(closure)));
354 }
355
356 static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure))
357 {
358         return PyC_UnicodeFromByte(G.autoexec_fail);
359 }
360
361
362 PyDoc_STRVAR(bpy_app_use_static_override_doc,
363 "Boolean, whether static override is exposed in UI or not."
364 );
365 static PyObject *bpy_app_use_static_override_get(PyObject *UNUSED(self), void *UNUSED(closure))
366 {
367         return PyBool_FromLong((long)BKE_override_static_is_enabled());
368 }
369
370 static int bpy_app_use_static_override_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
371 {
372         const int param = PyC_Long_AsBool(value);
373
374         if (param == -1 && PyErr_Occurred()) {
375                 PyErr_SetString(PyExc_TypeError, "bpy.app.use_static_override must be a boolean");
376                 return -1;
377         }
378
379         BKE_override_static_enable((const bool)param);
380
381         return 0;
382 }
383
384
385 static PyGetSetDef bpy_app_getsets[] = {
386         {(char *)"debug",           bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG},
387         {(char *)"debug_ffmpeg",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FFMPEG},
388         {(char *)"debug_freestyle", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FREESTYLE},
389         {(char *)"debug_python",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_PYTHON},
390         {(char *)"debug_events",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_EVENTS},
391         {(char *)"debug_handlers",  bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_HANDLERS},
392         {(char *)"debug_wm",        bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM},
393         {(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH},
394         {(char *)"debug_depsgraph_build", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_BUILD},
395         {(char *)"debug_depsgraph_eval", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_EVAL},
396         {(char *)"debug_depsgraph_tag", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TAG},
397         {(char *)"debug_depsgraph_time", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TIME},
398         {(char *)"debug_depsgraph_pretty", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_PRETTY},
399         {(char *)"debug_simdata",   bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA},
400         {(char *)"debug_gpumem",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM},
401         {(char *)"debug_io",        bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_IO},
402
403         {(char *)"use_static_override", bpy_app_use_static_override_get, bpy_app_use_static_override_set, (char *)bpy_app_use_static_override_doc, NULL},
404
405         {(char *)"binary_path_python", bpy_app_binary_path_python_get, NULL, (char *)bpy_app_binary_path_python_doc, NULL},
406
407         {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL},
408         {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL},
409         {(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)bpy_app_driver_dict_doc, NULL},
410
411         {(char *)"render_icon_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_ICON},
412         {(char *)"render_preview_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_PREVIEW},
413
414         /* security */
415         {(char *)"autoexec_fail", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL},
416         {(char *)"autoexec_fail_quiet", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL_QUIET},
417         {(char *)"autoexec_fail_message", bpy_app_autoexec_fail_message_get, NULL, NULL, NULL},
418         {NULL, NULL, NULL, NULL, NULL}
419 };
420
421 static void py_struct_seq_getset_init(void)
422 {
423         /* tricky dynamic members, not to py-spec! */
424         for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) {
425                 PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset);
426                 PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(item), item);
427                 Py_DECREF(item);
428         }
429 }
430 /* end dynamic bpy.app */
431
432
433 PyObject *BPY_app_struct(void)
434 {
435         PyObject *ret;
436
437         PyStructSequence_InitType(&BlenderAppType, &app_info_desc);
438
439         ret = make_app_info();
440
441         /* prevent user from creating new instances */
442         BlenderAppType.tp_init = NULL;
443         BlenderAppType.tp_new = NULL;
444         BlenderAppType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
445
446         /* kindof a hack ontop of PyStructSequence */
447         py_struct_seq_getset_init();
448
449         return ret;
450 }