Blender V5.0
bpy.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
12
13/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
14#define PY_SSIZE_T_CLEAN
15
16#include <Python.h>
17
18#include "BLI_string.h"
19#include "BLI_string_utils.hh"
20#include "BLI_utildefines.h"
21
22#include "BKE_appdir.hh"
23#include "BKE_blender_version.h"
24#include "BKE_bpath.hh"
25#include "BKE_global.hh" /* XXX, G_MAIN only */
26
27#include "RNA_access.hh"
28#include "RNA_enum_types.hh"
29#include "RNA_prototypes.hh"
30
31#include "GPU_state.hh"
32
33#include "WM_api.hh" /* For #WM_ghost_backend */
34
35#include "bpy.hh"
36#include "bpy_app.hh"
37#include "bpy_cli_command.hh"
38#include "bpy_driver.hh"
39#include "bpy_geometry_set.hh"
41#include "bpy_library.hh"
42#include "bpy_operator.hh"
43#include "bpy_props.hh"
44#include "bpy_rna.hh"
45#include "bpy_rna_data.hh"
46#include "bpy_rna_gizmo.hh"
47#include "bpy_rna_types_capi.hh"
48#include "bpy_utils_previews.hh"
49#include "bpy_utils_units.hh"
50
52#include "../generic/python_compat.hh" /* IWYU pragma: keep. */
54
55/* external util modules */
58#include "bpy_msgbus.hh"
59
60#ifdef WITH_FREESTYLE
61# include "BPy_Freestyle.h"
62#endif
63
64PyObject *bpy_package_py = nullptr;
65
67 /* Wrap. */
68 bpy_script_paths_doc,
69 ".. function:: script_paths()\n"
70 "\n"
71 " Return 2 paths to blender scripts directories.\n"
72 "\n"
73 " :return: (system, user) strings will be empty when not found.\n"
74 " :rtype: tuple[str, str]\n");
75static PyObject *bpy_script_paths(PyObject * /*self*/)
76{
77 PyObject *ret = PyTuple_New(2);
78 PyObject *item;
79
80 std::optional<std::string> path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, nullptr);
81 item = PyC_UnicodeFromStdStr(path.value_or(""));
82 BLI_assert(item != nullptr);
83 PyTuple_SET_ITEM(ret, 0, item);
85 item = PyC_UnicodeFromStdStr(path.value_or(""));
86 BLI_assert(item != nullptr);
87 PyTuple_SET_ITEM(ret, 1, item);
88
89 return ret;
90}
91
93 char * /*path_dst*/,
94 size_t /*path_dst_maxncpy*/,
95 const char *path_src)
96{
97 PyObject *py_list = static_cast<PyObject *>(bpath_data->user_data);
98 PyList_APPEND(py_list, PyC_UnicodeFromBytes(path_src));
99 return false; /* Never edits the path. */
100}
101
103 /* Wrap. */
104 bpy_blend_paths_doc,
105 ".. function:: blend_paths(*, absolute=False, packed=False, local=False)\n"
106 "\n"
107 " Returns a list of paths to external files referenced by the loaded .blend file.\n"
108 "\n"
109 " :arg absolute: When true the paths returned are made absolute.\n"
110 " :type absolute: bool\n"
111 " :arg packed: When true skip file paths for packed data.\n"
112 " :type packed: bool\n"
113 " :arg local: When true skip linked library paths.\n"
114 " :type local: bool\n"
115 " :return: path list.\n"
116 " :rtype: list[str]\n");
117static PyObject *bpy_blend_paths(PyObject * /*self*/, PyObject *args, PyObject *kw)
118{
120 PyObject *list;
121
122 bool absolute = false;
123 bool packed = false;
124 bool local = false;
125
126 static const char *_keywords[] = {"absolute", "packed", "local", nullptr};
127 static _PyArg_Parser _parser = {
129 "|$" /* Optional keyword only arguments. */
130 "O&" /* `absolute` */
131 "O&" /* `packed` */
132 "O&" /* `local` */
133 ":blend_paths",
134 _keywords,
135 nullptr,
136 };
137 if (!_PyArg_ParseTupleAndKeywordsFast(args,
138 kw,
139 &_parser,
141 &absolute,
143 &packed,
145 &local))
146 {
147 return nullptr;
148 }
149
150 if (absolute) {
152 }
153 if (!packed) {
155 }
156 if (local) {
158 }
159
160 list = PyList_New(0);
161
162 BPathForeachPathData path_data{};
163 path_data.bmain = G_MAIN;
165 path_data.flag = flag;
166 path_data.user_data = list;
167 BKE_bpath_foreach_path_main(&path_data);
168
169 return list;
170}
171
173 /* Wrap. */
174 bpy_flip_name_doc,
175 ".. function:: flip_name(name, *, strip_digits=False)\n"
176 "\n"
177 " Flip a name between left/right sides, useful for \n"
178 " mirroring bone names.\n"
179 "\n"
180 " :arg name: Bone name to flip.\n"
181 " :type name: str\n"
182 " :arg strip_digits: Whether to remove ``.###`` suffix.\n"
183 " :type strip_digits: bool\n"
184 " :return: The flipped name.\n"
185 " :rtype: str\n");
186static PyObject *bpy_flip_name(PyObject * /*self*/, PyObject *args, PyObject *kw)
187{
188 const char *name_src = nullptr;
189 Py_ssize_t name_src_len;
190 bool strip_digits = false;
191
192 static const char *_keywords[] = {"", "strip_digits", nullptr};
193 static _PyArg_Parser _parser = {
195 "s#" /* `name` */
196 "|$" /* Optional, keyword only arguments. */
197 "O&" /* `strip_digits` */
198 ":flip_name",
199 _keywords,
200 nullptr,
201 };
202 if (!_PyArg_ParseTupleAndKeywordsFast(
203 args, kw, &_parser, &name_src, &name_src_len, PyC_ParseBool, &strip_digits))
204 {
205 return nullptr;
206 }
207
208 /* Worst case we gain one extra byte (besides null-terminator) by changing
209 * "Left" to "Right", because only the first appearance of "Left" gets replaced. */
210 const size_t size = name_src_len + 2;
211 char *name_dst = static_cast<char *>(PyMem_MALLOC(size));
212 const size_t name_dst_len = BLI_string_flip_side_name(name_dst, name_src, strip_digits, size);
213
214 PyObject *result = PyUnicode_FromStringAndSize(name_dst, name_dst_len);
215
216 PyMem_FREE(name_dst);
217
218 return result;
219}
220
221/* `bpy_user_resource_doc`, Now in `bpy/utils/__init__.py`. */
222static PyObject *bpy_user_resource(PyObject * /*self*/, PyObject *args, PyObject *kw)
223{
224 const PyC_StringEnumItems type_items[] = {
225 {BLENDER_USER_DATAFILES, "DATAFILES"},
226 {BLENDER_USER_CONFIG, "CONFIG"},
227 {BLENDER_USER_SCRIPTS, "SCRIPTS"},
228 {BLENDER_USER_EXTENSIONS, "EXTENSIONS"},
229 {0, nullptr},
230 };
231 PyC_StringEnum type = {type_items};
232 PyC_UnicodeAsBytesAndSize_Data subdir_data = {nullptr};
233
234 static const char *_keywords[] = {"type", "path", nullptr};
235 static _PyArg_Parser _parser = {
237 "O&" /* `type` */
238 "|$" /* Optional keyword only arguments. */
239 "O&" /* `path` */
240 ":user_resource",
241 _keywords,
242 nullptr,
243 };
244 if (!_PyArg_ParseTupleAndKeywordsFast(args,
245 kw,
246 &_parser,
248 &type,
250 &subdir_data))
251 {
252 return nullptr;
253 }
254
255 /* same logic as BKE_appdir_folder_id_create(),
256 * but best leave it up to the script author to create */
257 const std::optional<std::string> path = BKE_appdir_folder_id_user_notest(type.value_found,
258 subdir_data.value);
259 Py_XDECREF(subdir_data.value_coerce);
260
261 return PyC_UnicodeFromStdStr(path.value_or(""));
262}
263
265 /* Wrap. */
266 bpy_system_resource_doc,
267 ".. function:: system_resource(type, *, path=\"\")\n"
268 "\n"
269 " Return a system resource path.\n"
270 "\n"
271 " :arg type: string in ['DATAFILES', 'SCRIPTS', 'EXTENSIONS', 'PYTHON'].\n"
272 " :type type: str\n"
273 " :arg path: Optional subdirectory.\n"
274 " :type path: str | bytes\n");
275static PyObject *bpy_system_resource(PyObject * /*self*/, PyObject *args, PyObject *kw)
276{
277 const PyC_StringEnumItems type_items[] = {
278 {BLENDER_SYSTEM_DATAFILES, "DATAFILES"},
279 {BLENDER_SYSTEM_SCRIPTS, "SCRIPTS"},
280 {BLENDER_SYSTEM_EXTENSIONS, "EXTENSIONS"},
281 {BLENDER_SYSTEM_PYTHON, "PYTHON"},
282 {0, nullptr},
283 };
284 PyC_StringEnum type = {type_items};
285
286 PyC_UnicodeAsBytesAndSize_Data subdir_data = {nullptr};
287
288 static const char *_keywords[] = {"type", "path", nullptr};
289 static _PyArg_Parser _parser = {
291 "O&" /* `type` */
292 "|$" /* Optional keyword only arguments. */
293 "O&" /* `path` */
294 ":system_resource",
295 _keywords,
296 nullptr,
297 };
298 if (!_PyArg_ParseTupleAndKeywordsFast(args,
299 kw,
300 &_parser,
302 &type,
304 &subdir_data))
305 {
306 return nullptr;
307 }
308
309 std::optional<std::string> path = BKE_appdir_folder_id(type.value_found, subdir_data.value);
310 Py_XDECREF(subdir_data.value_coerce);
311
312 return PyC_UnicodeFromStdStr(path.value_or(""));
313}
314
316 /* Wrap. */
317 bpy_resource_path_doc,
318 ".. function:: resource_path(type, *, major=bpy.app.version[0], minor=bpy.app.version[1])\n"
319 "\n"
320 " Return the base path for storing system files.\n"
321 "\n"
322 " :arg type: string in ['USER', 'LOCAL', 'SYSTEM'].\n"
323 " :type type: str\n"
324 " :arg major: major version, defaults to current.\n"
325 " :type major: int\n"
326 " :arg minor: minor version, defaults to current.\n"
327 " :type minor: str\n"
328 " :return: the resource path (not necessarily existing).\n"
329 " :rtype: str\n");
330static PyObject *bpy_resource_path(PyObject * /*self*/, PyObject *args, PyObject *kw)
331{
332 const PyC_StringEnumItems type_items[] = {
336 {0, nullptr},
337 };
338 PyC_StringEnum type = {type_items};
339
340 int major = BLENDER_VERSION / 100, minor = BLENDER_VERSION % 100;
341
342 static const char *_keywords[] = {"type", "major", "minor", nullptr};
343 static _PyArg_Parser _parser = {
345 "O&" /* `type` */
346 "|$" /* Optional keyword only arguments. */
347 "i" /* `major` */
348 "i" /* `minor` */
349 ":resource_path",
350 _keywords,
351 nullptr,
352 };
353 if (!_PyArg_ParseTupleAndKeywordsFast(
354 args, kw, &_parser, PyC_ParseStringEnum, &type, &major, &minor))
355 {
356 return nullptr;
357 }
358
359 const std::optional<std::string> path = BKE_appdir_resource_path_id_with_version(
360 type.value_found, false, (major * 100) + minor);
361
362 return PyC_UnicodeFromStdStr(path.value_or(""));
363}
364
365/* This is only exposed for tests, see: `tests/python/bl_pyapi_bpy_driver_secure_eval.py`. */
367 /* Wrap. */
368 bpy_driver_secure_code_test_doc,
369 ".. function:: _driver_secure_code_test(code, *, namespace=None, verbose=False)\n"
370 "\n"
371 " Test if the script should be considered trusted.\n"
372 "\n"
373 " :arg code: The code to test.\n"
374 " :type code: code\n"
375 " :arg namespace: The namespace of values which are allowed.\n"
376 " :type namespace: dict[str, Any]\n"
377 " :arg verbose: Print the reason for considering insecure to the ``stderr``.\n"
378 " :type verbose: bool\n"
379 " :return: True when the script is considered trusted.\n"
380 " :rtype: bool\n");
381static PyObject *bpy_driver_secure_code_test(PyObject * /*self*/, PyObject *args, PyObject *kw)
382{
383 PyObject *py_code;
384 PyObject *py_namespace = nullptr;
385 const bool verbose = false;
386 static const char *_keywords[] = {"code", "namespace", "verbose", nullptr};
387 static _PyArg_Parser _parser = {
389 "O!" /* `expression` */
390 "|$" /* Optional keyword only arguments. */
391 "O!" /* `namespace` */
392 "O&" /* `verbose` */
393 ":driver_secure_code_test",
394 _keywords,
395 nullptr,
396 };
397 if (!_PyArg_ParseTupleAndKeywordsFast(args,
398 kw,
399 &_parser,
400 &PyCode_Type,
401 &py_code,
402 &PyDict_Type,
403 &py_namespace,
405 &verbose))
406 {
407 return nullptr;
408 }
409 return PyBool_FromLong(BPY_driver_secure_bytecode_test(py_code, py_namespace, verbose));
410}
411
413 /* Wrap. */
414 bpy_escape_identifier_doc,
415 ".. function:: escape_identifier(string)\n"
416 "\n"
417 " Simple string escaping function used for animation paths.\n"
418 "\n"
419 " :arg string: text\n"
420 " :type string: str\n"
421 " :return: The escaped string.\n"
422 " :rtype: str\n");
423static PyObject *bpy_escape_identifier(PyObject * /*self*/, PyObject *value)
424{
425 Py_ssize_t value_str_len;
426 const char *value_str = PyUnicode_AsUTF8AndSize(value, &value_str_len);
427
428 if (value_str == nullptr) {
429 PyErr_SetString(PyExc_TypeError, "expected a string");
430 return nullptr;
431 }
432
433 const size_t size = (value_str_len * 2) + 1;
434 char *value_escape_str = static_cast<char *>(PyMem_MALLOC(size));
435 const Py_ssize_t value_escape_str_len = BLI_str_escape(value_escape_str, value_str, size);
436
437 PyObject *value_escape;
438 if (value_escape_str_len == value_str_len) {
439 Py_INCREF(value);
440 value_escape = value;
441 }
442 else {
443 value_escape = PyUnicode_FromStringAndSize(value_escape_str, value_escape_str_len);
444 }
445
446 PyMem_FREE(value_escape_str);
447
448 return value_escape;
449}
450
452 /* Wrap. */
453 bpy_unescape_identifier_doc,
454 ".. function:: unescape_identifier(string)\n"
455 "\n"
456 " Simple string un-escape function used for animation paths.\n"
457 " This performs the reverse of :func:`escape_identifier`.\n"
458 "\n"
459 " :arg string: text\n"
460 " :type string: str\n"
461 " :return: The un-escaped string.\n"
462 " :rtype: str\n");
463static PyObject *bpy_unescape_identifier(PyObject * /*self*/, PyObject *value)
464{
465 Py_ssize_t value_str_len;
466 const char *value_str = PyUnicode_AsUTF8AndSize(value, &value_str_len);
467
468 if (value_str == nullptr) {
469 PyErr_SetString(PyExc_TypeError, "expected a string");
470 return nullptr;
471 }
472
473 const size_t size = value_str_len + 1;
474 char *value_unescape_str = static_cast<char *>(PyMem_MALLOC(size));
475 const Py_ssize_t value_unescape_str_len = BLI_str_unescape(value_unescape_str, value_str, size);
476
477 PyObject *value_unescape;
478 if (value_unescape_str_len == value_str_len) {
479 Py_INCREF(value);
480 value_unescape = value;
481 }
482 else {
483 value_unescape = PyUnicode_FromStringAndSize(value_unescape_str, value_unescape_str_len);
484 }
485
486 PyMem_FREE(value_unescape_str);
487
488 return value_unescape;
489}
490
491extern "C" const char *buttons_context_dir[];
492extern "C" const char *clip_context_dir[];
493extern "C" const char *file_context_dir[];
494extern "C" const char *image_context_dir[];
495extern "C" const char *node_context_dir[];
496extern "C" const char *screen_context_dir[];
497extern "C" const char *sequencer_context_dir[];
498extern "C" const char *text_context_dir[];
499extern "C" const char *view3d_context_dir[];
500
505 /* Wrap. */
506 bpy_context_members_doc,
507 ".. function:: context_members()\n"
508 "\n"
509 " :return: A dict where the key is the context and the value is a tuple of it's members.\n"
510 " :rtype: dict[str, tuple[str]]\n");
511static PyObject *bpy_context_members(PyObject * /*self*/)
512{
513
514 struct {
515 const char *name;
516 const char **dir;
517 } context_members_all[] = {
518 {"buttons", buttons_context_dir},
519 {"clip", clip_context_dir},
520 {"file", file_context_dir},
521 {"image", image_context_dir},
522 {"node", node_context_dir},
523 {"screen", screen_context_dir},
524 {"sequencer", sequencer_context_dir},
525 {"text", text_context_dir},
526 {"view3d", view3d_context_dir},
527 };
528
529 PyObject *result = _PyDict_NewPresized(ARRAY_SIZE(context_members_all));
530 for (int context_index = 0; context_index < ARRAY_SIZE(context_members_all); context_index++) {
531 const char *name = context_members_all[context_index].name;
532 const char **dir = context_members_all[context_index].dir;
533 int i;
534 for (i = 0; dir[i]; i++) {
535 /* Pass. */
536 }
537 PyObject *members = PyTuple_New(i);
538 for (i = 0; dir[i]; i++) {
539 PyTuple_SET_ITEM(members, i, PyUnicode_FromString(dir[i]));
540 }
541 PyDict_SetItemString(result, name, members);
543 }
544 BLI_assert(PyDict_GET_SIZE(result) == ARRAY_SIZE(context_members_all));
545
546 return result;
547}
548
553 /* Wrap. */
554 bpy_rna_enum_items_static_doc,
555 ".. function:: rna_enum_items_static()\n"
556 "\n"
557 " :return: A dict where the key the name of the enum, the value is a tuple of enum items.\n"
558 " :rtype: dict[str, tuple[:class:`bpy.types.EnumPropertyItem`]]\n");
559static PyObject *bpy_rna_enum_items_static(PyObject * /*self*/)
560{
561#define DEF_ENUM(id) {STRINGIFY(id), id},
562 struct {
563 const char *id;
564 const EnumPropertyItem *items;
565 } enum_info[] = {
566#include "RNA_enum_items.hh"
567 };
568 PyObject *result = _PyDict_NewPresized(ARRAY_SIZE(enum_info));
569 for (int i = 0; i < ARRAY_SIZE(enum_info); i++) {
570 /* Include all items (including headings & separators), can be shown in documentation. */
571 const EnumPropertyItem *items = enum_info[i].items;
572 const int items_count = RNA_enum_items_count(items);
573 PyObject *value = PyTuple_New(items_count);
574 for (int item_index = 0; item_index < items_count; item_index++) {
576 nullptr, &RNA_EnumPropertyItem, (void *)&items[item_index]);
577 PyTuple_SET_ITEM(value, item_index, pyrna_struct_CreatePyObject(&ptr));
578 }
579 PyDict_SetItemString(result, enum_info[i].id, value);
580 Py_DECREF(value);
581 }
582 return result;
583}
584
585/* This is only exposed for (Unix/Linux), see: #GHOST_ISystem::getSystemBackend for details. */
587 /* Wrap. */
588 bpy_ghost_backend_doc,
589 ".. function:: _ghost_backend()\n"
590 "\n"
591 " :return: An identifier for the GHOST back-end.\n"
592 " :rtype: str\n");
593static PyObject *bpy_ghost_backend(PyObject * /*self*/)
594{
595 return PyUnicode_FromString(WM_ghost_backend());
596}
597
598/* NOTE(@ideasman42): This is a private function because the keys in the returned dictionary,
599 * are not considered stable. Sometimes a function is temporarily only supported by one platform.
600 * Once all platforms support the functionality there is no need for the flag
601 * and it can be removed. This is at odds with a public API that has values which are
602 * intended to be kept between releases.
603 * If this were to be made public we would have to document that this is subject to change. */
604
606 /* Wrap. */
607 bpy_wm_capabilities_doc,
608 ".. function:: _wm_capabilities()\n"
609 "\n"
610 " :return: A dictionary of capabilities (string keys, boolean values).\n"
611 " :rtype: dict[str, bool]\n");
612static PyObject *bpy_wm_capabilities(PyObject *self)
613{
614 PyObject *py_id_capabilities = PyUnicode_FromString("_wm_capabilities_");
615 PyObject *result = nullptr;
616 switch (PyObject_GetOptionalAttr(self, py_id_capabilities, &result)) {
617 case 1: {
618 BLI_assert(result != nullptr);
619 break;
620 }
621 case 0: {
622 result = PyDict_New();
623
625
626#define SetFlagItem(x) \
627 PyDict_SetItemString(result, STRINGIFY(x), PyBool_FromLong((WM_CAPABILITY_##x) & flag));
628
629 /* Only exposed flags which are used, by Blender's built-in scripts
630 * since this is a private API. */
631
632 SetFlagItem(TRACKPAD_PHYSICAL_DIRECTION);
633 SetFlagItem(KEYBOARD_HYPER_KEY);
634
635#undef SetFlagItem
636 PyObject_SetAttr(self, py_id_capabilities, result);
637 break;
638 }
639 default:
640 /* Unlikely, but there may be an error, forward it. */
641 BLI_assert(result == nullptr);
642 break;
643 }
644
645 Py_DECREF(py_id_capabilities);
646 return result;
647}
648
649#ifdef __GNUC__
650# ifdef __clang__
651# pragma clang diagnostic push
652# pragma clang diagnostic ignored "-Wcast-function-type"
653# else
654# pragma GCC diagnostic push
655# pragma GCC diagnostic ignored "-Wcast-function-type"
656# endif
657#endif
658
659static PyMethodDef bpy_methods[] = {
660 {"script_paths", (PyCFunction)bpy_script_paths, METH_NOARGS, bpy_script_paths_doc},
661 {"blend_paths",
662 (PyCFunction)bpy_blend_paths,
663 METH_VARARGS | METH_KEYWORDS,
664 bpy_blend_paths_doc},
665 {"flip_name", (PyCFunction)bpy_flip_name, METH_VARARGS | METH_KEYWORDS, bpy_flip_name_doc},
666 {"user_resource", (PyCFunction)bpy_user_resource, METH_VARARGS | METH_KEYWORDS, nullptr},
667 {"system_resource",
668 (PyCFunction)bpy_system_resource,
669 METH_VARARGS | METH_KEYWORDS,
670 bpy_system_resource_doc},
671 {"resource_path",
672 (PyCFunction)bpy_resource_path,
673 METH_VARARGS | METH_KEYWORDS,
674 bpy_resource_path_doc},
675 {"escape_identifier", (PyCFunction)bpy_escape_identifier, METH_O, bpy_escape_identifier_doc},
676 {"unescape_identifier",
677 (PyCFunction)bpy_unescape_identifier,
678 METH_O,
679 bpy_unescape_identifier_doc},
680 {"context_members", (PyCFunction)bpy_context_members, METH_NOARGS, bpy_context_members_doc},
681 {"rna_enum_items_static",
682 (PyCFunction)bpy_rna_enum_items_static,
683 METH_NOARGS,
684 bpy_rna_enum_items_static_doc},
685
686 /* Private functions (not part of the public API and may be removed at any time). */
687 {"_driver_secure_code_test",
688 (PyCFunction)bpy_driver_secure_code_test,
689 METH_VARARGS | METH_KEYWORDS,
690 bpy_driver_secure_code_test_doc},
691 {"_ghost_backend", (PyCFunction)bpy_ghost_backend, METH_NOARGS, bpy_ghost_backend_doc},
692 {"_wm_capabilities", (PyCFunction)bpy_wm_capabilities, METH_NOARGS, bpy_wm_capabilities_doc},
693
694 {nullptr, nullptr, 0, nullptr},
695};
696
697#ifdef __GNUC__
698# ifdef __clang__
699# pragma clang diagnostic pop
700# else
701# pragma GCC diagnostic pop
702# endif
703#endif
704
705static PyObject *bpy_import_test(const char *modname)
706{
707 PyObject *mod = PyImport_ImportModuleLevel(modname, nullptr, nullptr, nullptr, 0);
708
709 if (mod) {
710 Py_DECREF(mod);
711 }
712 else {
713 PyErr_Print();
714 }
715
716 return mod;
717}
718
720{
721 PyObject *mod;
722
723 /* Needs to be first since this dir is needed for future modules */
724 const std::optional<std::string> modpath = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS,
725 "modules");
726 if (modpath.has_value()) {
727 // printf("bpy: found module path '%s'.\n", modpath);
728 PyObject *sys_path = PySys_GetObject("path"); /* borrow */
729 PyObject *py_modpath = PyC_UnicodeFromStdStr(modpath.value());
730 PyList_Insert(sys_path, 0, py_modpath); /* add first */
731 Py_DECREF(py_modpath);
732 }
733 else {
734 printf("bpy: couldn't find 'scripts/modules', blender probably won't start.\n");
735 }
736 /* stand alone utility modules not related to blender directly */
737 IDProp_Init_Types(); /* not actually a submodule, just types */
739#ifdef WITH_FREESTYLE
741#endif
742
743 mod = PyModule_New("_bpy");
744
745 /* add the module so we can import it */
746 PyDict_SetItemString(PyImport_GetModuleDict(), "_bpy", mod);
747 Py_DECREF(mod);
748
749 /* Needs to be first so `_bpy_types` can run. */
750 PyObject *bpy_types = BPY_rna_types();
751 PyModule_AddObject(bpy_types, "GeometrySet", BPyInit_geometry_set_type());
752 PyModule_AddObject(bpy_types, "InlineShaderNodes", BPyInit_inline_shader_nodes_type());
753 PyModule_AddObject(mod, "types", bpy_types);
754
755 /* Needs to be first so `_bpy_types` can run. */
757
759
761
762 /* Important to internalizes `_bpy_types` before creating RNA instances. */
763 {
764 /* Set a dummy module so the `_bpy_types.py` can access `bpy.types.ID`
765 * without a null pointer dereference when instancing types. */
766 PyObject *bpy_types_dict_dummy = PyDict_New();
767 BPY_rna_types_dict_set(bpy_types_dict_dummy);
768 PyObject *bpy_types_module_py = bpy_import_test("_bpy_types");
769 /* Something has gone wrong if this is ever populated. */
770 BLI_assert(PyDict_GET_SIZE(bpy_types_dict_dummy) == 0);
771 Py_DECREF(bpy_types_dict_dummy);
772
773 PyObject *bpy_types_module_py_dict = PyModule_GetDict(bpy_types_module_py);
774 BPY_rna_types_dict_set(bpy_types_module_py_dict);
775 }
776 PyModule_AddObject(mod, "data", BPY_rna_module());
778
779 PyModule_AddObject(mod, "props", BPY_rna_props());
780 PyModule_AddObject(mod, "ops", BPY_operator_module());
781 PyModule_AddObject(mod, "app", BPY_app_struct());
782 PyModule_AddObject(mod, "_utils_units", BPY_utils_units());
783 PyModule_AddObject(mod, "_utils_previews", BPY_utils_previews_module());
784 PyModule_AddObject(mod, "msgbus", BPY_msgbus_module());
785
786 PointerRNA ctx_ptr = RNA_pointer_create_discrete(nullptr, &RNA_Context, C);
788 PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module);
789
790 /* Register methods and property get/set for RNA types. */
792
793#define PYMODULE_ADD_METHOD(mod, meth) \
794 PyModule_AddObject(mod, (meth)->ml_name, (PyObject *)PyCFunction_New(meth, mod))
795
796 for (int i = 0; bpy_methods[i].ml_name; i++) {
797 PyMethodDef *m = &bpy_methods[i];
798 /* Currently there is no need to support these. */
799 BLI_assert((m->ml_flags & (METH_CLASS | METH_STATIC)) == 0);
801 }
802
803 /* Register functions (`bpy_rna.cc`). */
806
809
810 /* Register command functions. */
813
814#undef PYMODULE_ADD_METHOD
815
816 /* add our own modules dir, this is a python package */
818}
std::optional< std::string > BKE_appdir_folder_id_user_notest(int folder_id, const char *subfolder) ATTR_WARN_UNUSED_RESULT
Definition appdir.cc:730
std::optional< std::string > BKE_appdir_resource_path_id_with_version(int folder_id, bool check_is_dir, int version)
Definition appdir.cc:806
@ BLENDER_RESOURCE_PATH_SYSTEM
@ BLENDER_RESOURCE_PATH_LOCAL
@ BLENDER_RESOURCE_PATH_USER
std::optional< std::string > BKE_appdir_folder_id(int folder_id, const char *subfolder) ATTR_WARN_UNUSED_RESULT
Definition appdir.cc:721
@ BLENDER_USER_DATAFILES
@ BLENDER_USER_EXTENSIONS
@ BLENDER_SYSTEM_DATAFILES
@ BLENDER_SYSTEM_EXTENSIONS
@ BLENDER_SYSTEM_PYTHON
@ BLENDER_SYSTEM_SCRIPTS
@ BLENDER_USER_CONFIG
@ BLENDER_USER_SCRIPTS
#define BLENDER_VERSION
eBPathForeachFlag
Definition BKE_bpath.hh:32
@ BKE_BPATH_FOREACH_PATH_SKIP_LINKED
Definition BKE_bpath.hh:40
@ BKE_BPATH_FOREACH_PATH_ABSOLUTE
Definition BKE_bpath.hh:38
@ BKE_BPATH_FOREACH_PATH_SKIP_PACKED
Definition BKE_bpath.hh:42
void BKE_bpath_foreach_path_main(BPathForeachPathData *bpath_data)
Definition bpath.cc:116
#define G_MAIN
#define BLI_assert(a)
Definition BLI_assert.h:46
size_t size_t size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, size_t src_maxncpy) ATTR_NONNULL(1
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t BLI_string_flip_side_name(char *name_dst, const char *name_src, bool strip_number, size_t name_dst_maxncpy) ATTR_NONNULL(1
#define ARRAY_SIZE(arr)
PyObject * Freestyle_Init()
#define C
Definition RandGen.cpp:29
eWM_CapabilitiesFlag
Definition WM_api.hh:168
#define PYMODULE_ADD_METHOD(mod, meth)
static PyObject * bpy_ghost_backend(PyObject *)
Definition bpy.cc:593
static PyObject * bpy_unescape_identifier(PyObject *, PyObject *value)
Definition bpy.cc:463
#define SetFlagItem(x)
static PyObject * bpy_resource_path(PyObject *, PyObject *args, PyObject *kw)
Definition bpy.cc:330
static PyObject * bpy_blend_paths(PyObject *, PyObject *args, PyObject *kw)
Definition bpy.cc:117
static PyObject * bpy_escape_identifier(PyObject *, PyObject *value)
Definition bpy.cc:423
static PyMethodDef bpy_methods[]
Definition bpy.cc:659
PyObject * bpy_package_py
Definition bpy.cc:64
void BPy_init_modules(bContext *C)
Definition bpy.cc:719
static PyObject * bpy_driver_secure_code_test(PyObject *, PyObject *args, PyObject *kw)
Definition bpy.cc:381
static PyObject * bpy_flip_name(PyObject *, PyObject *args, PyObject *kw)
Definition bpy.cc:186
static PyObject * bpy_import_test(const char *modname)
Definition bpy.cc:705
static bool bpy_blend_foreach_path_cb(BPathForeachPathData *bpath_data, char *, size_t, const char *path_src)
Definition bpy.cc:92
PyDoc_STRVAR(bpy_script_paths_doc, ".. function:: script_paths()\n" "\n" " Return 2 paths to blender scripts directories.\n" "\n" " :return: (system, user) strings will be empty when not found.\n" " :rtype: tuple[str, str]\n")
const char * sequencer_context_dir[]
Definition bpy.cc:497
static PyObject * bpy_wm_capabilities(PyObject *self)
Definition bpy.cc:612
static PyObject * bpy_context_members(PyObject *)
Definition bpy.cc:511
static PyObject * bpy_system_resource(PyObject *, PyObject *args, PyObject *kw)
Definition bpy.cc:275
static PyObject * bpy_script_paths(PyObject *)
Definition bpy.cc:75
static PyObject * bpy_user_resource(PyObject *, PyObject *args, PyObject *kw)
Definition bpy.cc:222
PyObject * BPY_app_struct()
Definition bpy_app.cc:823
PyMethodDef BPY_cli_command_register_def
PyMethodDef BPY_cli_command_unregister_def
PyObject * self
bool BPY_driver_secure_bytecode_test(PyObject *expr_code, PyObject *py_namespace, const bool verbose)
PyObject * BPyInit_geometry_set_type()
PyObject * BPyInit_inline_shader_nodes_type()
int BPY_library_load_type_ready()
PyObject * BPY_msgbus_module()
PyObject * BPY_operator_module()
PyObject * BPY_rna_props()
PyMethodDef meth_bpy_owner_id_set
Definition bpy_rna.cc:10604
PyObject * BPY_rna_module()
Definition bpy_rna.cc:8703
PyMethodDef meth_bpy_owner_id_get
Definition bpy_rna.cc:10598
void BPY_rna_types_finalize_external_types(PyObject *submodule)
Definition bpy_rna.cc:8898
void BPY_rna_types_dict_set(PyObject *dict)
Definition bpy_rna.cc:8237
PyObject * BPY_rna_types()
Definition bpy_rna.cc:8868
PyMethodDef meth_bpy_unregister_class
Definition bpy_rna.cc:10378
PyMethodDef meth_bpy_register_class
Definition bpy_rna.cc:10147
PyObject * pyrna_struct_CreatePyObject(PointerRNA *ptr)
Definition bpy_rna.cc:8496
BPy_StructRNA * bpy_context_module
Definition bpy_rna.cc:96
int BPY_rna_data_context_type_ready()
bool BPY_rna_gizmo_module(PyObject *mod_par)
void BPY_rna_types_extend_capi()
PyObject * BPY_utils_previews_module()
PyObject * BPY_utils_units()
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
btMatrix3x3 absolute() const
Return the matrix with all values non negative.
Definition btVector3.h:364
const char * buttons_context_dir[]
static int verbose
Definition cineonlib.cc:30
const char * file_context_dir[]
#define packed
#define printf(...)
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
void IDProp_Init_Types()
void IDPropertyUIData_Init_Types()
const char * image_context_dir[]
static char ** members
Definition makesdna.cc:69
const char * node_context_dir[]
int PyC_ParseUnicodeAsBytesAndSize(PyObject *o, void *p)
int PyC_ParseStringEnum(PyObject *o, void *p)
PyObject * PyC_UnicodeFromBytes(const char *str)
PyObject * PyC_UnicodeFromStdStr(const std::string &str)
int PyC_ParseBool(PyObject *o, void *p)
header-only compatibility defines.
#define PyObject_GetOptionalAttr
Py_DECREF(oname)
#define PY_ARG_PARSER_HEAD_COMPAT()
const char * name
header-only utilities
return ret
uint RNA_enum_items_count(const EnumPropertyItem *item)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
const char * screen_context_dir[]
const char * clip_context_dir[]
const char * text_context_dir[]
eBPathForeachFlag flag
Definition BKE_bpath.hh:102
BPathForeachPathFunctionCallback callback_function
Definition BKE_bpath.hh:101
i
Definition text_draw.cc:230
const char * view3d_context_dir[]
PointerRNA * ptr
Definition wm_files.cc:4238
const char * WM_ghost_backend()
eWM_CapabilitiesFlag WM_capabilities_flag()
uint8_t flag
Definition wm_window.cc:145