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