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