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