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