Blender V5.0
py_capi_utils.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
11
12/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
13#define PY_SSIZE_T_CLEAN
14
15#include <Python.h>
16#include <frameobject.h>
17
18#include "BLI_utildefines.h" /* for bool */
19
20#include "py_capi_utils.hh"
21
22#include "python_utildefines.hh"
23
24#ifndef MATH_STANDALONE
25# include "MEM_guardedalloc.h"
26
27# include "BLI_string_utf8.h"
28#endif
29
30#ifdef _WIN32
31# include "BLI_math_base.h" /* isfinite() */
32#endif
33
34#if PY_VERSION_HEX < 0x030d0000 /* <3.13 */
35# define PyLong_AsInt _PyLong_AsInt
36#endif
37
38/* -------------------------------------------------------------------- */
41
42/* array utility function */
44 const size_t array_item_size,
45 PyObject *value_fast,
46 const Py_ssize_t length,
47 const PyTypeObject *type,
48 const char *error_prefix)
49{
50 const Py_ssize_t value_len = PySequence_Fast_GET_SIZE(value_fast);
51 PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
52 Py_ssize_t i;
53
54 BLI_assert(PyList_Check(value_fast) || PyTuple_Check(value_fast));
55
56 if (value_len != length) {
57 PyErr_Format(PyExc_TypeError,
58 "%.200s: invalid sequence length. expected %d, got %d",
59 error_prefix,
60 length,
61 value_len);
62 return -1;
63 }
64
65 /* for each type */
66 if (type == &PyFloat_Type) {
67 switch (array_item_size) {
68 case sizeof(double): {
69 double *array_double = static_cast<double *>(array);
70 for (i = 0; i < length; i++) {
71 array_double[i] = PyFloat_AsDouble(value_fast_items[i]);
72 }
73 break;
74 }
75 case sizeof(float): {
76 float *array_float = static_cast<float *>(array);
77 for (i = 0; i < length; i++) {
78 array_float[i] = PyFloat_AsDouble(value_fast_items[i]);
79 }
80 break;
81 }
82 default: {
83 /* Internal error. */
85 }
86 }
87 }
88 else if (type == &PyLong_Type) {
89 switch (array_item_size) {
90 case sizeof(int64_t): {
91 int64_t *array_int = static_cast<int64_t *>(array);
92 for (i = 0; i < length; i++) {
93 array_int[i] = PyC_Long_AsI64(value_fast_items[i]);
94 }
95 break;
96 }
97 case sizeof(int32_t): {
98 int32_t *array_int = static_cast<int32_t *>(array);
99 for (i = 0; i < length; i++) {
100 array_int[i] = PyC_Long_AsI32(value_fast_items[i]);
101 }
102 break;
103 }
104 case sizeof(int16_t): {
105 int16_t *array_int = static_cast<int16_t *>(array);
106 for (i = 0; i < length; i++) {
107 array_int[i] = PyC_Long_AsI16(value_fast_items[i]);
108 }
109 break;
110 }
111 case sizeof(int8_t): {
112 int8_t *array_int = static_cast<int8_t *>(array);
113 for (i = 0; i < length; i++) {
114 array_int[i] = PyC_Long_AsI8(value_fast_items[i]);
115 }
116 break;
117 }
118 default: {
119 /* Internal error. */
121 }
122 }
123 }
124 else if (type == &PyBool_Type) {
125 switch (array_item_size) {
126 case sizeof(int64_t): {
127 int64_t *array_bool = static_cast<int64_t *>(array);
128 for (i = 0; i < length; i++) {
129 array_bool[i] = (PyLong_AsLong(value_fast_items[i]) != 0);
130 }
131 break;
132 }
133 case sizeof(int32_t): {
134 int32_t *array_bool = static_cast<int32_t *>(array);
135 for (i = 0; i < length; i++) {
136 array_bool[i] = (PyLong_AsLong(value_fast_items[i]) != 0);
137 }
138 break;
139 }
140 case sizeof(int16_t): {
141 int16_t *array_bool = static_cast<int16_t *>(array);
142 for (i = 0; i < length; i++) {
143 array_bool[i] = (PyLong_AsLong(value_fast_items[i]) != 0);
144 }
145 break;
146 }
147 case sizeof(int8_t): {
148 int8_t *array_bool = static_cast<int8_t *>(array);
149 for (i = 0; i < length; i++) {
150 array_bool[i] = (PyLong_AsLong(value_fast_items[i]) != 0);
151 }
152 break;
153 }
154 default: {
155 /* Internal error. */
157 }
158 }
159 }
160 else {
161 PyErr_Format(PyExc_TypeError, "%s: internal error %s is invalid", error_prefix, type->tp_name);
162 return -1;
163 }
164
165 if (PyErr_Occurred()) {
166 PyErr_Format(PyExc_TypeError,
167 "%s: one or more items could not be used as a %s",
168 error_prefix,
169 type->tp_name);
170 return -1;
171 }
172
173 return 0;
174}
175
177 const size_t array_item_size,
178 PyObject *value,
179 const Py_ssize_t length,
180 const PyTypeObject *type,
181 const char *error_prefix)
182{
183 PyObject *value_fast;
184 int ret;
185
186 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
187 return -1;
188 }
189
190 ret = PyC_AsArray_FAST(array, array_item_size, value_fast, length, type, error_prefix);
191 Py_DECREF(value_fast);
192 return ret;
193}
194
195static int PyC_AsArray_Multi_impl(void **array_p,
196 const size_t array_item_size,
197 PyObject *value,
198 const int *dims,
199 const int dims_len,
200 const PyTypeObject *type,
201 const char *error_prefix);
202
203static int PyC_AsArray_Multi_FAST_impl(void **array_p,
204 const size_t array_item_size,
205 PyObject *value_fast,
206 const int *dims,
207 const int dims_len,
208 const PyTypeObject *type,
209 const char *error_prefix)
210{
211 const Py_ssize_t value_len = PySequence_Fast_GET_SIZE(value_fast);
212 const int length = dims[0];
213
214 if (dims_len == 1) {
215 if (PyC_AsArray_FAST(*array_p, array_item_size, value_fast, length, type, error_prefix) == -1)
216 {
217 return -1;
218 }
219 *array_p = POINTER_OFFSET(*array_p, array_item_size * length);
220 }
221 else {
222 if (value_len != length) {
223 PyErr_Format(PyExc_TypeError,
224 "%.200s: invalid sequence length. expected %d, got %d",
225 error_prefix,
226 length,
227 value_len);
228 return -1;
229 }
230
231 PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
232 const int *dims_next = dims + 1;
233 const int dims_next_len = dims_len - 1;
234
235 for (int i = 0; i < length; i++) {
236 if (PyC_AsArray_Multi_impl(array_p,
237 array_item_size,
238 value_fast_items[i],
239 dims_next,
240 dims_next_len,
241 type,
242 error_prefix) == -1)
243 {
244 return -1;
245 }
246 }
247 }
248 return 0;
249}
250
251static int PyC_AsArray_Multi_impl(void **array_p,
252 const size_t array_item_size,
253 PyObject *value,
254 const int *dims,
255 const int dims_len,
256 const PyTypeObject *type,
257 const char *error_prefix)
258{
259 PyObject *value_fast;
260 int ret;
261
262 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
263 return -1;
264 }
265
267 array_p, array_item_size, value_fast, dims, dims_len, type, error_prefix);
268 Py_DECREF(value_fast);
269 return ret;
270}
271
273 const size_t array_item_size,
274 PyObject *value_fast,
275 const int *dims,
276 const int dims_len,
277 const PyTypeObject *type,
278 const char *error_prefix)
279{
281 &array, array_item_size, value_fast, dims, dims_len, type, error_prefix);
282}
283
285 const size_t array_item_size,
286 PyObject *value,
287 const int *dims,
288 const int dims_len,
289 const PyTypeObject *type,
290 const char *error_prefix)
291{
293 &array, array_item_size, value, dims, dims_len, type, error_prefix);
294}
295
297
298/* -------------------------------------------------------------------- */
303
304/* array utility function */
305PyObject *PyC_Tuple_PackArray_F32(const float *array, uint len)
306{
307 PyObject *tuple = PyTuple_New(len);
308 for (uint i = 0; i < len; i++) {
309 PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array[i]));
310 }
311 return tuple;
312}
313
314PyObject *PyC_Tuple_PackArray_F64(const double *array, uint len)
315{
316 PyObject *tuple = PyTuple_New(len);
317 for (uint i = 0; i < len; i++) {
318 PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array[i]));
319 }
320 return tuple;
321}
322
323PyObject *PyC_Tuple_PackArray_I32(const int *array, uint len)
324{
325 PyObject *tuple = PyTuple_New(len);
326 for (uint i = 0; i < len; i++) {
327 PyTuple_SET_ITEM(tuple, i, PyLong_FromLong(array[i]));
328 }
329 return tuple;
330}
331
333{
334 PyObject *tuple = PyTuple_New(len);
335 for (uint i = 0; i < len; i++) {
336 PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array[i]));
337 }
338 return tuple;
339}
340
341PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len)
342{
343 PyObject *tuple = PyTuple_New(len);
344 for (uint i = 0; i < len; i++) {
345 PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array[i]));
346 }
347 return tuple;
348}
349
350PyObject *PyC_Tuple_PackArray_String(const char **array, uint len)
351{
352 /* Not part of numeric array packing but useful none the less. */
353 PyObject *tuple = PyTuple_New(len);
354 for (uint i = 0; i < len; i++) {
355 if (PyObject *value = PyUnicode_FromString(array[i])) {
356 PyTuple_SET_ITEM(tuple, i, value);
357 }
358 else {
359 Py_DECREF(tuple);
360 tuple = nullptr;
361 break;
362 }
363 }
364 return tuple;
365}
366
368
369/* -------------------------------------------------------------------- */
372
373static PyObject *PyC_Tuple_PackArray_Multi_F32_impl(const float **array_p,
374 const int dims[],
375 const int dims_len)
376{
377 const int len = dims[0];
378 if (dims_len == 1) {
379 PyObject *tuple = PyC_Tuple_PackArray_F32(*array_p, len);
380 *array_p = (*array_p) + len;
381 return tuple;
382 }
383 PyObject *tuple = PyTuple_New(dims[0]);
384 const int *dims_next = dims + 1;
385 const int dims_next_len = dims_len - 1;
386 for (uint i = 0; i < len; i++) {
387 PyTuple_SET_ITEM(
388 tuple, i, PyC_Tuple_PackArray_Multi_F32_impl(array_p, dims_next, dims_next_len));
389 }
390 return tuple;
391}
392PyObject *PyC_Tuple_PackArray_Multi_F32(const float *array, const int dims[], const int dims_len)
393{
394 return PyC_Tuple_PackArray_Multi_F32_impl(&array, dims, dims_len);
395}
396
397static PyObject *PyC_Tuple_PackArray_Multi_F64_impl(const double **array_p,
398 const int dims[],
399 const int dims_len)
400{
401 const int len = dims[0];
402 if (dims_len == 1) {
403 PyObject *tuple = PyC_Tuple_PackArray_F64(*array_p, len);
404 *array_p = (*array_p) + len;
405 return tuple;
406 }
407 PyObject *tuple = PyTuple_New(dims[0]);
408 const int *dims_next = dims + 1;
409 const int dims_next_len = dims_len - 1;
410 for (uint i = 0; i < len; i++) {
411 PyTuple_SET_ITEM(
412 tuple, i, PyC_Tuple_PackArray_Multi_F64_impl(array_p, dims_next, dims_next_len));
413 }
414 return tuple;
415}
416PyObject *PyC_Tuple_PackArray_Multi_F64(const double *array, const int dims[], const int dims_len)
417{
418 return PyC_Tuple_PackArray_Multi_F64_impl(&array, dims, dims_len);
419}
420
421static PyObject *PyC_Tuple_PackArray_Multi_I32_impl(const int **array_p,
422 const int dims[],
423 const int dims_len)
424{
425 const int len = dims[0];
426 if (dims_len == 1) {
427 PyObject *tuple = PyC_Tuple_PackArray_I32(*array_p, len);
428 *array_p = (*array_p) + len;
429 return tuple;
430 }
431 PyObject *tuple = PyTuple_New(dims[0]);
432 const int *dims_next = dims + 1;
433 const int dims_next_len = dims_len - 1;
434 for (uint i = 0; i < len; i++) {
435 PyTuple_SET_ITEM(
436 tuple, i, PyC_Tuple_PackArray_Multi_I32_impl(array_p, dims_next, dims_next_len));
437 }
438 return tuple;
439}
440PyObject *PyC_Tuple_PackArray_Multi_I32(const int *array, const int dims[], const int dims_len)
441{
442 return PyC_Tuple_PackArray_Multi_I32_impl(&array, dims, dims_len);
443}
444
445static PyObject *PyC_Tuple_PackArray_Multi_Bool_impl(const bool **array_p,
446 const int dims[],
447 const int dims_len)
448{
449 const int len = dims[0];
450 if (dims_len == 1) {
451 PyObject *tuple = PyC_Tuple_PackArray_Bool(*array_p, len);
452 *array_p = (*array_p) + len;
453 return tuple;
454 }
455 PyObject *tuple = PyTuple_New(dims[0]);
456 const int *dims_next = dims + 1;
457 const int dims_next_len = dims_len - 1;
458 for (uint i = 0; i < len; i++) {
459 PyTuple_SET_ITEM(
460 tuple, i, PyC_Tuple_PackArray_Multi_Bool_impl(array_p, dims_next, dims_next_len));
461 }
462 return tuple;
463}
464PyObject *PyC_Tuple_PackArray_Multi_Bool(const bool *array, const int dims[], const int dims_len)
465{
466 return PyC_Tuple_PackArray_Multi_Bool_impl(&array, dims, dims_len);
467}
468
470
471/* -------------------------------------------------------------------- */
474
475void PyC_Tuple_Fill(PyObject *tuple, PyObject *value)
476{
477 const uint tot = PyTuple_GET_SIZE(tuple);
478 uint i;
479
480 for (i = 0; i < tot; i++) {
481 PyTuple_SET_ITEM(tuple, i, value);
482 Py_INCREF(value);
483 }
484}
485
486void PyC_List_Fill(PyObject *list, PyObject *value)
487{
488 const uint tot = PyList_GET_SIZE(list);
489 uint i;
490
491 for (i = 0; i < tot; i++) {
492 PyList_SET_ITEM(list, i, value);
493 Py_INCREF(value);
494 }
495}
496
498
499/* -------------------------------------------------------------------- */
502
503int PyC_ParseBool(PyObject *o, void *p)
504{
505 bool *bool_p = static_cast<bool *>(p);
506 long value;
507 if (((value = PyLong_AsLong(o)) == -1) || !ELEM(value, 0, 1)) {
508 PyErr_Format(PyExc_ValueError, "expected a bool or int (0/1), got %s", Py_TYPE(o)->tp_name);
509 return 0;
510 }
511
512 *bool_p = value ? true : false;
513 return 1;
514}
515
516int PyC_ParseStringEnum(PyObject *o, void *p)
517{
518 PyC_StringEnum *e = static_cast<PyC_StringEnum *>(p);
519 const char *value = PyUnicode_AsUTF8(o);
520 if (value == nullptr) {
521 PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name);
522 return 0;
523 }
524 int i;
525 for (i = 0; e->items[i].id; i++) {
526 if (STREQ(e->items[i].id, value)) {
527 e->value_found = e->items[i].value;
528 return 1;
529 }
530 }
531
532 /* Set as a precaution. */
533 e->value_found = -1;
534
535 PyObject *enum_items = PyTuple_New(i);
536 for (i = 0; e->items[i].id; i++) {
537 PyTuple_SET_ITEM(enum_items, i, PyUnicode_FromString(e->items[i].id));
538 }
539 PyErr_Format(PyExc_ValueError, "expected a string in %S, got '%s'", enum_items, value);
540 Py_DECREF(enum_items);
541 return 0;
542}
543
544const char *PyC_StringEnum_FindIDFromValue(const PyC_StringEnumItems *items, const int value)
545{
546 for (int i = 0; items[i].id; i++) {
547 if (items[i].value == value) {
548 return items[i].id;
549 }
550 }
551 return nullptr;
552}
553
554int PyC_CheckArgs_DeepCopy(PyObject *args)
555{
556 PyObject *dummy_pydict;
557 return PyArg_ParseTuple(args, "|O!:__deepcopy__", &PyDict_Type, &dummy_pydict) != 0;
558}
559
561
562#ifndef MATH_STANDALONE
563
564/* -------------------------------------------------------------------- */
569
570void PyC_ObSpit(const char *name, PyObject *var)
571{
572 const char *null_str = "<null>";
573 fprintf(stderr, "<%s> : ", name);
574 if (var == nullptr) {
575 fprintf(stderr, "%s\n", null_str);
576 }
577 else {
578 PyObject_Print(var, stderr, 0);
579 const PyTypeObject *type = Py_TYPE(var);
580 fprintf(stderr,
581 " ref:%d, ptr:%p, type: %s\n",
582 int(var->ob_refcnt),
583 (void *)var,
584 type ? type->tp_name : null_str);
585 }
586}
587
588void PyC_ObSpitStr(char *result, size_t result_maxncpy, PyObject *var)
589{
590 /* No name, creator of string can manage that. */
591 const char *null_str = "<null>";
592 if (var == nullptr) {
593 BLI_strncpy_utf8(result, null_str, result_maxncpy);
594 }
595 else {
596 const PyTypeObject *type = Py_TYPE(var);
597 PyObject *var_str = PyObject_Repr(var);
598 if (var_str == nullptr) {
599 /* We could print error here,
600 * but this may be used for generating errors - so don't for now. */
601 PyErr_Clear();
602 }
604 result_maxncpy,
605 " ref=%d, ptr=%p, type=%s, value=%.200s",
606 int(var->ob_refcnt),
607 (void *)var,
608 type ? type->tp_name : null_str,
609 var_str ? PyUnicode_AsUTF8(var_str) : "<error>");
610 if (var_str != nullptr) {
611 Py_DECREF(var_str);
612 }
613 }
614}
615
617{
618
619 const char *filename;
620 int lineno;
621
622 /* NOTE: allow calling from outside python (RNA). */
624 fprintf(stderr, "Python line lookup failed, interpreter inactive\n");
625 return;
626 }
627
628 PyErr_Clear();
629 PyC_FileAndNum(&filename, &lineno);
630
631 fprintf(stderr, "%s:%d\n", filename, lineno);
632}
633
635{
636 /* NOTE: allow calling from outside python (RNA). */
638 fprintf(stderr, "Python line lookup failed, interpreter inactive\n");
639 return;
640 }
641
642 /* lame but handy */
643 const PyGILState_STATE gilstate = PyGILState_Ensure();
644 PyRun_SimpleString("__import__('traceback').print_stack()");
645 PyGILState_Release(gilstate);
646}
647
649
650/* -------------------------------------------------------------------- */
653
654void PyC_FileAndNum(const char **r_filename, int *r_lineno)
655{
656 PyFrameObject *frame;
657 PyCodeObject *code;
658
659 if (r_filename) {
660 *r_filename = nullptr;
661 }
662 if (r_lineno) {
663 *r_lineno = -1;
664 }
665
666 if (!(frame = PyEval_GetFrame())) {
667 return;
668 }
669 if (!(code = PyFrame_GetCode(frame))) {
670 return;
671 }
672
673 /* when executing a script */
674 if (r_filename) {
675 *r_filename = PyUnicode_AsUTF8(code->co_filename);
676 }
677
678 /* when executing a module */
679 if (r_filename && *r_filename == nullptr) {
680 /* try an alternative method to get the r_filename - module based
681 * references below are all borrowed (double checked) */
682 PyObject *mod_name = PyDict_GetItemString(PyEval_GetGlobals(), "__name__");
683 if (mod_name) {
684 PyObject *mod = PyDict_GetItem(PyImport_GetModuleDict(), mod_name);
685 if (mod) {
686 PyObject *mod_file = PyModule_GetFilenameObject(mod);
687 if (mod_file) {
688 *r_filename = PyUnicode_AsUTF8(mod_name);
689 Py_DECREF(mod_file);
690 }
691 else {
692 PyErr_Clear();
693 }
694 }
695
696 /* unlikely, fallback */
697 if (*r_filename == nullptr) {
698 *r_filename = PyUnicode_AsUTF8(mod_name);
699 }
700 }
701 }
702
703 if (r_lineno) {
704 *r_lineno = PyFrame_GetLineNumber(frame);
705 }
706}
707
708void PyC_FileAndNum_Safe(const char **r_filename, int *r_lineno)
709{
711 return;
712 }
713
714 PyC_FileAndNum(r_filename, r_lineno);
715}
716
718
719/* -------------------------------------------------------------------- */
722
723PyObject *PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
724{
725 /* NOTE: Would be nice if python had this built in. */
726
727 Py_ssize_t i;
728 PyObject *item = o;
729 const char *attr;
730
731 va_list vargs;
732
733 va_start(vargs, n);
734 for (i = 0; i < n; i++) {
735 attr = va_arg(vargs, char *);
736 item = PyObject_GetAttrString(item, attr);
737
738 if (item) {
739 Py_DECREF(item);
740 }
741 else {
742 /* python will set the error value here */
743 break;
744 }
745 }
746 va_end(vargs);
747
748 Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */
749 return item;
750}
751
753
754/* -------------------------------------------------------------------- */
757
758PyObject *PyC_FrozenSetFromStrings(const char **strings)
759{
760 const char **str;
761 PyObject *ret;
762
763 ret = PyFrozenSet_New(nullptr);
764
765 for (str = strings; *str; str++) {
766 PyObject *py_str = PyUnicode_FromString(*str);
767 PySet_Add(ret, py_str);
768 Py_DECREF(py_str);
769 }
770
771 return ret;
772}
773
775
776/* -------------------------------------------------------------------- */
779
780PyObject *PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...)
781{
782 PyObject *error_value_as_unicode = nullptr;
783
784 if (PyErr_Occurred()) {
785 PyObject *error_type, *error_value, *error_traceback;
786 PyErr_Fetch(&error_type, &error_value, &error_traceback);
787
788 if (PyUnicode_Check(error_value)) {
789 error_value_as_unicode = error_value;
790 Py_INCREF(error_value_as_unicode);
791 }
792 else {
793 error_value_as_unicode = PyUnicode_FromFormat(
794 "%.200s(%S)", Py_TYPE(error_value)->tp_name, error_value);
795 }
796 PyErr_Restore(error_type, error_value, error_traceback);
797 }
798
799 va_list args;
800
801 va_start(args, format);
802 PyObject *error_value_format = PyUnicode_FromFormatV(format, args); /* Can fail and be null. */
803 va_end(args);
804
805 if (error_value_as_unicode) {
806 if (error_value_format) {
807 PyObject *error_value_format_prev = error_value_format;
808 error_value_format = PyUnicode_FromFormat(
809 "%S, %S", error_value_format, error_value_as_unicode);
810 Py_DECREF(error_value_format_prev);
811 }
812 else {
813 /* Should never happen, hints at incorrect API use or memory corruption. */
814 error_value_format = PyUnicode_FromFormat("(internal error), %S", error_value_as_unicode);
815 }
816 Py_DECREF(error_value_as_unicode);
817 }
818
819 PyErr_SetObject(exception_type_prefix, error_value_format);
820 Py_XDECREF(error_value_format);
821
822 /* Strange to always return null, matches #PyErr_Format. */
823 return nullptr;
824}
825
826PyObject *PyC_Err_SetString_Prefix(PyObject *exception_type_prefix, const char *str)
827{
828 return PyC_Err_Format_Prefix(exception_type_prefix, "%s", str);
829}
830
831void PyC_Err_PrintWithFunc(PyObject *py_func)
832{
833 /* since we return to C code we can't leave the error */
834 PyCodeObject *f_code = (PyCodeObject *)PyFunction_GET_CODE(py_func);
835 PyErr_Print();
836
837 /* use py style error */
838 fprintf(stderr,
839 "File \"%s\", line %d, in %s\n",
840 PyUnicode_AsUTF8(f_code->co_filename),
841 f_code->co_firstlineno,
842 PyUnicode_AsUTF8(((PyFunctionObject *)py_func)->func_name));
843}
844
846
847/* -------------------------------------------------------------------- */
850
868{
869 if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {
870 return;
871 }
872/* Inspecting, follow Python's logic in #_Py_HandleSystemExit & treat as a regular exception. */
873# if 0 /* FIXME: */
874 if (_Py_GetConfig()->inspect) {
875 return;
876 }
877# endif
878
879 /* NOTE(@ideasman42): A `SystemExit` exception will exit immediately (unless inspecting).
880 * So print the error and exit now. Without this #PyErr_Display shows the error stack-trace
881 * as a regular exception (as if something went wrong) and fail to exit.
882 * see: #99966 for additional context.
883 *
884 * Arguably accessing a `SystemExit` exception as a buffer should be supported without exiting.
885 * (by temporarily enabling inspection for example) however - it's not obvious exactly when this
886 * should be enabled and complicates the Python API by introducing different kinds of execution.
887 * Since the rule of thumb is for Blender's embedded Python to match stand-alone Python,
888 * favor exiting when a `SystemExit` is raised.
889 * Especially since this exception more likely to be used for background/batch-processing
890 * utilities where exiting immediately makes sense, the possibility of this being called
891 * indirectly from python-drivers or modal-operators is less of a concern. */
892 PyErr_Print();
893}
894
896{
897 BLI_assert(PyErr_Occurred());
898
900
901 /* The resulting exception as a string (return value). */
902 PyObject *result = nullptr;
903
904 PyObject *error_type, *error_value, *error_traceback;
905 PyErr_Fetch(&error_type, &error_value, &error_traceback);
906
907 /* Normalizing is needed because it's possible the error value is a string which
908 * #PyErr_Display will fail to print. */
909 PyErr_NormalizeException(&error_type, &error_value, &error_traceback);
910
911 /* `io.StringIO()`. */
912 PyObject *string_io = nullptr;
913 PyObject *string_io_mod = nullptr;
914 PyObject *string_io_getvalue = nullptr;
915 if ((string_io_mod = PyImport_ImportModule("io")) &&
916 (string_io = PyObject_CallMethod(string_io_mod, "StringIO", nullptr)) &&
917 (string_io_getvalue = PyObject_GetAttrString(string_io, "getvalue")))
918 {
919 PyObject *stderr_backup = PySys_GetObject("stderr"); /* Borrowed. */
920 /* Since these were borrowed we don't want them freed when replaced. */
921 Py_INCREF(stderr_backup);
922 PySys_SetObject("stderr", string_io); /* Freed when overwriting. */
923
924 PyErr_Display(error_type, error_value, error_traceback);
925
926 result = PyObject_CallObject(string_io_getvalue, nullptr);
927 PySys_SetObject("stderr", stderr_backup);
928 Py_DECREF(stderr_backup); /* Now `sys` owns the reference again. */
929 }
930 else {
931 PySys_WriteStderr("Internal error creating: io.StringIO()!\n");
932 if (UNLIKELY(PyErr_Occurred())) {
933 PyErr_Print(); /* Show the error accessing `io.StringIO`. */
934 }
935 PyErr_Display(error_type, error_value, error_traceback);
936 }
937
938 Py_XDECREF(string_io_mod);
939 Py_XDECREF(string_io_getvalue);
940 Py_XDECREF(string_io); /* Free the original reference. */
941
942 if (result == nullptr) {
943 result = PyObject_Str(error_value);
944 /* Python does this too. */
945 if (UNLIKELY(result == nullptr)) {
946 result = PyUnicode_FromFormat("<unprintable %s object>", Py_TYPE(error_value)->tp_name);
947 }
948 }
949
950 PyErr_Restore(error_type, error_value, error_traceback);
951
952 return result;
953}
954
956{
957 BLI_assert(PyErr_Occurred());
958
960
961 /* The resulting exception as a string (return value). */
962 PyObject *result = nullptr;
963
964 PyObject *error_type, *error_value, *error_traceback;
965
966 PyErr_Fetch(&error_type, &error_value, &error_traceback);
967
968 if (PyErr_GivenExceptionMatches(error_type, PyExc_SyntaxError)) {
969 /* Special exception for syntax errors,
970 * in these cases the full error is verbose and not very useful,
971 * just use the initial text so we know what the error is. */
972 if (PyTuple_CheckExact(error_value) && PyTuple_GET_SIZE(error_value) >= 1) {
973 result = PyObject_Str(PyTuple_GET_ITEM(error_value, 0));
974 }
975 }
976
977 if (result == nullptr) {
978 result = PyObject_Str(error_value);
979 /* Python does this too. */
980 if (UNLIKELY(result == nullptr)) {
981 result = PyUnicode_FromFormat("<unprintable %s object>", Py_TYPE(error_value)->tp_name);
982 }
983 }
984
985 PyErr_Restore(error_type, error_value, error_traceback);
986
987 return result;
988}
989
991
992/* -------------------------------------------------------------------- */
997
998const char *PyC_UnicodeAsBytesAndSize(PyObject *py_str, Py_ssize_t *r_size, PyObject **r_coerce)
999{
1000 const char *result;
1001
1002 result = PyUnicode_AsUTF8AndSize(py_str, r_size);
1003
1004 if (result) {
1005 /* 99% of the time this is enough but we better support non unicode
1006 * chars since blender doesn't limit this */
1007 return result;
1008 }
1009
1010 PyErr_Clear();
1011
1012 if (PyBytes_Check(py_str)) {
1013 *r_size = PyBytes_GET_SIZE(py_str);
1014 return PyBytes_AS_STRING(py_str);
1015 }
1016 if ((*r_coerce = PyUnicode_EncodeFSDefault(py_str))) {
1017 *r_size = PyBytes_GET_SIZE(*r_coerce);
1018 return PyBytes_AS_STRING(*r_coerce);
1019 }
1020
1021 /* leave error raised from EncodeFS */
1022 return nullptr;
1023}
1024
1025const char *PyC_UnicodeAsBytes(PyObject *py_str, PyObject **r_coerce)
1026{
1027 const char *result;
1028
1029 result = PyUnicode_AsUTF8(py_str);
1030
1031 if (result) {
1032 /* 99% of the time this is enough but we better support non unicode
1033 * chars since blender doesn't limit this. */
1034 return result;
1035 }
1036
1037 PyErr_Clear();
1038
1039 if (PyBytes_Check(py_str)) {
1040 return PyBytes_AS_STRING(py_str);
1041 }
1042 if ((*r_coerce = PyUnicode_EncodeFSDefault(py_str))) {
1043 return PyBytes_AS_STRING(*r_coerce);
1044 }
1045
1046 /* leave error raised from EncodeFS */
1047 return nullptr;
1048}
1049
1050PyObject *PyC_UnicodeFromBytesAndSize(const char *str, Py_ssize_t size)
1051{
1052 PyObject *result = PyUnicode_FromStringAndSize(str, size);
1053 if (result) {
1054 /* 99% of the time this is enough but we better support non unicode
1055 * chars since blender doesn't limit this */
1056 return result;
1057 }
1058
1059 PyErr_Clear();
1060 /* this means paths will always be accessible once converted, on all OS's */
1061 result = PyUnicode_DecodeFSDefaultAndSize(str, size);
1062 return result;
1063}
1064
1065PyObject *PyC_UnicodeFromBytes(const char *str)
1066{
1067 return PyC_UnicodeFromBytesAndSize(str, strlen(str));
1068}
1069
1070PyObject *PyC_UnicodeFromStdStr(const std::string &str)
1071{
1072 return PyC_UnicodeFromBytesAndSize(str.c_str(), str.length());
1073}
1074
1075int PyC_ParseUnicodeAsBytesAndSize(PyObject *o, void *p)
1076{
1078 if (UNLIKELY(o == nullptr)) {
1079 /* Signal to cleanup. */
1080 Py_CLEAR(data->value_coerce);
1081 return 1;
1082 }
1083 /* The value must be cleared. */
1084 BLI_assert(!(data->value_coerce || data->value || data->value_len));
1085 data->value = PyC_UnicodeAsBytesAndSize(o, &data->value_len, &data->value_coerce);
1086 if (data->value == nullptr) {
1087 /* Leave the error as-is. */
1088 return 0;
1089 }
1090 /* Needed to #Py_DECREF `data->value_coerce` on future failure. */
1091 return data->value_coerce ? Py_CLEANUP_SUPPORTED : 1;
1092}
1093
1095{
1096 if (o == Py_None) {
1098 BLI_assert(!(data->value_coerce || data->value || data->value_len));
1100 return 1;
1101 }
1102 return PyC_ParseUnicodeAsBytesAndSize(o, p);
1103}
1104
1106
1107/* -------------------------------------------------------------------- */
1110
1111PyObject *PyC_DefaultNameSpace(const char *filename)
1112{
1113 PyObject *modules = PyImport_GetModuleDict();
1114 PyObject *builtins = PyEval_GetBuiltins();
1115 PyObject *mod_main = PyModule_New("__main__");
1116 PyDict_SetItemString(modules, "__main__", mod_main);
1117 Py_DECREF(mod_main); /* `sys.modules` owns now. */
1118 PyModule_AddStringConstant(mod_main, "__name__", "__main__");
1119
1120 /* This won't map to a real file when executing text-blocks and buttons.
1121 * In this case an identifier is typically used that is surrounded by angle-brackets.
1122 * It's mainly helpful for the UI and messages to show *something*. */
1123 PyModule_AddObject(mod_main, "__file__", PyC_UnicodeFromBytes(filename));
1124 PyModule_AddObjectRef(mod_main, "__builtins__", builtins);
1125
1126 return PyModule_GetDict(mod_main);
1127}
1128
1129bool PyC_NameSpace_ImportArray(PyObject *py_dict, const char *imports[])
1130{
1131 for (int i = 0; imports[i]; i++) {
1132 PyObject *name = PyUnicode_FromString(imports[i]);
1133 PyObject *mod = PyImport_ImportModuleLevelObject(name, nullptr, nullptr, nullptr, 0);
1134 bool ok = false;
1135 if (mod) {
1136 PyDict_SetItem(py_dict, name, mod);
1137 ok = true;
1138 Py_DECREF(mod);
1139 }
1140 Py_DECREF(name);
1141
1142 if (!ok) {
1143 return false;
1144 }
1145 }
1146 return true;
1147}
1148
1150{
1151 PyObject *modules = PyImport_GetModuleDict();
1152 PyObject *main_mod = PyDict_GetItemString(modules, "__main__");
1153 if (main_mod) {
1154 /* Ensure the backed up module is kept until it's ownership */
1155 /* is transferred back to `sys.modules`. */
1156 Py_INCREF(main_mod);
1157 }
1158 return main_mod;
1159}
1160
1161void PyC_MainModule_Restore(PyObject *main_mod)
1162{
1163 PyObject *modules = PyImport_GetModuleDict();
1164 if (main_mod) {
1165 PyDict_SetItemString(modules, "__main__", main_mod);
1166 Py_DECREF(main_mod);
1167 }
1168 else {
1169 PyDict_DelItemString(modules, "__main__");
1170 }
1171}
1172
1174{
1175 /* instead of PyThreadState_Get, which calls Py_FatalError */
1176 return (PyThreadState_GetDict() != nullptr);
1177}
1178
1180
1181/* -------------------------------------------------------------------- */
1184
1185void PyC_RunQuicky(const char *filepath, int n, ...)
1186{
1187 /* NOTE: Would be nice if python had this built in
1188 * See: https://developer.blender.org/docs/handbook/tooling/pyfromc/ */
1189
1190 FILE *fp = fopen(filepath, "r");
1191
1192 if (fp) {
1193 const PyGILState_STATE gilstate = PyGILState_Ensure();
1194
1195 va_list vargs;
1196
1197 Py_ssize_t *sizes = static_cast<Py_ssize_t *>(PyMem_MALLOC(sizeof(*sizes) * (n / 2)));
1198 int i;
1199
1200 PyObject *py_dict = PyC_DefaultNameSpace(filepath);
1201 PyObject *values = PyList_New(n / 2); /* namespace owns this, don't free */
1202
1203 PyObject *py_result, *ret;
1204
1205 PyObject *struct_mod = PyImport_ImportModule("struct");
1206 PyObject *calcsize = PyObject_GetAttrString(struct_mod, "calcsize"); /* struct.calcsize */
1207 PyObject *pack = PyObject_GetAttrString(struct_mod, "pack"); /* struct.pack */
1208 PyObject *unpack = PyObject_GetAttrString(struct_mod, "unpack"); /* struct.unpack */
1209
1210 Py_DECREF(struct_mod);
1211
1212 va_start(vargs, n);
1213 for (i = 0; i * 2 < n; i++) {
1214 const char *format = va_arg(vargs, char *);
1215 void *ptr = va_arg(vargs, void *);
1216
1217 ret = PyObject_CallFunction(calcsize, "s", format);
1218
1219 if (ret) {
1220 sizes[i] = PyLong_AsLong(ret);
1221 Py_DECREF(ret);
1222 ret = PyObject_CallFunction(unpack, "sy#", format, (char *)ptr, sizes[i]);
1223 }
1224
1225 if (ret == nullptr) {
1226 printf("%s error, line:%d\n", __func__, __LINE__);
1227 PyErr_Print();
1228
1229 PyList_SET_ITEM(values, i, Py_NewRef(Py_None)); /* hold user */
1230
1231 sizes[i] = 0;
1232 }
1233 else {
1234 if (PyTuple_GET_SIZE(ret) == 1) {
1235 /* convenience, convert single tuples into single values */
1236 PyObject *tmp = PyTuple_GET_ITEM(ret, 0);
1237 Py_INCREF(tmp);
1238 Py_DECREF(ret);
1239 ret = tmp;
1240 }
1241
1242 PyList_SET_ITEM(values, i, ret); /* hold user */
1243 }
1244 }
1245 va_end(vargs);
1246
1247 /* set the value so we can access it */
1248 PyDict_SetItemString(py_dict, "values", values);
1249 Py_DECREF(values);
1250
1251 py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict);
1252
1253 fclose(fp);
1254
1255 if (py_result) {
1256
1257 /* we could skip this but then only slice assignment would work
1258 * better not be so strict */
1259 values = PyDict_GetItemString(py_dict, "values");
1260
1261 if (values && PyList_Check(values)) {
1262
1263 /* don't use the result */
1264 Py_DECREF(py_result);
1265 py_result = nullptr;
1266
1267 /* now get the values back */
1268 va_start(vargs, n);
1269 for (i = 0; i * 2 < n; i++) {
1270 const char *format = va_arg(vargs, char *);
1271 void *ptr = va_arg(vargs, void *);
1272
1273 PyObject *item;
1274 PyObject *item_new;
1275 /* prepend the string formatting and remake the tuple */
1276 item = PyList_GET_ITEM(values, i);
1277 if (PyTuple_CheckExact(item)) {
1278 int ofs = PyTuple_GET_SIZE(item);
1279 item_new = PyTuple_New(ofs + 1);
1280 while (ofs--) {
1281 PyObject *member = PyTuple_GET_ITEM(item, ofs);
1282 PyTuple_SET_ITEM(item_new, ofs + 1, member);
1283 Py_INCREF(member);
1284 }
1285
1286 PyTuple_SET_ITEM(item_new, 0, PyUnicode_FromString(format));
1287 }
1288 else {
1289 item_new = Py_BuildValue("sO", format, item);
1290 }
1291
1292 ret = PyObject_Call(pack, item_new, nullptr);
1293
1294 if (ret) {
1295 /* copy the bytes back into memory */
1296 memcpy(ptr, PyBytes_AS_STRING(ret), sizes[i]);
1297 Py_DECREF(ret);
1298 }
1299 else {
1300 printf("%s error on arg '%d', line:%d\n", __func__, i, __LINE__);
1301 PyC_ObSpit("failed converting:", item_new);
1302 PyErr_Print();
1303 }
1304
1305 Py_DECREF(item_new);
1306 }
1307 va_end(vargs);
1308 }
1309 else {
1310 printf("%s error, 'values' not a list, line:%d\n", __func__, __LINE__);
1311 }
1312 }
1313 else {
1314 printf("%s error line:%d\n", __func__, __LINE__);
1315 PyErr_Print();
1316 }
1317
1318 Py_DECREF(calcsize);
1319 Py_DECREF(pack);
1320 Py_DECREF(unpack);
1321
1322 PyMem_FREE(sizes);
1323
1324 PyGILState_Release(gilstate);
1325 }
1326 else {
1327 fprintf(stderr, "%s: '%s' missing\n", __func__, filepath);
1328 }
1329}
1330
1331void *PyC_RNA_AsPointer(PyObject *value, const char *type_name)
1332{
1333 PyObject *as_pointer;
1334 PyObject *pointer;
1335
1336 if (STREQ(Py_TYPE(value)->tp_name, type_name) &&
1337 (as_pointer = PyObject_GetAttrString(value, "as_pointer")) != nullptr &&
1338 PyCallable_Check(as_pointer))
1339 {
1340 void *result = nullptr;
1341
1342 /* must be a 'type_name' object */
1343 pointer = PyObject_CallObject(as_pointer, nullptr);
1344 Py_DECREF(as_pointer);
1345
1346 if (!pointer) {
1347 PyErr_SetString(PyExc_SystemError, "value.as_pointer() failed");
1348 return nullptr;
1349 }
1350 result = PyLong_AsVoidPtr(pointer);
1351 Py_DECREF(pointer);
1352 if (!result) {
1353 PyErr_SetString(PyExc_SystemError, "value.as_pointer() failed");
1354 }
1355
1356 return result;
1357 }
1358
1359 PyErr_Format(PyExc_TypeError,
1360 "expected '%.200s' type found '%.200s' instead",
1361 type_name,
1362 Py_TYPE(value)->tp_name);
1363 return nullptr;
1364}
1365
1367
1368/* -------------------------------------------------------------------- */
1373
1374PyObject *PyC_FlagSet_AsString(const PyC_FlagSet *item)
1375{
1376 PyObject *py_items = PyList_New(0);
1377 for (; item->identifier; item++) {
1378 PyList_APPEND(py_items, PyUnicode_FromString(item->identifier));
1379 }
1380 PyObject *py_string = PyObject_Repr(py_items);
1381 Py_DECREF(py_items);
1382 return py_string;
1383}
1384
1385int PyC_FlagSet_ValueFromID_int(const PyC_FlagSet *item, const char *identifier, int *r_value)
1386{
1387 for (; item->identifier; item++) {
1388 if (STREQ(item->identifier, identifier)) {
1389 *r_value = item->value;
1390 return 1;
1391 }
1392 }
1393
1394 return 0;
1395}
1396
1398 const char *identifier,
1399 int *r_value,
1400 const char *error_prefix)
1401{
1402 if (PyC_FlagSet_ValueFromID_int(item, identifier, r_value) == 0) {
1403 PyObject *enum_str = PyC_FlagSet_AsString(item);
1404 PyErr_Format(
1405 PyExc_ValueError, "%s: '%.200s' not found in (%U)", error_prefix, identifier, enum_str);
1406 Py_DECREF(enum_str);
1407 return -1;
1408 }
1409
1410 return 0;
1411}
1412
1414 PyObject *value,
1415 int *r_value,
1416 const char *error_prefix)
1417{
1418 /* set of enum items, concatenate all values with OR */
1419 int ret, flag = 0;
1420
1421 if (!PySet_Check(value)) {
1422 PyErr_Format(PyExc_TypeError,
1423 "%.200s expected a set, not %.200s",
1424 error_prefix,
1425 Py_TYPE(value)->tp_name);
1426 return -1;
1427 }
1428
1429 *r_value = 0;
1430
1431 if (PySet_GET_SIZE(value) > 0) {
1432 PyObject *it = PyObject_GetIter(value);
1433 PyObject *key;
1434 while ((key = PyIter_Next(it))) {
1435 /* Borrow from the set. */
1436 Py_DECREF(key);
1437
1438 const char *param = PyUnicode_AsUTF8(key);
1439 if (param == nullptr) {
1440 PyErr_Format(PyExc_TypeError,
1441 "%.200s set must contain strings, not %.200s",
1442 error_prefix,
1443 Py_TYPE(key)->tp_name);
1444 break;
1445 }
1446
1447 if (PyC_FlagSet_ValueFromID(items, param, &ret, error_prefix) < 0) {
1448 break;
1449 }
1450
1451 flag |= ret;
1452 }
1453 Py_DECREF(it);
1454 if (key != nullptr) {
1455 return -1;
1456 }
1457 }
1458
1459 *r_value = flag;
1460 return 0;
1461}
1462
1464{
1465 PyObject *ret = PySet_New(nullptr);
1466 PyObject *pystr;
1467
1468 for (; items->identifier; items++) {
1469 if (items->value & flag) {
1470 pystr = PyUnicode_FromString(items->identifier);
1471 PySet_Add(ret, pystr);
1472 Py_DECREF(pystr);
1473 }
1474 }
1475
1476 return ret;
1477}
1478
1480
1481/* -------------------------------------------------------------------- */
1484
1485[[nodiscard]] static PyObject *pyc_run_string_as_py_object(const char *imports[],
1486 const char *imports_star[],
1487 const char *expr,
1488 const char *filename)
1489 ATTR_NONNULL(3, 4);
1490static PyObject *pyc_run_string_as_py_object(const char *imports[],
1491 const char *imports_star[],
1492 const char *expr,
1493 const char *filename)
1494{
1495 PyObject *main_mod = PyC_MainModule_Backup();
1496
1497 PyObject *py_dict = PyC_DefaultNameSpace(filename);
1498
1499 if (imports_star) {
1500 for (int i = 0; imports_star[i]; i++) {
1501 PyObject *mod = PyImport_ImportModule("math");
1502 if (mod) {
1503 /* Don't overwrite existing values (override=0). */
1504 PyDict_Merge(py_dict, PyModule_GetDict(mod), 0);
1505 Py_DECREF(mod);
1506 }
1507 else { /* Highly unlikely but possibly. */
1508 PyErr_Print();
1509 }
1510 }
1511 }
1512
1513 PyObject *retval;
1514 if (imports && !PyC_NameSpace_ImportArray(py_dict, imports)) {
1515 retval = nullptr; /* Failure. */
1516 }
1517 else {
1518 retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
1519 }
1520
1521 PyC_MainModule_Restore(main_mod);
1522
1523 return retval;
1524}
1525
1526bool PyC_RunString_AsNumber(const char *imports[],
1527 const char *expr,
1528 const char *filename,
1529 double *r_value)
1530{
1531 int ok = -1;
1532 const char *imports_star[] = {"math", nullptr};
1533 if (PyObject *retval = pyc_run_string_as_py_object(imports, imports_star, expr, filename)) {
1534 double val;
1535
1536 if (PyTuple_Check(retval)) {
1537 /* Users my have typed in `10km, 2m`, accumulate all values. */
1538 val = 0.0;
1539 for (int i = 0; i < PyTuple_GET_SIZE(retval); i++) {
1540 const double val_item = PyFloat_AsDouble(PyTuple_GET_ITEM(retval, i));
1541 if (val_item == -1 && PyErr_Occurred()) {
1542 val = -1;
1543 break;
1544 }
1545 val += val_item;
1546 }
1547 }
1548 else {
1549 val = PyFloat_AsDouble(retval);
1550 }
1551 Py_DECREF(retval);
1552
1553 if (val == -1 && PyErr_Occurred()) {
1554 ok = false;
1555 }
1556 else if (!isfinite(val)) {
1557 *r_value = 0.0;
1558 ok = true;
1559 }
1560 else {
1561 *r_value = val;
1562 ok = true;
1563 }
1564 }
1565 else {
1566 ok = false;
1567 }
1568 BLI_assert(ok != -1);
1569 return bool(ok);
1570}
1571
1572bool PyC_RunString_AsIntPtr(const char *imports[],
1573 const char *expr,
1574 const char *filename,
1575 intptr_t *r_value)
1576{
1577 int ok = -1;
1578 if (PyObject *retval = pyc_run_string_as_py_object(imports, nullptr, expr, filename)) {
1579 const intptr_t val = intptr_t(PyLong_AsVoidPtr(retval));
1580 if (val == 0 && PyErr_Occurred()) {
1581 ok = false;
1582 }
1583 else {
1584 *r_value = val;
1585 ok = true;
1586 }
1587
1588 Py_DECREF(retval);
1589 }
1590 else {
1591 ok = false;
1592 }
1593 BLI_assert(ok != -1);
1594 return ok;
1595}
1596
1597bool PyC_RunString_AsStringAndSize(const char *imports[],
1598 const char *expr,
1599 const char *filename,
1600 char **r_value,
1601 size_t *r_value_size)
1602{
1603 int ok = -1;
1604 if (PyObject *retval = pyc_run_string_as_py_object(imports, nullptr, expr, filename)) {
1605 Py_ssize_t val_len;
1606 const char *val = PyUnicode_AsUTF8AndSize(retval, &val_len);
1607 if (val == nullptr && PyErr_Occurred()) {
1608 ok = false;
1609 }
1610 else {
1611 char *val_alloc = MEM_malloc_arrayN<char>(size_t(val_len) + 1, __func__);
1612 memcpy(val_alloc, val, (size_t(val_len) + 1) * sizeof(*val_alloc));
1613 *r_value = val_alloc;
1614 *r_value_size = val_len;
1615 ok = true;
1616 }
1617 Py_DECREF(retval);
1618 }
1619 else {
1620 ok = false;
1621 }
1622 BLI_assert(ok != -1);
1623 return ok;
1624}
1625
1626bool PyC_RunString_AsString(const char *imports[],
1627 const char *expr,
1628 const char *filename,
1629 char **r_value)
1630{
1631 size_t value_size;
1632 return PyC_RunString_AsStringAndSize(imports, expr, filename, r_value, &value_size);
1633}
1634
1635bool PyC_RunString_AsStringAndSizeOrNone(const char *imports[],
1636 const char *expr,
1637 const char *filename,
1638 char **r_value,
1639 size_t *r_value_size)
1640{
1641 int ok = -1;
1642 if (PyObject *retval = pyc_run_string_as_py_object(imports, nullptr, expr, filename)) {
1643 if (retval == Py_None) {
1644 *r_value = nullptr;
1645 *r_value_size = 0;
1646 ok = true;
1647 }
1648 else {
1649 Py_ssize_t val_len;
1650 const char *val = PyUnicode_AsUTF8AndSize(retval, &val_len);
1651 if (val == nullptr && PyErr_Occurred()) {
1652 ok = false;
1653 }
1654 else {
1655 char *val_alloc = MEM_malloc_arrayN<char>(size_t(val_len) + 1, __func__);
1656 memcpy(val_alloc, val, (size_t(val_len) + 1) * sizeof(val_alloc));
1657 *r_value = val_alloc;
1658 *r_value_size = val_len;
1659 ok = true;
1660 }
1661 }
1662 Py_DECREF(retval);
1663 }
1664 else {
1665 ok = false;
1666 }
1667 BLI_assert(ok != -1);
1668 return bool(ok);
1669}
1670
1671bool PyC_RunString_AsStringOrNone(const char *imports[],
1672 const char *expr,
1673 const char *filename,
1674 char **r_value)
1675{
1676 size_t value_size;
1677 return PyC_RunString_AsStringAndSizeOrNone(imports, expr, filename, r_value, &value_size);
1678}
1679
1681
1682#endif /* #ifndef MATH_STANDALONE */
1683
1684/* -------------------------------------------------------------------- */
1688
1690{
1691 /* This is ported from CPython's internal #flush_std_files (2025-03-31). The code is a bit
1692 * different because the original code uses some internal APIs.
1693 *
1694 * This is approximately equivalent to:
1695 * \code{.py}
1696 * try:
1697 * sys.stdout.flush()
1698 * sys.stderr.flush()
1699 * except Exception:
1700 * pass
1701 * \endcode
1702 */
1703 PyObject *py_flush = PyUnicode_FromString("flush");
1704 BLI_assert(py_flush);
1705 for (const char *name : {"stdout", "stderr"}) {
1706 PyObject *py_file = PySys_GetObject(name);
1707 if (!py_file) {
1708 PyErr_Clear();
1709 continue;
1710 }
1711 PyObject *py_flush_retval = PyObject_CallMethodNoArgs(py_file, py_flush);
1712 if (py_flush_retval) {
1713 Py_DECREF(py_flush_retval);
1714 }
1715 else {
1716 PyErr_Clear();
1717 }
1718 }
1719 Py_DECREF(py_flush);
1720}
1721
1723
1724/* -------------------------------------------------------------------- */
1730
1731/* Compiler optimizes out redundant checks. */
1732#if defined(__GNUC__) && !defined(__clang__)
1733# pragma GCC diagnostic push
1734# pragma GCC diagnostic ignored "-Wtype-limits"
1735
1736#endif
1737
1738/* #PyLong_AsUnsignedLong, unlike #PyLong_AsLong, does not fall back to calling #PyNumber_Index
1739 * when its argument is not a `PyLongObject` instance. To match parsing signed integer types with
1740 * #PyLong_AsLong, this function performs the #PyNumber_Index fallback, if necessary, before
1741 * calling #PyLong_AsUnsignedLong. */
1742static ulong pyc_Long_AsUnsignedLong(PyObject *value)
1743{
1744 if (value == nullptr) {
1745 /* Let PyLong_AsUnsignedLong handle error raising. */
1746 return PyLong_AsUnsignedLong(value);
1747 }
1748
1749 if (PyLong_Check(value)) {
1750 return PyLong_AsUnsignedLong(value);
1751 }
1752
1753 /* Call `__index__` like PyLong_AsLong. */
1754 PyObject *value_converted = PyNumber_Index(value);
1755 if (value_converted == nullptr) {
1756 /* A `TypeError` will have been raised. */
1757 return ulong(-1);
1758 }
1759 ulong to_return = PyLong_AsUnsignedLong(value_converted);
1760 Py_DECREF(value_converted);
1761 return to_return;
1762}
1763
1764int PyC_Long_AsBool(PyObject *value)
1765{
1766 const int test = PyLong_AsInt(value);
1767 if (UNLIKELY(test == -1 && PyErr_Occurred())) {
1768 return -1;
1769 }
1770 if (UNLIKELY(uint(test) > 1)) {
1771 PyErr_SetString(PyExc_TypeError, "Python number not a bool (0/1)");
1772 return -1;
1773 }
1774 return test;
1775}
1776
1777int8_t PyC_Long_AsI8(PyObject *value)
1778{
1779 const int test = PyLong_AsInt(value);
1780 if (UNLIKELY(test == -1 && PyErr_Occurred())) {
1781 return -1;
1782 }
1783 if (UNLIKELY(test < INT8_MIN || test > INT8_MAX)) {
1784 PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C int8");
1785 return -1;
1786 }
1787 return int8_t(test);
1788}
1789
1790int16_t PyC_Long_AsI16(PyObject *value)
1791{
1792 const int test = PyLong_AsInt(value);
1793 if (UNLIKELY(test == -1 && PyErr_Occurred())) {
1794 return -1;
1795 }
1796 if (UNLIKELY(test < INT16_MIN || test > INT16_MAX)) {
1797 PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C int16");
1798 return -1;
1799 }
1800 return int16_t(test);
1801}
1802
1803/* Inlined in header:
1804 * PyC_Long_AsI32
1805 * PyC_Long_AsI64
1806 */
1807
1808uint8_t PyC_Long_AsU8(PyObject *value)
1809{
1810 const ulong test = pyc_Long_AsUnsignedLong(value);
1811 if (UNLIKELY(test == ulong(-1) && PyErr_Occurred())) {
1812 return uint8_t(-1);
1813 }
1814 if (UNLIKELY(test > UINT8_MAX)) {
1815 PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C uint8");
1816 return uint8_t(-1);
1817 }
1818 return uint8_t(test);
1819}
1820
1821uint16_t PyC_Long_AsU16(PyObject *value)
1822{
1823 const ulong test = pyc_Long_AsUnsignedLong(value);
1824 if (UNLIKELY(test == ulong(-1) && PyErr_Occurred())) {
1825 return uint16_t(-1);
1826 }
1827 if (UNLIKELY(test > UINT16_MAX)) {
1828 PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C uint16");
1829 return uint16_t(-1);
1830 }
1831 return uint16_t(test);
1832}
1833
1834uint32_t PyC_Long_AsU32(PyObject *value)
1835{
1836 const ulong test = pyc_Long_AsUnsignedLong(value);
1837 if (UNLIKELY(test == ulong(-1) && PyErr_Occurred())) {
1838 return uint32_t(-1);
1839 }
1840 if (UNLIKELY(test > UINT32_MAX)) {
1841 PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C uint32");
1842 return uint32_t(-1);
1843 }
1844 return uint32_t(test);
1845}
1846
1847uint64_t PyC_Long_AsU64(PyObject *value)
1848{
1849 if (value == nullptr) {
1850 /* Let PyLong_AsUnsignedLongLong handle error raising. */
1851 return uint64_t(PyLong_AsUnsignedLongLong(value));
1852 }
1853
1854 if (PyLong_Check(value)) {
1855 return uint64_t(PyLong_AsUnsignedLongLong(value));
1856 }
1857
1858 /* Call `__index__` like PyLong_AsLongLong. */
1859 PyObject *value_converted = PyNumber_Index(value);
1860 if (value_converted == nullptr) {
1861 /* A `TypeError` will have been raised. */
1862 return uint64_t(-1);
1863 }
1864
1865 uint64_t to_return = uint64_t(PyLong_AsUnsignedLongLong(value_converted));
1866 Py_DECREF(value_converted);
1867 return to_return;
1868}
1869
1870#if defined(__GNUC__) && !defined(__clang__)
1871# pragma GCC diagnostic pop
1872#endif
1873
1875
1876/* -------------------------------------------------------------------- */
1879
1880char PyC_StructFmt_type_from_str(const char *typestr)
1881{
1882 switch (typestr[0]) {
1883 case '!':
1884 case '<':
1885 case '=':
1886 case '>':
1887 case '@':
1888 return typestr[1];
1889 default:
1890 return typestr[0];
1891 }
1892}
1893
1895{
1896 switch (format) {
1897 case 'f':
1898 case 'd':
1899 case 'e':
1900 return true;
1901 default:
1902 return false;
1903 }
1904}
1905
1907{
1908 switch (format) {
1909 case 'i':
1910 case 'I':
1911 case 'l':
1912 case 'L':
1913 case 'h':
1914 case 'H':
1915 case 'b':
1916 case 'B':
1917 case 'q':
1918 case 'Q':
1919 case 'n':
1920 case 'N':
1921 case 'P':
1922 return true;
1923 default:
1924 return false;
1925 }
1926}
1927
1929{
1930 switch (format) {
1931 case 'c':
1932 case 's':
1933 case 'p':
1934 return true;
1935 default:
1936 return false;
1937 }
1938}
1939
1941{
1942 switch (format) {
1943 case '?':
1944 return true;
1945 default:
1946 return false;
1947 }
1948}
1949
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define ATTR_NONNULL(...)
size_t size_t size_t BLI_snprintf_utf8(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
unsigned long ulong
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
#define UNLIKELY(x)
#define ELEM(...)
#define POINTER_OFFSET(v, ofs)
#define STREQ(a, b)
Read Guarded memory(de)allocation.
BMesh const char void * data
return true
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
long long int int64_t
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
nullptr float
#define str(s)
#define UINT16_MAX
#define INT8_MAX
#define UINT32_MAX
#define INT16_MAX
#define UINT8_MAX
#define printf(...)
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
float length(VecOp< float, D >) RET
format
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
int16_t PyC_Long_AsI16(PyObject *value)
int PyC_AsArray_Multi_FAST(void *array, const size_t array_item_size, PyObject *value_fast, const int *dims, const int dims_len, const PyTypeObject *type, const char *error_prefix)
const char * PyC_UnicodeAsBytesAndSize(PyObject *py_str, Py_ssize_t *r_size, PyObject **r_coerce)
PyObject * PyC_Tuple_PackArray_Bool(const bool *array, uint len)
char PyC_StructFmt_type_from_str(const char *typestr)
PyObject * PyC_Err_SetString_Prefix(PyObject *exception_type_prefix, const char *str)
void PyC_LineSpit()
static PyObject * pyc_run_string_as_py_object(const char *imports[], const char *imports_star[], const char *expr, const char *filename) ATTR_NONNULL(3
void * PyC_RNA_AsPointer(PyObject *value, const char *type_name)
bool PyC_StructFmt_type_is_bool(char format)
uint8_t PyC_Long_AsU8(PyObject *value)
PyObject * PyC_Tuple_PackArray_Multi_Bool(const bool *array, const int dims[], const int dims_len)
PyObject * PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format,...)
void PyC_ObSpit(const char *name, PyObject *var)
int8_t PyC_Long_AsI8(PyObject *value)
PyObject * PyC_FlagSet_AsString(const PyC_FlagSet *item)
PyObject * PyC_UnicodeFromBytesAndSize(const char *str, Py_ssize_t size)
void PyC_RunQuicky(const char *filepath, int n,...)
bool PyC_RunString_AsString(const char *imports[], const char *expr, const char *filename, char **r_value)
static ulong pyc_Long_AsUnsignedLong(PyObject *value)
int PyC_CheckArgs_DeepCopy(PyObject *args)
int PyC_ParseUnicodeAsBytesAndSize(PyObject *o, void *p)
PyObject * PyC_Tuple_PackArray_I32FromBool(const int *array, uint len)
static int PyC_AsArray_Multi_impl(void **array_p, const size_t array_item_size, PyObject *value, const int *dims, const int dims_len, const PyTypeObject *type, const char *error_prefix)
int PyC_FlagSet_ValueFromID(const PyC_FlagSet *item, const char *identifier, int *r_value, const char *error_prefix)
PyObject * PyC_DefaultNameSpace(const char *filename)
bool PyC_RunString_AsStringAndSizeOrNone(const char *imports[], const char *expr, const char *filename, char **r_value, size_t *r_value_size)
int PyC_ParseStringEnum(PyObject *o, void *p)
PyObject * PyC_UnicodeFromBytes(const char *str)
PyObject * PyC_Tuple_PackArray_Multi_F64(const double *array, const int dims[], const int dims_len)
uint64_t PyC_Long_AsU64(PyObject *value)
static PyObject * PyC_Tuple_PackArray_Multi_I32_impl(const int **array_p, const int dims[], const int dims_len)
bool PyC_StructFmt_type_is_int_any(char format)
PyObject * PyC_Tuple_PackArray_I32(const int *array, uint len)
void PyC_ObSpitStr(char *result, size_t result_maxncpy, PyObject *var)
PyObject * PyC_ExceptionBuffer()
#define PyLong_AsInt
static PyObject * PyC_Tuple_PackArray_Multi_Bool_impl(const bool **array_p, const int dims[], const int dims_len)
PyObject * PyC_Tuple_PackArray_String(const char **array, uint len)
bool PyC_RunString_AsStringOrNone(const char *imports[], const char *expr, const char *filename, char **r_value)
int PyC_Long_AsBool(PyObject *value)
int PyC_AsArray(void *array, const size_t array_item_size, PyObject *value, const Py_ssize_t length, const PyTypeObject *type, const char *error_prefix)
int PyC_FlagSet_ValueFromID_int(const PyC_FlagSet *item, const char *identifier, int *r_value)
bool PyC_IsInterpreterActive()
bool PyC_RunString_AsNumber(const char *imports[], const char *expr, const char *filename, double *r_value)
bool PyC_StructFmt_type_is_byte(char format)
int PyC_FlagSet_ToBitfield(const PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix)
PyObject * PyC_Tuple_PackArray_Multi_F32(const float *array, const int dims[], const int dims_len)
PyObject * PyC_ExceptionBuffer_Simple()
int PyC_AsArray_Multi(void *array, const size_t array_item_size, PyObject *value, const int *dims, const int dims_len, const PyTypeObject *type, const char *error_prefix)
PyObject * PyC_MainModule_Backup()
bool PyC_RunString_AsStringAndSize(const char *imports[], const char *expr, const char *filename, char **r_value, size_t *r_value_size)
void PyC_FileAndNum_Safe(const char **r_filename, int *r_lineno)
const char * PyC_StringEnum_FindIDFromValue(const PyC_StringEnumItems *items, const int value)
int PyC_ParseUnicodeAsBytesAndSize_OrNone(PyObject *o, void *p)
uint32_t PyC_Long_AsU32(PyObject *value)
int PyC_AsArray_FAST(void *array, const size_t array_item_size, PyObject *value_fast, const Py_ssize_t length, const PyTypeObject *type, const char *error_prefix)
bool PyC_NameSpace_ImportArray(PyObject *py_dict, const char *imports[])
void PyC_FileAndNum(const char **r_filename, int *r_lineno)
static void pyc_exception_buffer_handle_system_exit()
void PyC_StackSpit()
void PyC_List_Fill(PyObject *list, PyObject *value)
uint16_t PyC_Long_AsU16(PyObject *value)
PyObject * PyC_UnicodeFromStdStr(const std::string &str)
void PyC_Err_PrintWithFunc(PyObject *py_func)
static PyObject * PyC_Tuple_PackArray_Multi_F64_impl(const double **array_p, const int dims[], const int dims_len)
void PyC_MainModule_Restore(PyObject *main_mod)
PyObject * PyC_Tuple_PackArray_F32(const float *array, uint len)
PyObject * PyC_Tuple_PackArray_F64(const double *array, uint len)
PyObject * PyC_Tuple_PackArray_Multi_I32(const int *array, const int dims[], const int dims_len)
void PyC_StdFilesFlush()
int PyC_ParseBool(PyObject *o, void *p)
static PyObject * PyC_Tuple_PackArray_Multi_F32_impl(const float **array_p, const int dims[], const int dims_len)
static int PyC_AsArray_Multi_FAST_impl(void **array_p, const size_t array_item_size, PyObject *value_fast, const int *dims, const int dims_len, const PyTypeObject *type, const char *error_prefix)
PyObject * PyC_FrozenSetFromStrings(const char **strings)
void PyC_Tuple_Fill(PyObject *tuple, PyObject *value)
PyObject * PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag)
PyObject * PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n,...)
bool PyC_StructFmt_type_is_float_any(char format)
const char * PyC_UnicodeAsBytes(PyObject *py_str, PyObject **r_coerce)
bool PyC_RunString_AsIntPtr(const char *imports[], const char *expr, const char *filename, intptr_t *r_value)
Py_DECREF(oname)
const char * name
header-only utilities
return ret
const char * identifier
i
Definition text_draw.cc:230
uint len
PointerRNA * ptr
Definition wm_files.cc:4238
uint8_t flag
Definition wm_window.cc:145