1 /* SPDX-FileCopyrightText: 2023 Blender Authors
3 * SPDX-License-Identifier: GPL-2.0-or-later */
6 * \ingroup pythonintern
8 * This file deals with embedding the python interpreter within blender,
9 * starting and stopping python and exposing blender/python modules so they can
10 * be accesses from scripts.
14 #include <frameobject.h>
16 #ifdef WITH_PYTHON_MODULE
17 # include "pylifecycle.h" /* For `Py_Version`. */
22 #include "BLI_path_utils.hh"
23 #include "BLI_string.h"
24 #include "BLI_threads.h"
25 #include "BLI_utildefines.h"
27 #include "BLT_translation.hh"
29 #include "RNA_types.hh"
32 #include "bpy_capi_utils.hh"
33 #include "bpy_intern_string.hh"
34 #include "bpy_path.hh"
35 #include "bpy_props.hh"
38 #include "bpy_app_translations.hh"
40 #include "DNA_text_types.h"
42 #include "BKE_appdir.hh"
43 #include "BKE_context.hh"
44 #include "BKE_global.hh" /* Only for script checking. */
45 #include "BKE_main.hh"
52 #include "BPY_extern.hh"
53 #include "BPY_extern_python.hh"
54 #include "BPY_extern_run.hh"
56 #include "../generic/py_capi_utils.hh"
58 /* `inittab` initialization functions. */
59 #include "../bmesh/bmesh_py_api.hh"
60 #include "../generic/bgl.hh"
61 #include "../generic/bl_math_py_api.hh"
62 #include "../generic/blf_py_api.hh"
63 #include "../generic/idprop_py_api.hh"
64 #include "../generic/imbuf_py_api.hh"
65 #include "../gpu/gpu_py_api.hh"
66 #include "../mathutils/mathutils.hh"
68 /* Logging types to use anywhere in the Python modules. */
70 CLG_LOGREF_DECLARE_GLOBAL(BPY_LOG_CONTEXT
, "bpy.context");
71 CLG_LOGREF_DECLARE_GLOBAL(BPY_LOG_INTERFACE
, "bpy.interface");
72 CLG_LOGREF_DECLARE_GLOBAL(BPY_LOG_RNA
, "bpy.rna");
74 /* For internal use, when starting and ending Python scripts. */
76 /* In case a Python script triggers another Python call,
77 * stop #bpy_context_clear from invalidating. */
78 static int py_call_level
= 0;
80 /* Set by command line arguments before Python starts. */
81 static bool py_use_system_env
= false;
83 // #define TIME_PY_RUN /* Simple python tests. prints on exit. */
86 # include "BLI_time.h"
87 static int bpy_timer_count
= 0;
88 /** Time since python starts. */
89 static double bpy_timer
;
90 /** Time for each Python script run. */
91 static double bpy_timer_run
;
92 /** Accumulate Python runs. */
93 static double bpy_timer_run_tot
;
96 void BPY_context_update(bContext
*C
)
98 /* Don't do this from a non-main (e.g. render) thread, it can cause a race
99 * condition on `C->data.recursion`. Ideal solution would be to disable
100 * context entirely from non-main threads, but that's more complicated. */
101 if (!BLI_thread_is_main()) {
107 /* Can give really bad results if this isn't here. */
108 BPY_modules_update();
111 void bpy_context_set(bContext
*C
, PyGILState_STATE
*gilstate
)
116 *gilstate
= PyGILState_Ensure();
119 if (py_call_level
== 1) {
120 BPY_context_update(C
);
123 if (bpy_timer_count
== 0) {
124 /* Record time from the beginning. */
125 bpy_timer
= BLI_time_now_seconds();
126 bpy_timer_run
= bpy_timer_run_tot
= 0.0;
128 bpy_timer_run
= BLI_time_now_seconds();
135 void bpy_context_clear(bContext
* /*C*/, const PyGILState_STATE
*gilstate
)
140 PyGILState_Release(*gilstate
);
143 if (py_call_level
< 0) {
144 fprintf(stderr
, "ERROR: Python context internal state bug. this should not happen!\n");
146 else if (py_call_level
== 0) {
147 /* NOTE: Unfortunately calling classes currently won't store the context.
148 * Can't set nullptr because of this - but this is very flaky still. */
150 BPY_context_set(nullptr);
154 bpy_timer_run_tot
+= BLI_time_now_seconds() - bpy_timer_run
;
160 static void bpy_context_end(bContext
*C
)
162 if (UNLIKELY(C
== nullptr)) {
165 CTX_wm_operator_poll_msg_clear(C
);
168 void BPY_context_dict_clear_members_array(void **dict_p
,
170 const char *context_members
[],
171 uint context_members_len
)
173 PyGILState_STATE gilstate
;
174 const bool use_gil
= !PyC_IsInterpreterActive();
177 gilstate
= PyGILState_Ensure();
181 if (*dict_p
== dict_orig
) {
182 *dict_p
= PyDict_Copy(static_cast<PyObject
*>(dict_orig
));
185 PyObject
*dict
= static_cast<PyObject
*>(*dict_p
);
186 BLI_assert(PyDict_Check(dict
));
188 /* Use #PyDict_Pop instead of #PyDict_DelItemString to avoid setting the exception,
189 * while supported it's good to avoid for low level functions like this that run often. */
190 for (uint i
= 0; i
< context_members_len
; i
++) {
191 PyObject
*key
= PyUnicode_FromString(context_members
[i
]);
192 PyObject
*item
= _PyDict_Pop(dict
, key
, Py_None
);
198 PyGILState_Release(gilstate
);
202 void BPY_text_free_code(Text
*text
)
204 if (text
->compiled
) {
205 PyGILState_STATE gilstate
;
206 const bool use_gil
= !PyC_IsInterpreterActive();
209 gilstate
= PyGILState_Ensure();
212 Py_DECREF((PyObject
*)text
->compiled
);
213 text
->compiled
= nullptr;
216 PyGILState_Release(gilstate
);
221 void BPY_modules_update()
223 /* Correct but slow, this runs all the time operator poll, panel draw etc
224 * (100's of time a second). */
226 PyObject
*mod
= PyImport_ImportModuleLevel("bpy", nullptr, nullptr, nullptr, 0);
227 PyModule_AddObject(mod
, "data", BPY_rna_module());
228 PyModule_AddObject(mod
, "types", BPY_rna_types()); /* This does not need updating. */
231 /* Refreshes the main struct. */
232 BPY_update_rna_module();
235 bContext
*BPY_context_get()
237 return static_cast<bContext
*>(bpy_context_module
->ptr
->data
);
240 void BPY_context_set(bContext
*C
)
242 bpy_context_module
->ptr
->data
= (void *)C
;
246 /* Defined in `manta` module. */
247 extern "C" PyObject
*Manta_initPython();
250 #ifdef WITH_AUDASPACE_PY
251 /* Defined in `AUD_C-API.cpp`. */
252 extern "C" PyObject
*AUD_initPython();
256 /* Defined in `cycles` module. */
257 static PyObject
*CCL_initPython()
259 return (PyObject
*)CCL_python_module_init();
264 /* Defined in `render_hydra` module. */
265 PyObject
*BPyInit_hydra();
268 static _inittab bpy_internal_modules
[] = {
269 {"mathutils", PyInit_mathutils
},
271 {"mathutils.geometry", PyInit_mathutils_geometry
},
272 {"mathutils.noise", PyInit_mathutils_noise
},
273 {"mathutils.kdtree", PyInit_mathutils_kdtree
},
275 {"_bpy_path", BPyInit__bpy_path
},
276 {"bgl", BPyInit_bgl
},
277 {"blf", BPyInit_blf
},
278 {"bl_math", BPyInit_bl_math
},
279 {"imbuf", BPyInit_imbuf
},
280 {"bmesh", BPyInit_bmesh
},
282 {"bmesh.types", BPyInit_bmesh_types
},
283 {"bmesh.utils", BPyInit_bmesh_utils
},
284 {"bmesh.utils", BPyInit_bmesh_geometry
},
287 {"manta", Manta_initPython
},
289 #ifdef WITH_AUDASPACE_PY
290 {"aud", AUD_initPython
},
293 {"_cycles", CCL_initPython
},
295 {"gpu", BPyInit_gpu
},
296 {"idprop", BPyInit_idprop
},
298 {"_bpy_hydra", BPyInit_hydra
},
303 #ifndef WITH_PYTHON_MODULE
305 * Convenience function for #BPY_python_start.
307 * These should happen so rarely that having comprehensive errors isn't needed.
308 * For example if `sys.argv` fails to allocate memory.
310 * Show an error just to avoid silent failure in the unlikely event something goes wrong,
311 * in this case a developer will need to track down the root cause.
313 static void pystatus_exit_on_error(const PyStatus
&status
)
315 if (UNLIKELY(PyStatus_Exception(status
))) {
316 fputs("Internal error initializing Python!\n", stderr
);
317 /* This calls `exit`. */
318 Py_ExitStatusException(status
);
323 void BPY_python_start(bContext
*C
, int argc
, const char **argv
)
325 #ifndef WITH_PYTHON_MODULE
326 BLI_assert_msg(Py_IsInitialized() == 0, "Python has already been initialized");
328 /* #PyPreConfig (early-configuration). */
330 PyPreConfig preconfig
;
333 /* To narrow down reports where the systems Python is inexplicably used, see: #98131. */
337 "Initializing %s support for the systems Python environment such as 'PYTHONPATH' and "
338 "the user-site directory.",
339 py_use_system_env
? "*with*" : "*without*");
341 if (py_use_system_env
) {
342 PyPreConfig_InitPythonConfig(&preconfig
);
345 /* Only use the systems environment variables and site when explicitly requested.
346 * Since an incorrect 'PYTHONPATH' causes difficult to debug errors, see: #72807.
347 * An alternative to setting `preconfig.use_environment = 0` */
348 PyPreConfig_InitIsolatedConfig(&preconfig
);
351 /* Force `utf-8` on all platforms, since this is what's used for Blender's internal strings,
352 * providing consistent encoding behavior across all Blender installations.
354 * This also uses the `surrogateescape` error handler ensures any unexpected bytes are escaped
355 * instead of raising an error.
357 * Without this `sys.getfilesystemencoding()` and `sys.stdout` for example may be set to ASCII
358 * or some other encoding - where printing some `utf-8` values will raise an error.
360 * This can cause scripts to fail entirely on some systems.
362 * This assignment is the equivalent of enabling the `PYTHONUTF8` environment variable.
363 * See `PEP-540` for details on exactly what this changes. */
364 preconfig
.utf8_mode
= true;
366 /* Note that there is no reason to call #Py_PreInitializeFromBytesArgs here
367 * as this is only used so that command line arguments can be handled by Python itself,
368 * not for setting `sys.argv` (handled below). */
369 status
= Py_PreInitialize(&preconfig
);
370 pystatus_exit_on_error(status
);
373 /* Must run before python initializes, but after #PyPreConfig. */
374 PyImport_ExtendInittab(bpy_internal_modules
);
376 /* #PyConfig (initialize Python). */
380 bool has_python_executable
= false;
382 if (py_use_system_env
) {
383 PyConfig_InitPythonConfig(&config
);
385 BLI_assert(config
.install_signal_handlers
);
388 PyConfig_InitIsolatedConfig(&config
);
389 /* Python's isolated config disables it's own signal overrides.
390 * While it makes sense not to interfering with other components of the process,
391 * the signal handlers are needed for Python's own error handling to work properly.
392 * Without this a `SIGPIPE` signal will crash Blender, see: #129657. */
393 config
.install_signal_handlers
= 1;
396 /* Suppress error messages when calculating the module search path.
397 * While harmless, it's noisy. */
398 config
.pathconfig_warnings
= 0;
400 /* Allow the user site directory because this is used
401 * when PIP installing packages from Blender, see: #104000.
403 * NOTE(@ideasman42): While an argument can be made for isolating Blender's Python
404 * from the users home directory entirely, an alternative directory should be used in that
405 * case - so PIP can be used to install packages. Otherwise PIP will install packages to a
406 * directory which us not in the users `sys.path`, see `site.USER_BASE` for details. */
407 // config.user_site_directory = py_use_system_env;
409 /* While `sys.argv` is set, we don't want Python to interpret it. */
410 config
.parse_argv
= 0;
411 status
= PyConfig_SetBytesArgv(&config
, argc
, (char *const *)argv
);
412 pystatus_exit_on_error(status
);
414 /* Needed for Python's initialization for portable Python installations.
415 * We could use #Py_SetPath, but this overrides Python's internal logic
416 * for calculating its own module search paths.
418 * `sys.executable` is overwritten after initialization to the Python binary. */
420 const char *program_path
= BKE_appdir_program_path();
421 status
= PyConfig_SetBytesString(&config
, &config
.program_name
, program_path
);
422 pystatus_exit_on_error(status
);
425 /* Setting the program name is important so the 'multiprocessing' module
426 * can launch new Python instances. */
428 char program_path
[FILE_MAX
];
429 if (BKE_appdir_program_python_search(
430 program_path
, sizeof(program_path
), PY_MAJOR_VERSION
, PY_MINOR_VERSION
))
432 status
= PyConfig_SetBytesString(&config
, &config
.executable
, program_path
);
433 pystatus_exit_on_error(status
);
434 has_python_executable
= true;
437 /* Set to `sys.executable = None` below (we can't do before Python is initialized). */
439 "Unable to find the Python binary, "
440 "the multiprocessing module may not be functional!\n");
444 /* Allow to use our own included Python. `py_path_bundle` may be nullptr. */
446 const std::optional
<std::string
> py_path_bundle
= BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON
,
448 if (py_path_bundle
.has_value()) {
451 /* Mac-OS allows file/directory names to contain `:` character
452 * (represented as `/` in the Finder) but current Python lib (as of release 3.1.1)
453 * doesn't handle these correctly. */
454 if (strchr(py_path_bundle
->c_str(), ':')) {
456 "Warning! Blender application is located in a path containing ':' or '/' chars\n"
457 "This may make Python import function fail\n");
459 # endif /* __APPLE__ */
461 status
= PyConfig_SetBytesString(&config
, &config
.home
, py_path_bundle
->c_str());
462 pystatus_exit_on_error(status
);
464 # ifdef PYTHON_SSL_CERT_FILE
465 /* Point to the portable SSL certificate to support HTTPS access, see: #102300. */
466 const char *ssl_cert_file_env
= "SSL_CERT_FILE";
467 if (BLI_getenv(ssl_cert_file_env
) == nullptr) {
468 const char *ssl_cert_file_suffix
= PYTHON_SSL_CERT_FILE
;
469 char ssl_cert_file
[FILE_MAX
];
471 ssl_cert_file
, sizeof(ssl_cert_file
), py_path_bundle
->c_str(), ssl_cert_file_suffix
);
472 BLI_setenv(ssl_cert_file_env
, ssl_cert_file
);
474 # endif /* PYTHON_SSL_CERT_FILE */
477 /* Common enough to use the system Python on Linux/Unix, warn on other systems. */
478 # if defined(__APPLE__) || defined(_WIN32)
480 "Bundled Python not found and is expected on this platform "
481 "(the 'install' target may have not been built)\n");
486 /* Initialize Python (also acquires lock). */
487 status
= Py_InitializeFromConfig(&config
);
488 PyConfig_Clear(&config
);
490 pystatus_exit_on_error(status
);
492 if (!has_python_executable
) {
493 PySys_SetObject("executable", Py_None
);
498 /* Required to prevent assertion error, see:
499 * https://stackoverflow.com/questions/27844676 */
500 Py_DECREF(PyImport_ImportModule("threading"));
503 #else /* WITH_PYTHON_MODULE */
507 /* NOTE(ideasman42): unfortunately the `inittab` can only be used
508 * before Python has been initialized.
509 * When built as a Python module, Python will have been initialized
510 * and using the `inittab` isn't supported.
511 * So it's necessary to load all modules as soon as `bpy` is imported. */
512 // PyImport_ExtendInittab(bpy_internal_modules);
514 #endif /* WITH_PYTHON_MODULE */
516 bpy_intern_string_init();
518 #ifdef WITH_PYTHON_MODULE
520 /* Manually load all modules */
521 struct _inittab
*inittab_item
;
522 PyObject
*sys_modules
= PyImport_GetModuleDict();
524 for (inittab_item
= bpy_internal_modules
; inittab_item
->name
; inittab_item
++) {
525 PyObject
*mod
= inittab_item
->initfunc();
527 PyDict_SetItemString(sys_modules
, inittab_item
->name
, mod
);
533 // Py_DECREF(mod); /* Ideally would decref, but in this case we never want to free. */
538 /* Run first, initializes RNA types. */
541 /* Defines `bpy.*` and lets us import it. */
546 #ifndef WITH_PYTHON_MODULE
547 /* Python module runs `atexit` when `bpy` is freed. */
548 BPY_atexit_register(); /* This can initialize any time. */
550 /* Free the lock acquired (implicitly) when Python is initialized. */
551 PyEval_ReleaseThread(PyGILState_GetThisThreadState());
555 #ifdef WITH_PYTHON_MODULE
556 /* Disable all add-ons at exit, not essential, it just avoids resource leaks, see #71362. */
557 const char *imports
[] = {"atexit", "addon_utils", nullptr};
558 BPY_run_string_eval(C
, imports
, "atexit.register(addon_utils.disable_all)");
562 void BPY_python_end(const bool do_python_exit
)
564 #ifndef WITH_PYTHON_MODULE
565 BLI_assert_msg(Py_IsInitialized() != 0, "Python must be initialized");
568 PyGILState_STATE gilstate
;
570 /* Finalizing, no need to grab the state, except when we are a module. */
571 gilstate
= PyGILState_Ensure();
573 /* Frees the Python-driver name-space & cached data. */
576 /* Clear Python values in the context so freeing the context after Python exits doesn't crash. */
577 bpy_context_end(BPY_context_get());
579 /* Decrement user counts of all callback functions. */
580 BPY_rna_props_clear_all();
582 /* Free other Python data. */
587 /* Clear all Python data from structs. */
589 bpy_intern_string_exit();
591 /* `bpy.app` modules that need cleanup. */
592 BPY_app_translations_end();
594 #ifndef WITH_PYTHON_MODULE
595 /* Without this we get recursive calls to #WM_exit_ex. */
596 BPY_atexit_unregister();
598 if (do_python_exit
) {
603 PyGILState_Release(gilstate
);
604 (void)do_python_exit
;
608 /* Measure time since Python started. */
609 bpy_timer
= BLI_time_now_seconds() - bpy_timer
;
611 printf("*bpy stats* - ");
612 printf("tot exec: %d, ", bpy_timer_count
);
613 printf("tot run: %.4fsec, ", bpy_timer_run_tot
);
614 if (bpy_timer_count
> 0) {
615 printf("average run: %.6fsec, ", (bpy_timer_run_tot
/ bpy_timer_count
));
618 if (bpy_timer
> 0.0) {
619 printf("tot usage %.4f%%", (bpy_timer_run_tot
/ bpy_timer
) * 100.0);
626 void BPY_python_reset(bContext
*C
)
628 BLI_assert_msg(Py_IsInitialized() != 0, "Python must be initialized");
630 /* Unrelated security stuff. */
631 G
.f
&= ~(G_FLAG_SCRIPT_AUTOEXEC_FAIL
| G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET
);
632 G
.autoexec_fail
[0] = '\0';
635 BPY_app_handlers_reset(false);
636 BPY_modules_load_user(C
);
639 void BPY_python_use_system_env()
641 BLI_assert(!Py_IsInitialized());
642 py_use_system_env
= true;
645 bool BPY_python_use_system_env_get()
647 return py_use_system_env
;
650 void BPY_python_backtrace(FILE *fp
)
652 fputs("\n# Python backtrace\n", fp
);
654 /* Can happen in rare cases. */
655 if (!_PyThreadState_UncheckedGet()) {
658 PyFrameObject
*frame
= PyEval_GetFrame();
659 if (frame
== nullptr) {
663 PyCodeObject
*code
= PyFrame_GetCode(frame
);
664 const int line
= PyFrame_GetLineNumber(frame
);
665 const char *filepath
= PyUnicode_AsUTF8(code
->co_filename
);
666 const char *funcname
= PyUnicode_AsUTF8(code
->co_name
);
667 fprintf(fp
, " File \"%s\", line %d in %s\n", filepath
, line
, funcname
);
668 } while ((frame
= PyFrame_GetBack(frame
)));
671 void BPY_DECREF(void *pyob_ptr
)
673 const PyGILState_STATE gilstate
= PyGILState_Ensure();
674 Py_DECREF((PyObject
*)pyob_ptr
);
675 PyGILState_Release(gilstate
);
678 void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr
)
680 const PyGILState_STATE gilstate
= PyGILState_Ensure();
681 const bool do_invalidate
= (Py_REFCNT((PyObject
*)pyob_ptr
) > 1);
682 Py_DECREF((PyObject
*)pyob_ptr
);
684 pyrna_invalidate(static_cast<BPy_DummyPointerRNA
*>(pyob_ptr
));
686 PyGILState_Release(gilstate
);
689 void BPY_modules_load_user(bContext
*C
)
691 PyGILState_STATE gilstate
;
692 Main
*bmain
= CTX_data_main(C
);
695 /* Can happen on file load. */
696 if (bmain
== nullptr) {
700 /* Update pointers since this can run from a nested script on file load. */
702 BPY_context_update(C
);
705 bpy_context_set(C
, &gilstate
);
707 for (text
= static_cast<Text
*>(bmain
->texts
.first
); text
;
708 text
= static_cast<Text
*>(text
->id
.next
))
710 if (text
->flags
& TXT_ISSCRIPT
) {
711 if (!(G
.f
& G_FLAG_SCRIPT_AUTOEXEC
)) {
712 if (!(G
.f
& G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET
)) {
713 G
.f
|= G_FLAG_SCRIPT_AUTOEXEC_FAIL
;
714 SNPRINTF(G
.autoexec_fail
, RPT_("Text '%s'"), text
->id
.name
+ 2);
716 printf("scripts disabled for \"%s\", skipping '%s'\n",
717 BKE_main_blendfile_path(bmain
),
722 BPY_run_text(C
, text
, nullptr, false);
724 /* Check if the script loaded a new file. */
725 if (bmain
!= CTX_data_main(C
)) {
731 bpy_context_clear(C
, &gilstate
);
734 int BPY_context_member_get(bContext
*C
, const char *member
, bContextDataResult
*result
)
736 PyGILState_STATE gilstate
;
737 const bool use_gil
= !PyC_IsInterpreterActive();
741 PointerRNA
*ptr
= nullptr;
745 gilstate
= PyGILState_Ensure();
748 pyctx
= (PyObject
*)CTX_py_dict_get(C
);
749 item
= PyDict_GetItemString(pyctx
, member
);
751 if (item
== nullptr) {
754 else if (item
== Py_None
) {
757 else if (BPy_StructRNA_Check(item
)) {
758 ptr
= &reinterpret_cast<BPy_StructRNA
*>(item
)->ptr
.value();
760 // result->ptr = ((BPy_StructRNA *)item)->ptr;
761 CTX_data_pointer_set_ptr(result
, ptr
);
762 CTX_data_type_set(result
, CTX_DATA_TYPE_POINTER
);
765 else if (PySequence_Check(item
)) {
766 PyObject
*seq_fast
= PySequence_Fast(item
, "bpy_context_get sequence conversion");
767 if (seq_fast
== nullptr) {
772 const int len
= PySequence_Fast_GET_SIZE(seq_fast
);
773 PyObject
**seq_fast_items
= PySequence_Fast_ITEMS(seq_fast
);
776 for (i
= 0; i
< len
; i
++) {
777 PyObject
*list_item
= seq_fast_items
[i
];
779 if (BPy_StructRNA_Check(list_item
)) {
780 ptr
= &reinterpret_cast<BPy_StructRNA
*>(list_item
)->ptr
.value();
781 CTX_data_list_add_ptr(result
, ptr
);
784 CLOG_INFO(BPY_LOG_CONTEXT
,
786 "'%s' list item not a valid type in sequence type '%s'",
788 Py_TYPE(item
)->tp_name
);
792 CTX_data_type_set(result
, CTX_DATA_TYPE_COLLECTION
);
799 CLOG_INFO(BPY_LOG_CONTEXT
, 1, "'%s' not a valid type", member
);
802 CLOG_INFO(BPY_LOG_CONTEXT
, 1, "'%s' not found", member
);
806 CLOG_INFO(BPY_LOG_CONTEXT
, 2, "'%s' found", member
);
810 PyGILState_Release(gilstate
);
816 #ifdef WITH_PYTHON_MODULE
817 /* TODO: reloading the module isn't functional at the moment. */
819 static void bpy_module_free(void *mod
);
821 /* Defined in 'creator.c' when building as a Python module. */
822 extern int main_python_enter(int argc
, const char **argv
);
823 extern void main_python_exit();
825 static struct PyModuleDef bpy_proxy_def
= {
826 /*m_base*/ PyModuleDef_HEAD_INIT
,
830 /*m_methods*/ nullptr,
832 /*m_traverse*/ nullptr,
834 /*m_free*/ bpy_module_free
,
839 /* Type-specific fields go here. */
843 /* Call once `__file__` is set. */
844 static void bpy_module_delay_init(PyObject
*bpy_proxy
)
849 /* Updating the module dict below will lose the reference to `__file__`. */
850 PyObject
*filepath_obj
= PyModule_GetFilenameObject(bpy_proxy
);
852 /* The file can be a relative path. */
853 const char *filepath_rel
= PyUnicode_AsUTF8(filepath_obj
);
854 char filepath_abs
[1024];
856 STRNCPY(filepath_abs
, filepath_rel
);
857 BLI_path_abs_from_cwd(filepath_abs
, sizeof(filepath_abs
));
858 Py_DECREF(filepath_obj
);
860 argv
[0] = filepath_abs
;
863 main_python_enter(argc
, argv
);
865 /* Initialized in #BPy_init_modules(). */
866 PyDict_Update(PyModule_GetDict(bpy_proxy
), PyModule_GetDict(bpy_package_py
));
870 * Raise an error and return false if the Python version used to compile Blender
871 * isn't compatible with the interpreter loading the `bpy` module.
873 static bool bpy_module_ensure_compatible_version()
875 /* First check the Python version used matches the major version that Blender was built with.
876 * While this isn't essential, the error message in this case may be cryptic and misleading.
877 * NOTE: using `Py_LIMITED_API` would remove the need for this, in practice it's
878 * unlikely Blender will ever used the limited API though. */
879 const uint version_runtime
= Py_Version
;
881 uint version_compile_major
= PY_VERSION_HEX
>> 24;
882 uint version_compile_minor
= ((PY_VERSION_HEX
& 0x00ff0000) >> 16);
883 uint version_runtime_major
= version_runtime
>> 24;
884 uint version_runtime_minor
= ((version_runtime
& 0x00ff0000) >> 16);
885 if ((version_compile_major
!= version_runtime_major
) ||
886 (version_compile_minor
!= version_runtime_minor
))
888 PyErr_Format(PyExc_ImportError
,
889 "The version of \"bpy\" was compiled with: "
890 "(%u.%u) is incompatible with: (%u.%u) used by the interpreter!",
891 version_compile_major
,
892 version_compile_minor
,
893 version_runtime_major
,
894 version_runtime_minor
);
900 static void dealloc_obj_dealloc(PyObject
*self
);
902 static PyTypeObject dealloc_obj_Type
;
904 /* Use our own `dealloc` so we can free a property if we use one. */
905 static void dealloc_obj_dealloc(PyObject
*self
)
907 bpy_module_delay_init(((dealloc_obj
*)self
)->mod
);
909 /* NOTE: for sub-classed `PyObject` objects
910 * we can't call #PyObject_DEL() directly or it will crash. */
911 dealloc_obj_Type
.tp_free(self
);
914 PyMODINIT_FUNC
PyInit_bpy();
916 PyMODINIT_FUNC
PyInit_bpy()
918 if (!bpy_module_ensure_compatible_version()) {
919 return nullptr; /* The error has been set. */
922 PyObject
*bpy_proxy
= PyModule_Create(&bpy_proxy_def
);
925 * 1) This initializing function is expected to have a private member defined - `md_def`
926 * but this is only set for CAPI defined modules (not Python packages)
927 * so we can't return `bpy_package_py` as is.
929 * 2) There is a `bpy` CAPI module for python to load which is basically all of blender,
930 * and there is `scripts/bpy/__init__.py`,
931 * we may end up having to rename this module so there is no naming conflict here eg:
932 * `from blender import bpy`
934 * 3) We don't know the file-path at this point, workaround by assigning a dummy value
935 * which calls back when its freed so the real loading can take place.
938 /* Assign an object which is freed after `__file__` is assigned. */
941 /* Assign dummy type. */
942 dealloc_obj_Type
.tp_name
= "dealloc_obj";
943 dealloc_obj_Type
.tp_basicsize
= sizeof(dealloc_obj
);
944 dealloc_obj_Type
.tp_dealloc
= dealloc_obj_dealloc
;
945 dealloc_obj_Type
.tp_flags
= Py_TPFLAGS_DEFAULT
;
947 if (PyType_Ready(&dealloc_obj_Type
) < 0) {
951 dob
= (dealloc_obj
*)dealloc_obj_Type
.tp_alloc(&dealloc_obj_Type
, 0);
952 dob
->mod
= bpy_proxy
; /* borrow */
953 PyModule_AddObject(bpy_proxy
, "__file__", (PyObject
*)dob
); /* borrow */
958 static void bpy_module_free(void * /*mod*/)
965 bool BPY_string_is_keyword(const char *str
)
967 /* List is from: `", ".join(['"%s"' % kw for kw in __import__("keyword").kwlist])`. */
968 const char *kwlist
[] = {
969 "False", "None", "True", "and", "as", "assert", "async", "await", "break",
970 "class", "continue", "def", "del", "elif", "else", "except", "finally", "for",
971 "from", "global", "if", "import", "in", "is", "lambda", "nonlocal", "not",
972 "or", "pass", "raise", "return", "try", "while", "with", "yield", nullptr,
975 for (int i
= 0; kwlist
[i
]; i
++) {
976 if (STREQ(str
, kwlist
[i
])) {
984 /* -------------------------------------------------------------------- */
985 /** \name Character Classification
987 * Define `text.cc` functions here (declared in `BKE_text.h`),
988 * This could be removed if Blender gets its own unicode library.
991 int text_check_identifier_unicode(const uint ch
)
993 return (ch
< 255 && text_check_identifier(char(ch
))) || Py_UNICODE_ISALNUM(ch
);
996 int text_check_identifier_nodigit_unicode(const uint ch
)
998 return (ch
< 255 && text_check_identifier_nodigit(char(ch
))) || Py_UNICODE_ISALPHA(ch
);