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