Blender V4.3
bpy_interface.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
13#include <Python.h>
14#include <frameobject.h>
15
16#ifdef WITH_PYTHON_MODULE
17# include "pylifecycle.h" /* For `Py_Version`. */
18#endif
19
20#include "MEM_guardedalloc.h"
21
22#include "CLG_log.h"
23
24#include "BLI_fileops.h"
25#include "BLI_listbase.h"
26#include "BLI_path_utils.hh"
27#include "BLI_string.h"
28#include "BLI_string_utf8.h"
29#include "BLI_threads.h"
30#include "BLI_utildefines.h"
31
32#include "BLT_translation.hh"
33
34#include "RNA_types.hh"
35
36#include "bpy.hh"
37#include "bpy_capi_utils.hh"
38#include "bpy_intern_string.hh"
39#include "bpy_path.hh"
40#include "bpy_props.hh"
41#include "bpy_rna.hh"
42#include "bpy_traceback.hh"
43
45
46#include "DNA_text_types.h"
47
48#include "BKE_appdir.hh"
49#include "BKE_context.hh"
50#include "BKE_global.hh" /* Only for script checking. */
51#include "BKE_main.hh"
52#include "BKE_text.h"
53
54#ifdef WITH_CYCLES
55# include "CCL_api.h"
56#endif
57
58#include "BPY_extern.hh"
59#include "BPY_extern_python.hh"
60#include "BPY_extern_run.hh"
61
63
64/* `inittab` initialization functions. */
66#include "../generic/bgl.h"
71#include "../gpu/gpu_py_api.hh"
73
74/* Logging types to use anywhere in the Python modules. */
75
79
80/* For internal use, when starting and ending Python scripts. */
81
82/* In case a Python script triggers another Python call,
83 * stop #bpy_context_clear from invalidating. */
84static int py_call_level = 0;
85
86/* Set by command line arguments before Python starts. */
87static bool py_use_system_env = false;
88
89// #define TIME_PY_RUN /* Simple python tests. prints on exit. */
90
91#ifdef TIME_PY_RUN
92# include "BLI_time.h"
93static int bpy_timer_count = 0;
95static double bpy_timer;
97static double bpy_timer_run;
99static double bpy_timer_run_tot;
100#endif
101
103{
104 /* Don't do this from a non-main (e.g. render) thread, it can cause a race
105 * condition on `C->data.recursion`. Ideal solution would be to disable
106 * context entirely from non-main threads, but that's more complicated. */
107 if (!BLI_thread_is_main()) {
108 return;
109 }
110
112
113 /* Can give really bad results if this isn't here. */
115}
116
117void bpy_context_set(bContext *C, PyGILState_STATE *gilstate)
118{
120
121 if (gilstate) {
122 *gilstate = PyGILState_Ensure();
123 }
124
125 if (py_call_level == 1) {
127
128#ifdef TIME_PY_RUN
129 if (bpy_timer_count == 0) {
130 /* Record time from the beginning. */
131 bpy_timer = BLI_time_now_seconds();
132 bpy_timer_run = bpy_timer_run_tot = 0.0;
133 }
134 bpy_timer_run = BLI_time_now_seconds();
135
136 bpy_timer_count++;
137#endif
138 }
139}
140
141void bpy_context_clear(bContext * /*C*/, const PyGILState_STATE *gilstate)
142{
144
145 if (gilstate) {
146 PyGILState_Release(*gilstate);
147 }
148
149 if (py_call_level < 0) {
150 fprintf(stderr, "ERROR: Python context internal state bug. this should not happen!\n");
151 }
152 else if (py_call_level == 0) {
153 /* NOTE: Unfortunately calling classes currently won't store the context.
154 * Can't set nullptr because of this - but this is very flaky still. */
155#if 0
156 BPY_context_set(nullptr);
157#endif
158
159#ifdef TIME_PY_RUN
160 bpy_timer_run_tot += BLI_time_now_seconds() - bpy_timer_run;
161 bpy_timer_count++;
162#endif
163 }
164}
165
167{
168 if (UNLIKELY(C == nullptr)) {
169 return;
170 }
172}
173
175 void *dict_orig,
176 const char *context_members[],
177 uint context_members_len)
178{
179 PyGILState_STATE gilstate;
180 const bool use_gil = !PyC_IsInterpreterActive();
181
182 if (use_gil) {
183 gilstate = PyGILState_Ensure();
184 }
185
186 /* Copy on write. */
187 if (*dict_p == dict_orig) {
188 *dict_p = PyDict_Copy(static_cast<PyObject *>(dict_orig));
189 }
190
191 PyObject *dict = static_cast<PyObject *>(*dict_p);
192 BLI_assert(PyDict_Check(dict));
193
194 /* Use #PyDict_Pop instead of #PyDict_DelItemString to avoid setting the exception,
195 * while supported it's good to avoid for low level functions like this that run often. */
196 for (uint i = 0; i < context_members_len; i++) {
197 PyObject *key = PyUnicode_FromString(context_members[i]);
198 PyObject *item = _PyDict_Pop(dict, key, Py_None);
199 Py_DECREF(key);
200 Py_DECREF(item);
201 }
202
203 if (use_gil) {
204 PyGILState_Release(gilstate);
205 }
206}
207
209{
210 if (text->compiled) {
211 PyGILState_STATE gilstate;
212 const bool use_gil = !PyC_IsInterpreterActive();
213
214 if (use_gil) {
215 gilstate = PyGILState_Ensure();
216 }
217
218 Py_DECREF((PyObject *)text->compiled);
219 text->compiled = nullptr;
220
221 if (use_gil) {
222 PyGILState_Release(gilstate);
223 }
224 }
225}
226
228{
229 /* Correct but slow, this runs all the time operator poll, panel draw etc
230 * (100's of time a second). */
231#if 0
232 PyObject *mod = PyImport_ImportModuleLevel("bpy", nullptr, nullptr, nullptr, 0);
233 PyModule_AddObject(mod, "data", BPY_rna_module());
234 PyModule_AddObject(mod, "types", BPY_rna_types()); /* This does not need updating. */
235#endif
236
237 /* Refreshes the main struct. */
239}
240
242{
243 return static_cast<bContext *>(bpy_context_module->ptr.data);
244}
245
247{
248 bpy_context_module->ptr.data = (void *)C;
249}
250
251#ifdef WITH_FLUID
252/* Defined in `manta` module. */
253extern "C" PyObject *Manta_initPython(void);
254#endif
255
256#ifdef WITH_AUDASPACE_PY
257/* Defined in `AUD_C-API.cpp`. */
258extern "C" PyObject *AUD_initPython(void);
259#endif
260
261#ifdef WITH_CYCLES
262/* Defined in `cycles` module. */
263static PyObject *CCL_initPython()
264{
265 return (PyObject *)CCL_python_module_init();
266}
267#endif
268
269#ifdef WITH_HYDRA
270/* Defined in `render_hydra` module. */
271PyObject *BPyInit_hydra();
272#endif
273
274static _inittab bpy_internal_modules[] = {
275 {"mathutils", PyInit_mathutils},
276#if 0
277 {"mathutils.geometry", PyInit_mathutils_geometry},
278 {"mathutils.noise", PyInit_mathutils_noise},
279 {"mathutils.kdtree", PyInit_mathutils_kdtree},
280#endif
281 {"_bpy_path", BPyInit__bpy_path},
282 {"bgl", BPyInit_bgl},
283 {"blf", BPyInit_blf},
284 {"bl_math", BPyInit_bl_math},
285 {"imbuf", BPyInit_imbuf},
286 {"bmesh", BPyInit_bmesh},
287#if 0
288 {"bmesh.types", BPyInit_bmesh_types},
289 {"bmesh.utils", BPyInit_bmesh_utils},
290 {"bmesh.utils", BPyInit_bmesh_geometry},
291#endif
292#ifdef WITH_FLUID
293 {"manta", Manta_initPython},
294#endif
295#ifdef WITH_AUDASPACE_PY
296 {"aud", AUD_initPython},
297#endif
298#ifdef WITH_CYCLES
299 {"_cycles", CCL_initPython},
300#endif
301 {"gpu", BPyInit_gpu},
302 {"idprop", BPyInit_idprop},
303#ifdef WITH_HYDRA
304 {"_bpy_hydra", BPyInit_hydra},
305#endif
306 {nullptr, nullptr},
307};
308
309#ifndef WITH_PYTHON_MODULE
319static void pystatus_exit_on_error(const PyStatus &status)
320{
321 if (UNLIKELY(PyStatus_Exception(status))) {
322 fputs("Internal error initializing Python!\n", stderr);
323 /* This calls `exit`. */
324 Py_ExitStatusException(status);
325 }
326}
327#endif
328
329void BPY_python_start(bContext *C, int argc, const char **argv)
330{
331#ifndef WITH_PYTHON_MODULE
332 BLI_assert_msg(Py_IsInitialized() == 0, "Python has already been initialized");
333
334 /* #PyPreConfig (early-configuration). */
335 {
336 PyPreConfig preconfig;
337 PyStatus status;
338
339 /* To narrow down reports where the systems Python is inexplicably used, see: #98131. */
340 CLOG_INFO(
342 2,
343 "Initializing %s support for the systems Python environment such as 'PYTHONPATH' and "
344 "the user-site directory.",
345 py_use_system_env ? "*with*" : "*without*");
346
347 if (py_use_system_env) {
348 PyPreConfig_InitPythonConfig(&preconfig);
349 }
350 else {
351 /* Only use the systems environment variables and site when explicitly requested.
352 * Since an incorrect 'PYTHONPATH' causes difficult to debug errors, see: #72807.
353 * An alternative to setting `preconfig.use_environment = 0` */
354 PyPreConfig_InitIsolatedConfig(&preconfig);
355 }
356
357 /* Force `utf-8` on all platforms, since this is what's used for Blender's internal strings,
358 * providing consistent encoding behavior across all Blender installations.
359 *
360 * This also uses the `surrogateescape` error handler ensures any unexpected bytes are escaped
361 * instead of raising an error.
362 *
363 * Without this `sys.getfilesystemencoding()` and `sys.stdout` for example may be set to ASCII
364 * or some other encoding - where printing some `utf-8` values will raise an error.
365 *
366 * This can cause scripts to fail entirely on some systems.
367 *
368 * This assignment is the equivalent of enabling the `PYTHONUTF8` environment variable.
369 * See `PEP-540` for details on exactly what this changes. */
370 preconfig.utf8_mode = true;
371
372 /* Note that there is no reason to call #Py_PreInitializeFromBytesArgs here
373 * as this is only used so that command line arguments can be handled by Python itself,
374 * not for setting `sys.argv` (handled below). */
375 status = Py_PreInitialize(&preconfig);
377 }
378
379 /* Must run before python initializes, but after #PyPreConfig. */
380 PyImport_ExtendInittab(bpy_internal_modules);
381
382 /* #PyConfig (initialize Python). */
383 {
384 PyConfig config;
385 PyStatus status;
386 bool has_python_executable = false;
387
388 if (py_use_system_env) {
389 PyConfig_InitPythonConfig(&config);
390 }
391 else {
392 PyConfig_InitIsolatedConfig(&config);
393 }
394
395 /* Suppress error messages when calculating the module search path.
396 * While harmless, it's noisy. */
397 config.pathconfig_warnings = 0;
398
399 /* Allow the user site directory because this is used
400 * when PIP installing packages from Blender, see: #104000.
401 *
402 * NOTE(@ideasman42): While an argument can be made for isolating Blender's Python
403 * from the users home directory entirely, an alternative directory should be used in that
404 * case - so PIP can be used to install packages. Otherwise PIP will install packages to a
405 * directory which us not in the users `sys.path`, see `site.USER_BASE` for details. */
406 // config.user_site_directory = py_use_system_env;
407
408 /* While `sys.argv` is set, we don't want Python to interpret it. */
409 config.parse_argv = 0;
410 status = PyConfig_SetBytesArgv(&config, argc, (char *const *)argv);
412
413 /* Needed for Python's initialization for portable Python installations.
414 * We could use #Py_SetPath, but this overrides Python's internal logic
415 * for calculating its own module search paths.
416 *
417 * `sys.executable` is overwritten after initialization to the Python binary. */
418 {
419 const char *program_path = BKE_appdir_program_path();
420 status = PyConfig_SetBytesString(&config, &config.program_name, program_path);
422 }
423
424 /* Setting the program name is important so the 'multiprocessing' module
425 * can launch new Python instances. */
426 {
427 char program_path[FILE_MAX];
429 program_path, sizeof(program_path), PY_MAJOR_VERSION, PY_MINOR_VERSION))
430 {
431 status = PyConfig_SetBytesString(&config, &config.executable, program_path);
433 has_python_executable = true;
434 }
435 else {
436 /* Set to `sys.executable = None` below (we can't do before Python is initialized). */
437 fprintf(stderr,
438 "Unable to find the Python binary, "
439 "the multiprocessing module may not be functional!\n");
440 }
441 }
442
443 /* Allow to use our own included Python. `py_path_bundle` may be nullptr. */
444 {
445 const std::optional<std::string> py_path_bundle = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON,
446 nullptr);
447 if (py_path_bundle.has_value()) {
448
449# ifdef __APPLE__
450 /* Mac-OS allows file/directory names to contain `:` character
451 * (represented as `/` in the Finder) but current Python lib (as of release 3.1.1)
452 * doesn't handle these correctly. */
453 if (strchr(py_path_bundle->c_str(), ':')) {
454 fprintf(stderr,
455 "Warning! Blender application is located in a path containing ':' or '/' chars\n"
456 "This may make Python import function fail\n");
457 }
458# endif /* __APPLE__ */
459
460 status = PyConfig_SetBytesString(&config, &config.home, py_path_bundle->c_str());
462
463# ifdef PYTHON_SSL_CERT_FILE
464 /* Point to the portable SSL certificate to support HTTPS access, see: #102300. */
465 const char *ssl_cert_file_env = "SSL_CERT_FILE";
466 if (BLI_getenv(ssl_cert_file_env) == nullptr) {
467 const char *ssl_cert_file_suffix = PYTHON_SSL_CERT_FILE;
468 char ssl_cert_file[FILE_MAX];
470 ssl_cert_file, sizeof(ssl_cert_file), py_path_bundle->c_str(), ssl_cert_file_suffix);
471 BLI_setenv(ssl_cert_file_env, ssl_cert_file);
472 }
473# endif /* PYTHON_SSL_CERT_FILE */
474 }
475 else {
476/* Common enough to use the system Python on Linux/Unix, warn on other systems. */
477# if defined(__APPLE__) || defined(_WIN32)
478 fprintf(stderr,
479 "Bundled Python not found and is expected on this platform "
480 "(the 'install' target may have not been built)\n");
481# endif
482 }
483 }
484
485 /* Initialize Python (also acquires lock). */
486 status = Py_InitializeFromConfig(&config);
487 PyConfig_Clear(&config);
488
490
491 if (!has_python_executable) {
492 PySys_SetObject("executable", Py_None);
493 }
494 }
495
496# ifdef WITH_FLUID
497 /* Required to prevent assertion error, see:
498 * https://stackoverflow.com/questions/27844676 */
499 Py_DECREF(PyImport_ImportModule("threading"));
500# endif
501
502#else /* WITH_PYTHON_MODULE */
503 (void)argc;
504 (void)argv;
505
506 /* NOTE(ideasman42): unfortunately the `inittab` can only be used
507 * before Python has been initialized.
508 * When built as a Python module, Python will have been initialized
509 * and using the `inittab` isn't supported.
510 * So it's necessary to load all modules as soon as `bpy` is imported. */
511 // PyImport_ExtendInittab(bpy_internal_modules);
512
513#endif /* WITH_PYTHON_MODULE */
514
516
517#ifdef WITH_PYTHON_MODULE
518 {
519 /* Manually load all modules */
520 struct _inittab *inittab_item;
521 PyObject *sys_modules = PyImport_GetModuleDict();
522
523 for (inittab_item = bpy_internal_modules; inittab_item->name; inittab_item++) {
524 PyObject *mod = inittab_item->initfunc();
525 if (mod) {
526 PyDict_SetItemString(sys_modules, inittab_item->name, mod);
527 }
528 else {
529 PyErr_Print();
530 PyErr_Clear();
531 }
532 // Py_DECREF(mod); /* Ideally would decref, but in this case we never want to free. */
533 }
534 }
535#endif
536
537 /* Run first, initializes RNA types. */
538 BPY_rna_init();
539
540 /* Defines `bpy.*` and lets us import it. */
542
544
545#ifndef WITH_PYTHON_MODULE
546 /* Python module runs `atexit` when `bpy` is freed. */
547 BPY_atexit_register(); /* This can initialize any time. */
548
549 /* Free the lock acquired (implicitly) when Python is initialized. */
550 PyEval_ReleaseThread(PyGILState_GetThisThreadState());
551
552#endif
553
554#ifdef WITH_PYTHON_MODULE
555 /* Disable all add-ons at exit, not essential, it just avoids resource leaks, see #71362. */
556 const char *imports[] = {"atexit", "addon_utils", nullptr};
557 BPY_run_string_eval(C, imports, "atexit.register(addon_utils.disable_all)");
558#endif
559}
560
561void BPY_python_end(const bool do_python_exit)
562{
563#ifndef WITH_PYTHON_MODULE
564 BLI_assert_msg(Py_IsInitialized() != 0, "Python must be initialized");
565#endif
566
567 PyGILState_STATE gilstate;
568
569 /* Finalizing, no need to grab the state, except when we are a module. */
570 gilstate = PyGILState_Ensure();
571
572 /* Frees the Python-driver name-space & cached data. */
574
575 /* Clear Python values in the context so freeing the context after Python exits doesn't crash. */
577
578 /* Decrement user counts of all callback functions. */
580
581 /* Free other Python data. */
583
584 BPY_rna_exit();
585
586 /* Clear all Python data from structs. */
587
589
590 /* `bpy.app` modules that need cleanup. */
592
593#ifndef WITH_PYTHON_MODULE
594 /* Without this we get recursive calls to #WM_exit_ex. */
596
597 if (do_python_exit) {
598 Py_Finalize();
599 }
600 (void)gilstate;
601#else
602 PyGILState_Release(gilstate);
603 (void)do_python_exit;
604#endif
605
606#ifdef TIME_PY_RUN
607 /* Measure time since Python started. */
608 bpy_timer = BLI_time_now_seconds() - bpy_timer;
609
610 printf("*bpy stats* - ");
611 printf("tot exec: %d, ", bpy_timer_count);
612 printf("tot run: %.4fsec, ", bpy_timer_run_tot);
613 if (bpy_timer_count > 0) {
614 printf("average run: %.6fsec, ", (bpy_timer_run_tot / bpy_timer_count));
615 }
616
617 if (bpy_timer > 0.0) {
618 printf("tot usage %.4f%%", (bpy_timer_run_tot / bpy_timer) * 100.0);
619 }
620
621 printf("\n");
622#endif
623}
624
626{
627 BLI_assert_msg(Py_IsInitialized() != 0, "Python must be initialized");
628
629 /* Unrelated security stuff. */
631 G.autoexec_fail[0] = '\0';
632
636}
637
639{
640 BLI_assert(!Py_IsInitialized());
641 py_use_system_env = true;
642}
643
648
650{
651 fputs("\n# Python backtrace\n", fp);
652
653 /* Can happen in rare cases. */
654 if (!_PyThreadState_UncheckedGet()) {
655 return;
656 }
657 PyFrameObject *frame = PyEval_GetFrame();
658 if (frame == nullptr) {
659 return;
660 }
661 do {
662 PyCodeObject *code = PyFrame_GetCode(frame);
663 const int line = PyFrame_GetLineNumber(frame);
664 const char *filepath = PyUnicode_AsUTF8(code->co_filename);
665 const char *funcname = PyUnicode_AsUTF8(code->co_name);
666 fprintf(fp, " File \"%s\", line %d in %s\n", filepath, line, funcname);
667 } while ((frame = PyFrame_GetBack(frame)));
668}
669
670void BPY_DECREF(void *pyob_ptr)
671{
672 const PyGILState_STATE gilstate = PyGILState_Ensure();
673 Py_DECREF((PyObject *)pyob_ptr);
674 PyGILState_Release(gilstate);
675}
676
677void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr)
678{
679 const PyGILState_STATE gilstate = PyGILState_Ensure();
680 const bool do_invalidate = (Py_REFCNT((PyObject *)pyob_ptr) > 1);
681 Py_DECREF((PyObject *)pyob_ptr);
682 if (do_invalidate) {
683 pyrna_invalidate(static_cast<BPy_DummyPointerRNA *>(pyob_ptr));
684 }
685 PyGILState_Release(gilstate);
686}
687
689{
690 PyGILState_STATE gilstate;
691 Main *bmain = CTX_data_main(C);
692 Text *text;
693
694 /* Can happen on file load. */
695 if (bmain == nullptr) {
696 return;
697 }
698
699 /* Update pointers since this can run from a nested script on file load. */
700 if (py_call_level) {
702 }
703
704 bpy_context_set(C, &gilstate);
705
706 for (text = static_cast<Text *>(bmain->texts.first); text;
707 text = static_cast<Text *>(text->id.next))
708 {
709 if (text->flags & TXT_ISSCRIPT) {
710 if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) {
713 SNPRINTF(G.autoexec_fail, RPT_("Text '%s'"), text->id.name + 2);
714
715 printf("scripts disabled for \"%s\", skipping '%s'\n",
717 text->id.name + 2);
718 }
719 }
720 else {
721 BPY_run_text(C, text, nullptr, false);
722
723 /* Check if the script loaded a new file. */
724 if (bmain != CTX_data_main(C)) {
725 break;
726 }
727 }
728 }
729 }
730 bpy_context_clear(C, &gilstate);
731}
732
733int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *result)
734{
735 PyGILState_STATE gilstate;
736 const bool use_gil = !PyC_IsInterpreterActive();
737
738 PyObject *pyctx;
739 PyObject *item;
740 PointerRNA *ptr = nullptr;
741 bool done = false;
742
743 if (use_gil) {
744 gilstate = PyGILState_Ensure();
745 }
746
747 pyctx = (PyObject *)CTX_py_dict_get(C);
748 item = PyDict_GetItemString(pyctx, member);
749
750 if (item == nullptr) {
751 /* Pass. */
752 }
753 else if (item == Py_None) {
754 done = true;
755 }
756 else if (BPy_StructRNA_Check(item)) {
757 ptr = &(((BPy_StructRNA *)item)->ptr);
758
759 // result->ptr = ((BPy_StructRNA *)item)->ptr;
762 done = true;
763 }
764 else if (PySequence_Check(item)) {
765 PyObject *seq_fast = PySequence_Fast(item, "bpy_context_get sequence conversion");
766 if (seq_fast == nullptr) {
767 PyErr_Print();
768 PyErr_Clear();
769 }
770 else {
771 const int len = PySequence_Fast_GET_SIZE(seq_fast);
772 PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast);
773 int i;
774
775 for (i = 0; i < len; i++) {
776 PyObject *list_item = seq_fast_items[i];
777
778 if (BPy_StructRNA_Check(list_item)) {
779 ptr = &(((BPy_StructRNA *)list_item)->ptr);
780 CTX_data_list_add_ptr(result, ptr);
781 }
782 else {
784 1,
785 "'%s' list item not a valid type in sequence type '%s'",
786 member,
787 Py_TYPE(item)->tp_name);
788 }
789 }
790 Py_DECREF(seq_fast);
792 done = true;
793 }
794 }
795
796 if (done == false) {
797 if (item) {
798 CLOG_INFO(BPY_LOG_CONTEXT, 1, "'%s' not a valid type", member);
799 }
800 else {
801 CLOG_INFO(BPY_LOG_CONTEXT, 1, "'%s' not found", member);
802 }
803 }
804 else {
805 CLOG_INFO(BPY_LOG_CONTEXT, 2, "'%s' found", member);
806 }
807
808 if (use_gil) {
809 PyGILState_Release(gilstate);
810 }
811
812 return done;
813}
814
815#ifdef WITH_PYTHON_MODULE
816/* TODO: reloading the module isn't functional at the moment. */
817
818static void bpy_module_free(void *mod);
819
820/* Defined in 'creator.c' when building as a Python module. */
821extern int main_python_enter(int argc, const char **argv);
822extern void main_python_exit();
823
824static struct PyModuleDef bpy_proxy_def = {
825 /*m_base*/ PyModuleDef_HEAD_INIT,
826 /*m_name*/ "bpy",
827 /*m_doc*/ nullptr,
828 /*m_size*/ 0,
829 /*m_methods*/ nullptr,
830 /*m_slots*/ nullptr,
831 /*m_traverse*/ nullptr,
832 /*m_clear*/ nullptr,
833 /*m_free*/ bpy_module_free,
834};
835
836struct dealloc_obj {
837 PyObject_HEAD
838 /* Type-specific fields go here. */
839 PyObject *mod;
840};
841
842/* Call once `__file__` is set. */
843static void bpy_module_delay_init(PyObject *bpy_proxy)
844{
845 const int argc = 1;
846 const char *argv[2];
847
848 /* Updating the module dict below will lose the reference to `__file__`. */
849 PyObject *filepath_obj = PyModule_GetFilenameObject(bpy_proxy);
850
851 /* The file can be a relative path. */
852 const char *filepath_rel = PyUnicode_AsUTF8(filepath_obj);
853 char filepath_abs[1024];
854
855 STRNCPY(filepath_abs, filepath_rel);
856 BLI_path_abs_from_cwd(filepath_abs, sizeof(filepath_abs));
857 Py_DECREF(filepath_obj);
858
859 argv[0] = filepath_abs;
860 argv[1] = nullptr;
861
862 main_python_enter(argc, argv);
863
864 /* Initialized in #BPy_init_modules(). */
865 PyDict_Update(PyModule_GetDict(bpy_proxy), PyModule_GetDict(bpy_package_py));
866}
867
872static bool bpy_module_ensure_compatible_version()
873{
874 /* First check the Python version used matches the major version that Blender was built with.
875 * While this isn't essential, the error message in this case may be cryptic and misleading.
876 * NOTE: using `Py_LIMITED_API` would remove the need for this, in practice it's
877 * unlikely Blender will ever used the limited API though. */
878 const uint version_runtime = Py_Version;
879
880 uint version_compile_major = PY_VERSION_HEX >> 24;
881 uint version_compile_minor = ((PY_VERSION_HEX & 0x00ff0000) >> 16);
882 uint version_runtime_major = version_runtime >> 24;
883 uint version_runtime_minor = ((version_runtime & 0x00ff0000) >> 16);
884 if ((version_compile_major != version_runtime_major) ||
885 (version_compile_minor != version_runtime_minor))
886 {
887 PyErr_Format(PyExc_ImportError,
888 "The version of \"bpy\" was compiled with: "
889 "(%u.%u) is incompatible with: (%u.%u) used by the interpreter!",
890 version_compile_major,
891 version_compile_minor,
892 version_runtime_major,
893 version_runtime_minor);
894 return false;
895 }
896 return true;
897}
898
899static void dealloc_obj_dealloc(PyObject *self);
900
901static PyTypeObject dealloc_obj_Type;
902
903/* Use our own `dealloc` so we can free a property if we use one. */
904static void dealloc_obj_dealloc(PyObject *self)
905{
906 bpy_module_delay_init(((dealloc_obj *)self)->mod);
907
908 /* NOTE: for sub-classed `PyObject` objects
909 * we can't call #PyObject_DEL() directly or it will crash. */
910 dealloc_obj_Type.tp_free(self);
911}
912
913PyMODINIT_FUNC PyInit_bpy();
914
915PyMODINIT_FUNC PyInit_bpy()
916{
917 if (!bpy_module_ensure_compatible_version()) {
918 return nullptr; /* The error has been set. */
919 }
920
921 PyObject *bpy_proxy = PyModule_Create(&bpy_proxy_def);
922
923 /* Problem:
924 * 1) This initializing function is expected to have a private member defined - `md_def`
925 * but this is only set for CAPI defined modules (not Python packages)
926 * so we can't return `bpy_package_py` as is.
927 *
928 * 2) There is a `bpy` CAPI module for python to load which is basically all of blender,
929 * and there is `scripts/bpy/__init__.py`,
930 * we may end up having to rename this module so there is no naming conflict here eg:
931 * `from blender import bpy`
932 *
933 * 3) We don't know the file-path at this point, workaround by assigning a dummy value
934 * which calls back when its freed so the real loading can take place.
935 */
936
937 /* Assign an object which is freed after `__file__` is assigned. */
938 dealloc_obj *dob;
939
940 /* Assign dummy type. */
941 dealloc_obj_Type.tp_name = "dealloc_obj";
942 dealloc_obj_Type.tp_basicsize = sizeof(dealloc_obj);
943 dealloc_obj_Type.tp_dealloc = dealloc_obj_dealloc;
944 dealloc_obj_Type.tp_flags = Py_TPFLAGS_DEFAULT;
945
946 if (PyType_Ready(&dealloc_obj_Type) < 0) {
947 return nullptr;
948 }
949
950 dob = (dealloc_obj *)dealloc_obj_Type.tp_alloc(&dealloc_obj_Type, 0);
951 dob->mod = bpy_proxy; /* borrow */
952 PyModule_AddObject(bpy_proxy, "__file__", (PyObject *)dob); /* borrow */
953
954 return bpy_proxy;
955}
956
957static void bpy_module_free(void * /*mod*/)
958{
959 main_python_exit();
960}
961
962#endif
963
964bool BPY_string_is_keyword(const char *str)
965{
966 /* List is from: `", ".join(['"%s"' % kw for kw in __import__("keyword").kwlist])`. */
967 const char *kwlist[] = {
968 "False", "None", "True", "and", "as", "assert", "async", "await", "break",
969 "class", "continue", "def", "del", "elif", "else", "except", "finally", "for",
970 "from", "global", "if", "import", "in", "is", "lambda", "nonlocal", "not",
971 "or", "pass", "raise", "return", "try", "while", "with", "yield", nullptr,
972 };
973
974 for (int i = 0; kwlist[i]; i++) {
975 if (STREQ(str, kwlist[i])) {
976 return true;
977 }
978 }
979
980 return false;
981}
982
983/* -------------------------------------------------------------------- */
991{
992 return (ch < 255 && text_check_identifier(char(ch))) || Py_UNICODE_ISALNUM(ch);
993}
994
996{
997 return (ch < 255 && text_check_identifier_nodigit(char(ch))) || Py_UNICODE_ISALPHA(ch);
998}
999
PyObject * AUD_initPython(void)
const char * BKE_appdir_program_path() ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition appdir.cc:940
bool BKE_appdir_program_python_search(char *program_filepath, size_t program_filepath_maxncpy, int version_major, int version_minor) ATTR_NONNULL(1)
Definition appdir.cc:954
@ BLENDER_SYSTEM_PYTHON
std::optional< std::string > BKE_appdir_folder_id(int folder_id, const char *subfolder) ATTR_WARN_UNUSED_RESULT
Definition appdir.cc:704
void CTX_wm_operator_poll_msg_clear(bContext *C)
Main * CTX_data_main(const bContext *C)
@ CTX_DATA_TYPE_POINTER
@ CTX_DATA_TYPE_COLLECTION
void CTX_data_list_add_ptr(bContextDataResult *result, const PointerRNA *ptr)
void CTX_data_pointer_set_ptr(bContextDataResult *result, const PointerRNA *ptr)
void * CTX_py_dict_get(const bContext *C)
void CTX_data_type_set(bContextDataResult *result, short type)
@ G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET
@ G_FLAG_SCRIPT_AUTOEXEC_FAIL
@ G_FLAG_SCRIPT_AUTOEXEC
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
Definition main.cc:832
bool text_check_identifier_nodigit(char ch)
Definition text.cc:2337
bool text_check_identifier(char ch)
Definition text.cc:2314
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
File and directory operations.
#define FILE_MAX
void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1)
#define BLI_path_join(...)
const char * BLI_getenv(const char *env) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
bool BLI_path_abs_from_cwd(char *path, size_t path_maxncpy) ATTR_NONNULL(1)
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
unsigned int uint
int BLI_thread_is_main(void)
Definition threads.cc:179
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.c:65
#define UNLIKELY(x)
#define STREQ(a, b)
#define RPT_(msgid)
void BPY_driver_reset()
void BPY_driver_exit()
void BPY_app_handlers_reset(bool do_all)
struct CLG_LogRef * BPY_LOG_RNA
struct CLG_LogRef * BPY_LOG_CONTEXT
bool bool BPY_run_text(bContext *C, Text *text, ReportList *reports, bool do_jump) ATTR_NONNULL(1
bool BPY_run_string_eval(bContext *C, const char *imports[], const char *expr)
void * CCL_python_module_init(void)
Definition python.cpp:1005
#define CLG_LOGREF_DECLARE_GLOBAL(var, id)
Definition CLG_log.h:145
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
@ TXT_ISSCRIPT
Read Guarded memory(de)allocation.
PyObject * BPyInit_bgl()
Definition bgl.cc:2658
PyMODINIT_FUNC BPyInit_bl_math()
PyObject * BPyInit_blf()
PyObject * BPyInit_bmesh()
PyObject * BPyInit_bmesh_geometry()
PyObject * BPyInit_bmesh_types()
PyObject * BPyInit_bmesh_utils()
PyObject * bpy_package_py
Definition bpy.cc:62
void BPy_init_modules(bContext *C)
Definition bpy.cc:711
void BPY_atexit_unregister()
void BPY_atexit_register()
struct CLG_LogRef * BPY_LOG_INTERFACE
void BPY_app_translations_end()
PyObject * self
int text_check_identifier_nodigit_unicode(const uint ch)
bool BPY_string_is_keyword(const char *str)
void BPY_python_use_system_env()
void BPY_context_dict_clear_members_array(void **dict_p, void *dict_orig, const char *context_members[], uint context_members_len)
int text_check_identifier_unicode(const uint ch)
int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *result)
void BPY_modules_update()
bContext * BPY_context_get()
void bpy_context_set(bContext *C, PyGILState_STATE *gilstate)
void BPY_context_set(bContext *C)
static void pystatus_exit_on_error(const PyStatus &status)
void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr)
void BPY_python_backtrace(FILE *fp)
static int py_call_level
static void bpy_context_end(bContext *C)
void BPY_python_reset(bContext *C)
static bool py_use_system_env
void BPY_context_update(bContext *C)
void BPY_python_end(const bool do_python_exit)
static _inittab bpy_internal_modules[]
bool BPY_python_use_system_env_get()
void BPY_text_free_code(Text *text)
void bpy_context_clear(bContext *, const PyGILState_STATE *gilstate)
void BPY_modules_load_user(bContext *C)
void BPY_python_start(bContext *C, int argc, const char **argv)
void BPY_DECREF(void *pyob_ptr)
void bpy_intern_string_exit()
void bpy_intern_string_init()
PyObject * BPyInit__bpy_path()
Definition bpy_path.cc:37
void BPY_rna_props_clear_all()
void pyrna_invalidate(BPy_DummyPointerRNA *self)
Definition bpy_rna.cc:147
PyObject * BPY_rna_module()
Definition bpy_rna.cc:7904
void BPY_rna_init()
Definition bpy_rna.cc:7828
void pyrna_free_types()
Definition bpy_rna.cc:9099
void BPY_rna_exit()
Definition bpy_rna.cc:7881
PyObject * BPY_rna_types()
Definition bpy_rna.cc:8042
void pyrna_alloc_types()
Definition bpy_rna.cc:9064
void BPY_update_rna_module()
Definition bpy_rna.cc:7916
BPy_StructRNA * bpy_context_module
Definition bpy_rna.cc:91
#define BPy_StructRNA_Check(v)
Definition bpy_rna.hh:69
#define printf
int len
#define str(s)
PyObject * BPyInit_gpu()
Definition gpu_py_api.cc:50
PyObject * BPyInit_idprop()
PyObject * BPyInit_imbuf()
PyObject * Manta_initPython(void)
PyMODINIT_FUNC PyInit_mathutils()
Definition mathutils.cc:765
PyMODINIT_FUNC PyInit_mathutils_geometry()
PyMODINIT_FUNC PyInit_mathutils_kdtree()
PyMODINIT_FUNC PyInit_mathutils_noise()
#define G(x, y, z)
bool PyC_IsInterpreterActive()
PyObject * BPyInit_hydra()
Definition python.cc:211
PyObject_HEAD PointerRNA ptr
Definition bpy_rna.hh:124
void * first
ListBase texts
Definition BKE_main.hh:227
void * data
Definition RNA_types.hh:42
ccl_device_inline int mod(int x, int m)
Definition util/math.h:520
PointerRNA * ptr
Definition wm_files.cc:4126