| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2011-10-23 17:52:20 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup pygen | 
					
						
							| 
									
										
										
										
											2011-11-05 08:40:07 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Extend upon CPython's API, filling in some gaps, these functions use PyC_ | 
					
						
							|  |  |  |  * prefix to distinguish them apart from CPython. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note | 
					
						
							|  |  |  |  * This module should only depend on CPython, however it currently uses | 
					
						
							|  |  |  |  * BLI_string_utf8() for unicode conversion. | 
					
						
							| 
									
										
										
										
											2011-02-27 20:10:08 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-16 15:55:47 +11:00
										 |  |  | /* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */ | 
					
						
							|  |  |  | #define PY_SSIZE_T_CLEAN
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | #include <Python.h>
 | 
					
						
							| 
									
										
										
										
											2011-02-22 07:57:18 +00:00
										 |  |  | #include <frameobject.h>
 | 
					
						
							| 
									
										
										
										
											2011-02-14 04:15:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-07 05:26:12 +00:00
										 |  |  | #include "BLI_utildefines.h" /* for bool */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | #include "py_capi_utils.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-18 06:11:02 +10:00
										 |  |  | #include "python_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2015-01-06 16:42:22 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 11:07:26 +11:00
										 |  |  | #ifndef MATH_STANDALONE
 | 
					
						
							| 
									
										
										
										
											2019-10-22 17:37:52 +11:00
										 |  |  | #  include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  include "BLI_string.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-29 19:59:13 +10:00
										 |  |  | /* Only for BLI_strncpy_wchar_from_utf8,
 | 
					
						
							|  |  |  |  * should replace with py funcs but too late in release now. */ | 
					
						
							| 
									
										
										
										
											2012-02-05 02:04:26 +00:00
										 |  |  | #  include "BLI_string_utf8.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-07 11:07:26 +11:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-18 10:31:16 +02:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							| 
									
										
										
										
											2016-05-16 00:48:02 +02:00
										 |  |  | #  include "BLI_math_base.h" /* isfinite() */
 | 
					
						
							| 
									
										
										
										
											2011-04-18 10:18:35 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Fast Python to C Array Conversion for Primitive Types
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  | /* array utility function */ | 
					
						
							| 
									
										
										
										
											2015-07-29 09:31:53 +10:00
										 |  |  | int PyC_AsArray_FAST(void *array, | 
					
						
							|  |  |  |                      PyObject *value_fast, | 
					
						
							|  |  |  |                      const Py_ssize_t length, | 
					
						
							|  |  |  |                      const PyTypeObject *type, | 
					
						
							|  |  |  |                      const bool is_double, | 
					
						
							|  |  |  |                      const char *error_prefix) | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-07-29 09:31:53 +10:00
										 |  |  |   const Py_ssize_t value_len = PySequence_Fast_GET_SIZE(value_fast); | 
					
						
							| 
									
										
										
										
											2015-07-29 09:58:10 +10:00
										 |  |  |   PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); | 
					
						
							| 
									
										
										
										
											2012-02-05 02:04:26 +00:00
										 |  |  |   Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-29 09:31:53 +10:00
										 |  |  |   BLI_assert(PyList_Check(value_fast) || PyTuple_Check(value_fast)); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   if (value_len != length) { | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |     PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                  "%.200s: invalid sequence length. expected %d, got %d", | 
					
						
							|  |  |  |                  error_prefix, | 
					
						
							|  |  |  |                  length, | 
					
						
							|  |  |  |                  value_len); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |   /* for each type */ | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   if (type == &PyFloat_Type) { | 
					
						
							|  |  |  |     if (is_double) { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |       double *array_double = array; | 
					
						
							|  |  |  |       for (i = 0; i < length; i++) { | 
					
						
							| 
									
										
										
										
											2015-07-29 09:58:10 +10:00
										 |  |  |         array_double[i] = PyFloat_AsDouble(value_fast_items[i]); | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |       float *array_float = array; | 
					
						
							|  |  |  |       for (i = 0; i < length; i++) { | 
					
						
							| 
									
										
										
										
											2015-07-29 09:58:10 +10:00
										 |  |  |         array_float[i] = PyFloat_AsDouble(value_fast_items[i]); | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   else if (type == &PyLong_Type) { | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |     /* could use is_double for 'long int' but no use now */ | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |     int *array_int = array; | 
					
						
							|  |  |  |     for (i = 0; i < length; i++) { | 
					
						
							| 
									
										
										
										
											2017-08-20 15:39:08 +10:00
										 |  |  |       array_int[i] = PyC_Long_AsI32(value_fast_items[i]); | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   else if (type == &PyBool_Type) { | 
					
						
							| 
									
										
										
										
											2018-07-01 15:47:09 +02:00
										 |  |  |     bool *array_bool = array; | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |     for (i = 0; i < length; i++) { | 
					
						
							| 
									
										
										
										
											2015-07-29 09:58:10 +10:00
										 |  |  |       array_bool[i] = (PyLong_AsLong(value_fast_items[i]) != 0); | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |   else { | 
					
						
							|  |  |  |     PyErr_Format(PyExc_TypeError, "%s: internal error %s is invalid", error_prefix, type->tp_name); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   if (PyErr_Occurred()) { | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |     PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                  "%s: one or more items could not be used as a %s", | 
					
						
							|  |  |  |                  error_prefix, | 
					
						
							|  |  |  |                  type->tp_name); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-29 09:31:53 +10:00
										 |  |  | int PyC_AsArray(void *array, | 
					
						
							|  |  |  |                 PyObject *value, | 
					
						
							|  |  |  |                 const Py_ssize_t length, | 
					
						
							|  |  |  |                 const PyTypeObject *type, | 
					
						
							|  |  |  |                 const bool is_double, | 
					
						
							|  |  |  |                 const char *error_prefix) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PyObject *value_fast; | 
					
						
							|  |  |  |   int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!(value_fast = PySequence_Fast(value, error_prefix))) { | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ret = PyC_AsArray_FAST(array, value_fast, length, type, is_double, error_prefix); | 
					
						
							|  |  |  |   Py_DECREF(value_fast); | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-22 18:02:58 +10:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Typed Tuple Packing
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note See #PyC_Tuple_Pack_* macros that take multiple arguments. | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-05 14:56:37 +00:00
										 |  |  | /* array utility function */ | 
					
						
							| 
									
										
										
										
											2017-08-22 18:02:58 +10:00
										 |  |  | PyObject *PyC_Tuple_PackArray_F32(const float *array, uint len) | 
					
						
							| 
									
										
										
										
											2018-04-02 19:48:34 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   PyObject *tuple = PyTuple_New(len); | 
					
						
							|  |  |  |   for (uint i = 0; i < len; i++) { | 
					
						
							|  |  |  |     PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array[i])); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return tuple; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *PyC_Tuple_PackArray_F64(const double *array, uint len) | 
					
						
							| 
									
										
										
										
											2013-01-05 14:56:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-22 18:02:58 +10:00
										 |  |  |   PyObject *tuple = PyTuple_New(len); | 
					
						
							|  |  |  |   for (uint i = 0; i < len; i++) { | 
					
						
							|  |  |  |     PyTuple_SET_ITEM(tuple, i, PyFloat_FromDouble(array[i])); | 
					
						
							| 
									
										
										
										
											2013-01-05 14:56:37 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-08-22 18:02:58 +10:00
										 |  |  |   return tuple; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *PyC_Tuple_PackArray_I32(const int *array, uint len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PyObject *tuple = PyTuple_New(len); | 
					
						
							|  |  |  |   for (uint i = 0; i < len; i++) { | 
					
						
							|  |  |  |     PyTuple_SET_ITEM(tuple, i, PyLong_FromLong(array[i])); | 
					
						
							| 
									
										
										
										
											2013-01-05 14:56:37 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-08-22 18:02:58 +10:00
										 |  |  |   return tuple; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *PyC_Tuple_PackArray_I32FromBool(const int *array, uint len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PyObject *tuple = PyTuple_New(len); | 
					
						
							|  |  |  |   for (uint i = 0; i < len; i++) { | 
					
						
							|  |  |  |     PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array[i])); | 
					
						
							| 
									
										
										
										
											2013-01-05 14:56:37 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-08-22 18:02:58 +10:00
										 |  |  |   return tuple; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-01-05 14:56:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-22 18:02:58 +10:00
										 |  |  | PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PyObject *tuple = PyTuple_New(len); | 
					
						
							|  |  |  |   for (uint i = 0; i < len; i++) { | 
					
						
							|  |  |  |     PyTuple_SET_ITEM(tuple, i, PyBool_FromLong(array[i])); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-01-05 14:56:37 +00:00
										 |  |  |   return tuple; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-22 18:02:58 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Tuple/List Filling
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-06 16:46:00 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Caller needs to ensure tuple is uninitialized. | 
					
						
							| 
									
										
										
										
											2016-07-16 17:48:57 +10:00
										 |  |  |  * Handy for filling a tuple with None for eg. | 
					
						
							| 
									
										
										
										
											2014-01-06 16:46:00 +11:00
										 |  |  |  */ | 
					
						
							|  |  |  | void PyC_Tuple_Fill(PyObject *tuple, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-20 16:10:13 +10:00
										 |  |  |   const uint tot = PyTuple_GET_SIZE(tuple); | 
					
						
							| 
									
										
										
										
											2020-02-20 15:38:58 +11:00
										 |  |  |   uint i; | 
					
						
							| 
									
										
										
										
											2014-01-06 16:46:00 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; i < tot; i++) { | 
					
						
							|  |  |  |     PyTuple_SET_ITEM(tuple, i, value); | 
					
						
							|  |  |  |     Py_INCREF(value); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 16:42:22 +11:00
										 |  |  | void PyC_List_Fill(PyObject *list, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-20 16:10:13 +10:00
										 |  |  |   const uint tot = PyList_GET_SIZE(list); | 
					
						
							| 
									
										
										
										
											2020-02-20 15:38:58 +11:00
										 |  |  |   uint i; | 
					
						
							| 
									
										
										
										
											2015-01-06 16:42:22 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; i < tot; i++) { | 
					
						
							|  |  |  |     PyList_SET_ITEM(list, i, value); | 
					
						
							|  |  |  |     Py_INCREF(value); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Bool/Enum Argument Parsing
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 11:07:26 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Use with PyArg_ParseTuple's "O&" formatting. | 
					
						
							| 
									
										
										
										
											2017-08-20 15:39:08 +10:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \see #PyC_Long_AsBool for a similar function to use outside of argument parsing. | 
					
						
							| 
									
										
										
										
											2015-12-07 11:07:26 +11:00
										 |  |  |  */ | 
					
						
							|  |  |  | int PyC_ParseBool(PyObject *o, void *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bool *bool_p = p; | 
					
						
							|  |  |  |   long value; | 
					
						
							|  |  |  |   if (((value = PyLong_AsLong(o)) == -1) || !ELEM(value, 0, 1)) { | 
					
						
							|  |  |  |     PyErr_Format(PyExc_ValueError, "expected a bool or int (0/1), got %s", Py_TYPE(o)->tp_name); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 11:07:26 +11:00
										 |  |  |   *bool_p = value ? true : false; | 
					
						
							|  |  |  |   return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-01 04:09:33 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Use with PyArg_ParseTuple's "O&" formatting. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int PyC_ParseStringEnum(PyObject *o, void *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct PyC_StringEnum *e = p; | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |   const char *value = PyUnicode_AsUTF8(o); | 
					
						
							| 
									
										
										
										
											2019-10-01 04:09:33 +10:00
										 |  |  |   if (value == NULL) { | 
					
						
							|  |  |  |     PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  |   for (i = 0; e->items[i].id; i++) { | 
					
						
							|  |  |  |     if (STREQ(e->items[i].id, value)) { | 
					
						
							|  |  |  |       e->value_found = e->items[i].value; | 
					
						
							|  |  |  |       return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Set as a precaution. */ | 
					
						
							|  |  |  |   e->value_found = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PyObject *enum_items = PyTuple_New(i); | 
					
						
							|  |  |  |   for (i = 0; e->items[i].id; i++) { | 
					
						
							|  |  |  |     PyTuple_SET_ITEM(enum_items, i, PyUnicode_FromString(e->items[i].id)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   PyErr_Format(PyExc_ValueError, "expected a string in %S, got '%s'", enum_items, value); | 
					
						
							|  |  |  |   Py_DECREF(enum_items); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												Python: gpu module: add new submodules and types
This commit extends the gpu python API with:
```
gpu.types.Buffer         #"__init__", "to_list"
gpu.types.GPUTexture     #"__init__", "clear", "read", "format"
gpu.types.GPUFrameBuffer #"__init__", "bind", "clear", "is_bound", "viewport", ("__enter__",  "__exit__" with "GPUFrameBufferStackContext")
gpu.types.GPUUniformBuf  #"__init__", "update"
gpu.state                #"blend_set",  "blend_get",  "depth_test_set",  "depth_test_get",  "depth_mask_set",  "depth_mask_get",  "viewport_set",  "viewport_get",  "line_width_set",  "line_width_get",  "point_size_set",  "color_mask_set",  "face_culling_set", "front_facing_set",  "program_point_size_set"
```
Add these methods to existing objects:
```
gpu.types.GPUShader  #"uniform_sample", "uniform_buffer"
```
Maniphest Tasks: T80481
Differential Revision: https://developer.blender.org/D8826
											
										 
											2021-02-17 10:48:08 -03:00
										 |  |  | const char *PyC_StringEnum_FindIDFromValue(const struct PyC_StringEnumItems *items, | 
					
						
							|  |  |  |                                            const int value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   for (int i = 0; items[i].id; i++) { | 
					
						
							|  |  |  |     if (items[i].value == value) { | 
					
						
							|  |  |  |       return items[i].id; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 09:35:12 +11:00
										 |  |  | /* Silly function, we don't use arg. just check its compatible with `__deepcopy__`. */ | 
					
						
							| 
									
										
										
										
											2018-06-26 09:26:52 +02:00
										 |  |  | int PyC_CheckArgs_DeepCopy(PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PyObject *dummy_pydict; | 
					
						
							|  |  |  |   return PyArg_ParseTuple(args, "|O!:__deepcopy__", &PyDict_Type, &dummy_pydict) != 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-07 11:07:26 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 11:07:26 +11:00
										 |  |  | #ifndef MATH_STANDALONE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Simple Printing (for debugging)
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * These are useful to run directly from a debugger to be able to inspect the state. | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | /* for debugging */ | 
					
						
							| 
									
										
										
										
											2011-09-28 05:53:40 +00:00
										 |  |  | void PyC_ObSpit(const char *name, PyObject *var) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-04-02 11:05:15 +02:00
										 |  |  |   const char *null_str = "<null>"; | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   fprintf(stderr, "<%s> : ", name); | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   if (var == NULL) { | 
					
						
							| 
									
										
										
										
											2018-04-02 11:05:15 +02:00
										 |  |  |     fprintf(stderr, "%s\n", null_str); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     PyObject_Print(var, stderr, 0); | 
					
						
							| 
									
										
										
										
											2018-04-02 11:05:15 +02:00
										 |  |  |     const PyTypeObject *type = Py_TYPE(var); | 
					
						
							|  |  |  |     fprintf(stderr, | 
					
						
							|  |  |  |             " ref:%d, ptr:%p, type: %s\n", | 
					
						
							|  |  |  |             (int)var->ob_refcnt, | 
					
						
							|  |  |  |             (void *)var, | 
					
						
							|  |  |  |             type ? type->tp_name : null_str); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * A version of #PyC_ObSpit that writes into a string (and doesn't take a name argument). | 
					
						
							|  |  |  |  * Use for logging. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void PyC_ObSpitStr(char *result, size_t result_len, PyObject *var) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* No name, creator of string can manage that. */ | 
					
						
							|  |  |  |   const char *null_str = "<null>"; | 
					
						
							|  |  |  |   if (var == NULL) { | 
					
						
							|  |  |  |     BLI_snprintf(result, result_len, "%s", null_str); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     const PyTypeObject *type = Py_TYPE(var); | 
					
						
							|  |  |  |     PyObject *var_str = PyObject_Repr(var); | 
					
						
							|  |  |  |     if (var_str == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-29 19:59:13 +10:00
										 |  |  |       /* We could print error here,
 | 
					
						
							|  |  |  |        * but this may be used for generating errors - so don't for now. */ | 
					
						
							| 
									
										
										
										
											2018-04-02 11:05:15 +02:00
										 |  |  |       PyErr_Clear(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     BLI_snprintf(result, | 
					
						
							|  |  |  |                  result_len, | 
					
						
							|  |  |  |                  " ref=%d, ptr=%p, type=%s, value=%.200s", | 
					
						
							|  |  |  |                  (int)var->ob_refcnt, | 
					
						
							|  |  |  |                  (void *)var, | 
					
						
							|  |  |  |                  type ? type->tp_name : null_str, | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |                  var_str ? PyUnicode_AsUTF8(var_str) : "<error>"); | 
					
						
							| 
									
										
										
										
											2018-04-02 11:05:15 +02:00
										 |  |  |     if (var_str != NULL) { | 
					
						
							|  |  |  |       Py_DECREF(var_str); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-28 05:53:40 +00:00
										 |  |  | void PyC_LineSpit(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-03-25 04:36:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   const char *filename; | 
					
						
							|  |  |  |   int lineno; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-25 04:36:10 +00:00
										 |  |  |   /* Note, allow calling from outside python (RNA) */ | 
					
						
							| 
									
										
										
										
											2013-09-18 23:21:24 +00:00
										 |  |  |   if (!PyC_IsInterpreterActive()) { | 
					
						
							| 
									
										
										
										
											2011-03-25 04:36:10 +00:00
										 |  |  |     fprintf(stderr, "python line lookup failed, interpreter inactive\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   PyErr_Clear(); | 
					
						
							|  |  |  |   PyC_FileAndNum(&filename, &lineno); | 
					
						
							| 
									
										
										
										
											2018-06-04 08:54:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   fprintf(stderr, "%s:%d\n", filename, lineno); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-19 09:55:49 +00:00
										 |  |  | void PyC_StackSpit(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* Note, allow calling from outside python (RNA) */ | 
					
						
							| 
									
										
										
										
											2013-09-18 23:21:24 +00:00
										 |  |  |   if (!PyC_IsInterpreterActive()) { | 
					
						
							| 
									
										
										
										
											2012-07-19 09:55:49 +00:00
										 |  |  |     fprintf(stderr, "python line lookup failed, interpreter inactive\n"); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 12:41:06 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* lame but handy */ | 
					
						
							| 
									
										
										
										
											2020-08-20 16:10:13 +10:00
										 |  |  |   const PyGILState_STATE gilstate = PyGILState_Ensure(); | 
					
						
							| 
									
										
										
										
											2020-08-07 12:41:06 +02:00
										 |  |  |   PyRun_SimpleString("__import__('traceback').print_stack()"); | 
					
						
							|  |  |  |   PyGILState_Release(gilstate); | 
					
						
							| 
									
										
										
										
											2012-07-19 09:55:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Access Current Frame File Name & Line Number
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-25 17:58:58 +11:00
										 |  |  | void PyC_FileAndNum(const char **r_filename, int *r_lineno) | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-22 07:57:18 +00:00
										 |  |  |   PyFrameObject *frame; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-25 17:58:58 +11:00
										 |  |  |   if (r_filename) { | 
					
						
							|  |  |  |     *r_filename = NULL; | 
					
						
							| 
									
										
										
										
											2019-03-30 06:12:48 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-03-25 17:58:58 +11:00
										 |  |  |   if (r_lineno) { | 
					
						
							|  |  |  |     *r_lineno = -1; | 
					
						
							| 
									
										
										
										
											2019-03-30 06:12:48 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   if (!(frame = PyThreadState_GET()->frame)) { | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   /* when executing a script */ | 
					
						
							| 
									
										
										
										
											2020-03-25 17:58:58 +11:00
										 |  |  |   if (r_filename) { | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |     *r_filename = PyUnicode_AsUTF8(frame->f_code->co_filename); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   /* when executing a module */ | 
					
						
							| 
									
										
										
										
											2020-03-25 17:58:58 +11:00
										 |  |  |   if (r_filename && *r_filename == NULL) { | 
					
						
							|  |  |  |     /* try an alternative method to get the r_filename - module based
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |      * references below are all borrowed (double checked) */ | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |     PyObject *mod_name = PyDict_GetItemString(PyEval_GetGlobals(), "__name__"); | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |     if (mod_name) { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |       PyObject *mod = PyDict_GetItem(PyImport_GetModuleDict(), mod_name); | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |       if (mod) { | 
					
						
							| 
									
										
										
										
											2017-07-17 12:44:03 +10:00
										 |  |  |         PyObject *mod_file = PyModule_GetFilenameObject(mod); | 
					
						
							|  |  |  |         if (mod_file) { | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |           *r_filename = PyUnicode_AsUTF8(mod_name); | 
					
						
							| 
									
										
										
										
											2017-07-17 12:44:03 +10:00
										 |  |  |           Py_DECREF(mod_file); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           PyErr_Clear(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |       /* unlikely, fallback */ | 
					
						
							| 
									
										
										
										
											2020-03-25 17:58:58 +11:00
										 |  |  |       if (*r_filename == NULL) { | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |         *r_filename = PyUnicode_AsUTF8(mod_name); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-25 17:58:58 +11:00
										 |  |  |   if (r_lineno) { | 
					
						
							|  |  |  |     *r_lineno = PyFrame_GetLineNumber(frame); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-25 17:58:58 +11:00
										 |  |  | void PyC_FileAndNum_Safe(const char **r_filename, int *r_lineno) | 
					
						
							| 
									
										
										
										
											2011-10-20 00:48:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-18 23:21:24 +00:00
										 |  |  |   if (!PyC_IsInterpreterActive()) { | 
					
						
							| 
									
										
										
										
											2011-10-20 00:48:00 +00:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-25 17:58:58 +11:00
										 |  |  |   PyC_FileAndNum(r_filename, r_lineno); | 
					
						
							| 
									
										
										
										
											2011-10-20 00:48:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Object Access Utilities
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | /* Would be nice if python had this built in */ | 
					
						
							|  |  |  | PyObject *PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Py_ssize_t i; | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   PyObject *item = o; | 
					
						
							| 
									
										
										
										
											2014-04-27 00:21:23 +10:00
										 |  |  |   const char *attr; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   va_list vargs; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   va_start(vargs, n); | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   for (i = 0; i < n; i++) { | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |     attr = va_arg(vargs, char *); | 
					
						
							|  |  |  |     item = PyObject_GetAttrString(item, attr); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-30 06:12:48 +11:00
										 |  |  |     if (item) { | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |       Py_DECREF(item); | 
					
						
							| 
									
										
										
										
											2019-03-30 06:12:48 +11:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       /* python will set the error value here */ | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2019-03-30 06:12:48 +11:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   va_end(vargs); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */ | 
					
						
							|  |  |  |   return item; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Frozen Set Creation
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-04 03:47:37 +00:00
										 |  |  | PyObject *PyC_FrozenSetFromStrings(const char **strings) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const char **str; | 
					
						
							|  |  |  |   PyObject *ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ret = PyFrozenSet_New(NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (str = strings; *str; str++) { | 
					
						
							|  |  |  |     PyObject *py_str = PyUnicode_FromString(*str); | 
					
						
							|  |  |  |     PySet_Add(ret, py_str); | 
					
						
							|  |  |  |     Py_DECREF(py_str); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Exception Utilities
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-16 17:48:57 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Similar to #PyErr_Format(), | 
					
						
							| 
									
										
										
										
											2011-09-15 10:43:55 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-07-16 17:48:57 +10:00
										 |  |  |  * Implementation - we cant actually prepend the existing exception, | 
					
						
							| 
									
										
										
										
											2012-07-16 23:23:33 +00:00
										 |  |  |  * because it could have _any_ arguments given to it, so instead we get its | 
					
						
							| 
									
										
										
										
											2016-07-16 17:48:57 +10:00
										 |  |  |  * ``__str__`` output and raise our own exception including it. | 
					
						
							| 
									
										
										
										
											2011-09-15 10:43:55 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | PyObject *PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PyObject *error_value_prefix; | 
					
						
							|  |  |  |   va_list args; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-15 10:43:55 +00:00
										 |  |  |   va_start(args, format); | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   error_value_prefix = PyUnicode_FromFormatV(format, args); /* can fail and be NULL */ | 
					
						
							| 
									
										
										
										
											2011-09-15 10:43:55 +00:00
										 |  |  |   va_end(args); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   if (PyErr_Occurred()) { | 
					
						
							| 
									
										
										
										
											2011-09-15 10:43:55 +00:00
										 |  |  |     PyObject *error_type, *error_value, *error_traceback; | 
					
						
							|  |  |  |     PyErr_Fetch(&error_type, &error_value, &error_traceback); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-17 08:43:57 +11:00
										 |  |  |     if (PyUnicode_Check(error_value)) { | 
					
						
							|  |  |  |       PyErr_Format(exception_type_prefix, "%S, %S", error_value_prefix, error_value); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       PyErr_Format(exception_type_prefix, | 
					
						
							|  |  |  |                    "%S, %.200s(%S)", | 
					
						
							|  |  |  |                    error_value_prefix, | 
					
						
							|  |  |  |                    Py_TYPE(error_value)->tp_name, | 
					
						
							|  |  |  |                    error_value); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-09-15 10:43:55 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     PyErr_SetObject(exception_type_prefix, error_value_prefix); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-15 10:43:55 +00:00
										 |  |  |   Py_XDECREF(error_value_prefix); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-15 10:43:55 +00:00
										 |  |  |   /* dumb to always return NULL but matches PyErr_Format */ | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-17 08:38:59 +11:00
										 |  |  | PyObject *PyC_Err_SetString_Prefix(PyObject *exception_type_prefix, const char *str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return PyC_Err_Format_Prefix(exception_type_prefix, "%s", str); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-29 13:41:10 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Use for Python callbacks run directly from C, | 
					
						
							|  |  |  |  * when we can't use normal methods of raising exceptions. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void PyC_Err_PrintWithFunc(PyObject *py_func) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* since we return to C code we can't leave the error */ | 
					
						
							|  |  |  |   PyCodeObject *f_code = (PyCodeObject *)PyFunction_GET_CODE(py_func); | 
					
						
							|  |  |  |   PyErr_Print(); | 
					
						
							|  |  |  |   PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-29 13:41:10 +11:00
										 |  |  |   /* use py style error */ | 
					
						
							|  |  |  |   fprintf(stderr, | 
					
						
							|  |  |  |           "File \"%s\", line %d, in %s\n", | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |           PyUnicode_AsUTF8(f_code->co_filename), | 
					
						
							| 
									
										
										
										
											2017-11-29 13:41:10 +11:00
										 |  |  |           f_code->co_firstlineno, | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |           PyUnicode_AsUTF8(((PyFunctionObject *)py_func)->func_name)); | 
					
						
							| 
									
										
										
										
											2017-11-29 13:41:10 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Exception Buffer Access
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-03 06:46:31 +00:00
										 |  |  | /* returns the exception string as a new PyUnicode object, depends on external traceback module */ | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | #  if 0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* this version uses traceback module but somehow fails on UI errors */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | PyObject *PyC_ExceptionBuffer(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   PyObject *traceback_mod = NULL; | 
					
						
							|  |  |  |   PyObject *format_tb_func = NULL; | 
					
						
							|  |  |  |   PyObject *ret = NULL; | 
					
						
							| 
									
										
										
										
											2011-09-03 06:46:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   if (!(traceback_mod = PyImport_ImportModule("traceback"))) { | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |     goto error_cleanup; | 
					
						
							| 
									
										
										
										
											2011-03-19 11:12:48 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   else if (!(format_tb_func = PyObject_GetAttrString(traceback_mod, "format_exc"))) { | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |     goto error_cleanup; | 
					
						
							| 
									
										
										
										
											2011-03-19 11:12:48 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-09-03 06:46:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   ret = PyObject_CallObject(format_tb_func, NULL); | 
					
						
							| 
									
										
										
										
											2011-09-03 06:46:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   if (ret == Py_None) { | 
					
						
							| 
									
										
										
										
											2011-09-03 06:46:31 +00:00
										 |  |  |     Py_DECREF(ret); | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |     ret = NULL; | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-09-03 06:46:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | error_cleanup: | 
					
						
							|  |  |  |   /* could not import the module so print the error and close */ | 
					
						
							| 
									
										
										
										
											2011-09-03 06:46:31 +00:00
										 |  |  |   Py_XDECREF(traceback_mod); | 
					
						
							|  |  |  |   Py_XDECREF(format_tb_func); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-03 06:46:31 +00:00
										 |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | #  else /* verbose, non-threadsafe version */
 | 
					
						
							|  |  |  | PyObject *PyC_ExceptionBuffer(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PyObject *stdout_backup = PySys_GetObject("stdout"); /* borrowed */ | 
					
						
							|  |  |  |   PyObject *stderr_backup = PySys_GetObject("stderr"); /* borrowed */ | 
					
						
							|  |  |  |   PyObject *string_io = NULL; | 
					
						
							|  |  |  |   PyObject *string_io_buf = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   PyObject *string_io_mod = NULL; | 
					
						
							|  |  |  |   PyObject *string_io_getvalue = NULL; | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-30 06:12:48 +11:00
										 |  |  |   PyObject *error_type, *error_value, *error_traceback; | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!PyErr_Occurred()) { | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   PyErr_Fetch(&error_type, &error_value, &error_traceback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PyErr_Clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   /* import io
 | 
					
						
							| 
									
										
										
										
											2014-07-01 13:39:36 +10:00
										 |  |  |    * string_io = io.StringIO() | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  |   if (!(string_io_mod = PyImport_ImportModule("io"))) { | 
					
						
							|  |  |  |     goto error_cleanup; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  |   else if (!(string_io = PyObject_CallMethod(string_io_mod, "StringIO", NULL))) { | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  |     goto error_cleanup; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  |   else if (!(string_io_getvalue = PyObject_GetAttrString(string_io, "getvalue"))) { | 
					
						
							|  |  |  |     goto error_cleanup; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 00:41:09 +00:00
										 |  |  |   /* Since these were borrowed we don't want them freed when replaced. */ | 
					
						
							|  |  |  |   Py_INCREF(stdout_backup); | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  |   Py_INCREF(stderr_backup); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Both of these are freed when restoring. */ | 
					
						
							|  |  |  |   PySys_SetObject("stdout", string_io); | 
					
						
							|  |  |  |   PySys_SetObject("stderr", string_io); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PyErr_Restore(error_type, error_value, error_traceback); | 
					
						
							|  |  |  |   PyErr_Print(); /* print the error */ | 
					
						
							|  |  |  |   PyErr_Clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   string_io_buf = PyObject_CallObject(string_io_getvalue, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PySys_SetObject("stdout", stdout_backup); | 
					
						
							|  |  |  |   PySys_SetObject("stderr", stderr_backup); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Py_DECREF(stdout_backup); /* now sys owns the ref again */ | 
					
						
							|  |  |  |   Py_DECREF(stderr_backup); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Py_DECREF(string_io_mod); | 
					
						
							|  |  |  |   Py_DECREF(string_io_getvalue); | 
					
						
							|  |  |  |   Py_DECREF(string_io); /* free the original reference */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2015-05-18 09:12:26 +10:00
										 |  |  |   return string_io_buf; | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | error_cleanup: | 
					
						
							|  |  |  |   /* could not import the module so print the error and close */ | 
					
						
							|  |  |  |   Py_XDECREF(string_io_mod); | 
					
						
							|  |  |  |   Py_XDECREF(string_io); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PyErr_Restore(error_type, error_value, error_traceback); | 
					
						
							|  |  |  |   PyErr_Print(); /* print the error */ | 
					
						
							|  |  |  |   PyErr_Clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-18 09:12:26 +10:00
										 |  |  | PyObject *PyC_ExceptionBuffer_Simple(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-27 13:46:51 +10:00
										 |  |  |   PyObject *string_io_buf = NULL; | 
					
						
							| 
									
										
										
										
											2015-05-18 09:12:26 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  |   PyObject *error_type, *error_value, *error_traceback; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-30 06:12:48 +11:00
										 |  |  |   if (!PyErr_Occurred()) { | 
					
						
							| 
									
										
										
										
											2015-05-18 09:12:26 +10:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-03-30 06:12:48 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-05-18 09:12:26 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  |   PyErr_Fetch(&error_type, &error_value, &error_traceback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (error_value == NULL) { | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-27 13:46:51 +10:00
										 |  |  |   if (PyErr_GivenExceptionMatches(error_type, PyExc_SyntaxError)) { | 
					
						
							|  |  |  |     /* Special exception for syntax errors,
 | 
					
						
							|  |  |  |      * in these cases the full error is verbose and not very useful, | 
					
						
							|  |  |  |      * just use the initial text so we know what the error is. */ | 
					
						
							|  |  |  |     if (PyTuple_CheckExact(error_value) && PyTuple_GET_SIZE(error_value) >= 1) { | 
					
						
							|  |  |  |       string_io_buf = PyObject_Str(PyTuple_GET_ITEM(error_value, 0)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (string_io_buf == NULL) { | 
					
						
							|  |  |  |     string_io_buf = PyObject_Str(error_value); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-18 09:12:26 +10:00
										 |  |  |   /* Python does this too */ | 
					
						
							|  |  |  |   if (UNLIKELY(string_io_buf == NULL)) { | 
					
						
							|  |  |  |     string_io_buf = PyUnicode_FromFormat("<unprintable %s object>", Py_TYPE(error_value)->tp_name); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PyErr_Restore(error_type, error_value, error_traceback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PyErr_Clear(); | 
					
						
							|  |  |  |   return string_io_buf; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Unicode Conversion
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * In some cases we need to coerce strings, avoid doing this inline. | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | /* string conversion, escape non-unicode chars, coerce must be set to NULL */ | 
					
						
							| 
									
										
										
										
											2016-07-31 16:52:44 +10:00
										 |  |  | const char *PyC_UnicodeAsByteAndSize(PyObject *py_str, Py_ssize_t *size, PyObject **coerce) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const char *result; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |   result = PyUnicode_AsUTF8AndSize(py_str, size); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-31 16:52:44 +10:00
										 |  |  |   if (result) { | 
					
						
							|  |  |  |     /* 99% of the time this is enough but we better support non unicode
 | 
					
						
							| 
									
										
										
										
											2018-09-19 17:48:11 +02:00
										 |  |  |      * chars since blender doesn't limit this */ | 
					
						
							| 
									
										
										
										
											2016-07-31 16:52:44 +10:00
										 |  |  |     return result; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 12:41:06 +02:00
										 |  |  |   PyErr_Clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (PyBytes_Check(py_str)) { | 
					
						
							|  |  |  |     *size = PyBytes_GET_SIZE(py_str); | 
					
						
							|  |  |  |     return PyBytes_AS_STRING(py_str); | 
					
						
							| 
									
										
										
										
											2016-07-31 16:52:44 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 12:41:06 +02:00
										 |  |  |   if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) { | 
					
						
							|  |  |  |     *size = PyBytes_GET_SIZE(*coerce); | 
					
						
							|  |  |  |     return PyBytes_AS_STRING(*coerce); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* leave error raised from EncodeFS */ | 
					
						
							|  |  |  |   return NULL; | 
					
						
							| 
									
										
										
										
											2016-07-31 16:52:44 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-03 23:29:43 +00:00
										 |  |  | const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-11-03 14:09:18 +00:00
										 |  |  |   const char *result; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |   result = PyUnicode_AsUTF8(py_str); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   if (result) { | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |     /* 99% of the time this is enough but we better support non unicode
 | 
					
						
							| 
									
										
										
										
											2019-06-12 09:04:10 +10:00
										 |  |  |      * chars since blender doesn't limit this. */ | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |     return result; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 12:41:06 +02:00
										 |  |  |   PyErr_Clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (PyBytes_Check(py_str)) { | 
					
						
							|  |  |  |     return PyBytes_AS_STRING(py_str); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 12:41:06 +02:00
										 |  |  |   if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) { | 
					
						
							|  |  |  |     return PyBytes_AS_STRING(*coerce); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* leave error raised from EncodeFS */ | 
					
						
							|  |  |  |   return NULL; | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-22 10:49:35 +00:00
										 |  |  | PyObject *PyC_UnicodeFromByteAndSize(const char *str, Py_ssize_t size) | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 07:36:32 +00:00
										 |  |  |   PyObject *result = PyUnicode_FromStringAndSize(str, size); | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   if (result) { | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |     /* 99% of the time this is enough but we better support non unicode
 | 
					
						
							| 
									
										
										
										
											2018-09-19 17:48:11 +02:00
										 |  |  |      * chars since blender doesn't limit this */ | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  |     return result; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 12:41:06 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   PyErr_Clear(); | 
					
						
							|  |  |  |   /* this means paths will always be accessible once converted, on all OS's */ | 
					
						
							|  |  |  |   result = PyUnicode_DecodeFSDefaultAndSize(str, size); | 
					
						
							|  |  |  |   return result; | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-09-18 15:30:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-22 10:49:35 +00:00
										 |  |  | PyObject *PyC_UnicodeFromByte(const char *str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return PyC_UnicodeFromByteAndSize(str, strlen(str)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Name Space Creation/Manipulation
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-18 15:30:03 +00:00
										 |  |  | /*****************************************************************************
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:36:09 +00:00
										 |  |  |  * Description: This function creates a new Python dictionary object. | 
					
						
							|  |  |  |  * note: dict is owned by sys.modules["__main__"] module, reference is borrowed | 
					
						
							|  |  |  |  * note: important we use the dict from __main__, this is what python expects | 
					
						
							| 
									
										
										
										
											2018-09-02 18:51:31 +10:00
										 |  |  |  * for 'pickle' to work as well as strings like this... | 
					
						
							| 
									
										
										
										
											2012-03-03 20:36:09 +00:00
										 |  |  |  * >> foo = 10 | 
					
						
							|  |  |  |  * >> print(__import__("__main__").foo) | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-09-28 06:45:20 +00:00
										 |  |  |  * note: this overwrites __main__ which gives problems with nested calls. | 
					
						
							| 
									
										
										
										
											2012-03-03 20:36:09 +00:00
										 |  |  |  * be sure to run PyC_MainModule_Backup & PyC_MainModule_Restore if there is | 
					
						
							|  |  |  |  * any chance that python is in the call stack. | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  |  ****************************************************************************/ | 
					
						
							| 
									
										
										
										
											2010-09-18 15:30:03 +00:00
										 |  |  | PyObject *PyC_DefaultNameSpace(const char *filename) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-16 23:15:30 +11:00
										 |  |  |   PyObject *modules = PyImport_GetModuleDict(); | 
					
						
							|  |  |  |   PyObject *builtins = PyEval_GetBuiltins(); | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   PyObject *mod_main = PyModule_New("__main__"); | 
					
						
							| 
									
										
										
										
											2019-10-16 23:15:30 +11:00
										 |  |  |   PyDict_SetItemString(modules, "__main__", mod_main); | 
					
						
							| 
									
										
										
										
											2010-09-18 15:30:03 +00:00
										 |  |  |   Py_DECREF(mod_main); /* sys.modules owns now */ | 
					
						
							|  |  |  |   PyModule_AddStringConstant(mod_main, "__name__", "__main__"); | 
					
						
							| 
									
										
										
										
											2012-03-21 22:29:49 +00:00
										 |  |  |   if (filename) { | 
					
						
							| 
									
										
										
										
											2014-06-16 15:24:19 +10:00
										 |  |  |     /* __file__ mainly for nice UI'ness
 | 
					
						
							|  |  |  |      * note: this wont map to a real file when executing text-blocks and buttons. */ | 
					
						
							|  |  |  |     PyModule_AddObject(mod_main, "__file__", PyC_UnicodeFromByte(filename)); | 
					
						
							| 
									
										
										
										
											2012-03-21 22:29:49 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-10-16 23:15:30 +11:00
										 |  |  |   PyModule_AddObject(mod_main, "__builtins__", builtins); | 
					
						
							|  |  |  |   Py_INCREF(builtins); /* AddObject steals a reference */ | 
					
						
							| 
									
										
										
										
											2010-09-18 15:30:03 +00:00
										 |  |  |   return PyModule_GetDict(mod_main); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-03 12:38:19 +10:00
										 |  |  | bool PyC_NameSpace_ImportArray(PyObject *py_dict, const char *imports[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   for (int i = 0; imports[i]; i++) { | 
					
						
							|  |  |  |     PyObject *name = PyUnicode_FromString(imports[i]); | 
					
						
							|  |  |  |     PyObject *mod = PyImport_ImportModuleLevelObject(name, NULL, NULL, 0, 0); | 
					
						
							|  |  |  |     bool ok = false; | 
					
						
							|  |  |  |     if (mod) { | 
					
						
							|  |  |  |       PyDict_SetItem(py_dict, name, mod); | 
					
						
							|  |  |  |       ok = true; | 
					
						
							|  |  |  |       Py_DECREF(mod); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(name); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-03 12:38:19 +10:00
										 |  |  |     if (!ok) { | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-01 12:37:53 +00:00
										 |  |  | /* restore MUST be called after this */ | 
					
						
							| 
									
										
										
										
											2021-02-05 22:34:03 +11:00
										 |  |  | void PyC_MainModule_Backup(PyObject **r_main_mod) | 
					
						
							| 
									
										
										
										
											2011-02-01 12:37:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-16 23:15:30 +11:00
										 |  |  |   PyObject *modules = PyImport_GetModuleDict(); | 
					
						
							| 
									
										
										
										
											2021-02-05 22:34:03 +11:00
										 |  |  |   *r_main_mod = PyDict_GetItemString(modules, "__main__"); | 
					
						
							|  |  |  |   Py_XINCREF(*r_main_mod); /* don't free */ | 
					
						
							| 
									
										
										
										
											2011-02-01 12:37:53 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PyC_MainModule_Restore(PyObject *main_mod) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-16 23:15:30 +11:00
										 |  |  |   PyObject *modules = PyImport_GetModuleDict(); | 
					
						
							|  |  |  |   PyDict_SetItemString(modules, "__main__", main_mod); | 
					
						
							| 
									
										
										
										
											2011-02-01 12:37:53 +00:00
										 |  |  |   Py_XDECREF(main_mod); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-18 23:21:24 +00:00
										 |  |  | bool PyC_IsInterpreterActive(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-09-26 11:58:31 +10:00
										 |  |  |   /* instead of PyThreadState_Get, which calls Py_FatalError */ | 
					
						
							|  |  |  |   return (PyThreadState_GetDict() != NULL); | 
					
						
							| 
									
										
										
										
											2013-09-18 23:21:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name #Py_SetPythonHome Wrapper
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-28 10:02:10 +00:00
										 |  |  | /* Would be nice if python had this built in
 | 
					
						
							| 
									
										
										
										
											2018-08-31 14:21:32 +10:00
										 |  |  |  * See: https://wiki.blender.org/wiki/Tools/Debugging/PyFromC
 | 
					
						
							| 
									
										
										
										
											2012-08-28 10:02:10 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | void PyC_RunQuicky(const char *filepath, int n, ...) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   FILE *fp = fopen(filepath, "r"); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |   if (fp) { | 
					
						
							| 
									
										
										
										
											2020-08-20 16:10:13 +10:00
										 |  |  |     const PyGILState_STATE gilstate = PyGILState_Ensure(); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  |     va_list vargs; | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-16 15:55:47 +11:00
										 |  |  |     Py_ssize_t *sizes = PyMem_MALLOC(sizeof(*sizes) * (n / 2)); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     PyObject *py_dict = PyC_DefaultNameSpace(filepath); | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  |     PyObject *values = PyList_New(n / 2); /* namespace owns this, don't free */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     PyObject *py_result, *ret; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |     PyObject *struct_mod = PyImport_ImportModule("struct"); | 
					
						
							|  |  |  |     PyObject *calcsize = PyObject_GetAttrString(struct_mod, "calcsize"); /* struct.calcsize */ | 
					
						
							|  |  |  |     PyObject *pack = PyObject_GetAttrString(struct_mod, "pack");         /* struct.pack */ | 
					
						
							|  |  |  |     PyObject *unpack = PyObject_GetAttrString(struct_mod, "unpack");     /* struct.unpack */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     Py_DECREF(struct_mod); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     va_start(vargs, n); | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |     for (i = 0; i * 2 < n; i++) { | 
					
						
							| 
									
										
										
										
											2014-04-27 00:21:23 +10:00
										 |  |  |       const char *format = va_arg(vargs, char *); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |       void *ptr = va_arg(vargs, void *); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-01 13:39:36 +10:00
										 |  |  |       ret = PyObject_CallFunction(calcsize, "s", format); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |       if (ret) { | 
					
						
							| 
									
										
										
										
											2012-11-21 02:28:36 +00:00
										 |  |  |         sizes[i] = PyLong_AsLong(ret); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |         Py_DECREF(ret); | 
					
						
							| 
									
										
										
										
											2014-07-01 13:39:36 +10:00
										 |  |  |         ret = PyObject_CallFunction(unpack, "sy#", format, (char *)ptr, sizes[i]); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |       if (ret == NULL) { | 
					
						
							| 
									
										
										
										
											2015-11-25 22:56:49 +11:00
										 |  |  |         printf("%s error, line:%d\n", __func__, __LINE__); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |         PyErr_Print(); | 
					
						
							|  |  |  |         PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 16:42:22 +11:00
										 |  |  |         PyList_SET_ITEM(values, i, Py_INCREF_RET(Py_None)); /* hold user */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 06:55:09 +00:00
										 |  |  |         sizes[i] = 0; | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |         if (PyTuple_GET_SIZE(ret) == 1) { | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |           /* convenience, convert single tuples into single values */ | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |           PyObject *tmp = PyTuple_GET_ITEM(ret, 0); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |           Py_INCREF(tmp); | 
					
						
							|  |  |  |           Py_DECREF(ret); | 
					
						
							|  |  |  |           ret = tmp; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |         PyList_SET_ITEM(values, i, ret); /* hold user */ | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     va_end(vargs); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     /* set the value so we can access it */ | 
					
						
							|  |  |  |     PyDict_SetItemString(py_dict, "values", values); | 
					
						
							| 
									
										
										
										
											2016-07-14 17:28:28 +10:00
										 |  |  |     Py_DECREF(values); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     fclose(fp); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |     if (py_result) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |       /* we could skip this but then only slice assignment would work
 | 
					
						
							|  |  |  |        * better not be so strict */ | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |       values = PyDict_GetItemString(py_dict, "values"); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |       if (values && PyList_Check(values)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  |         /* don't use the result */ | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |         Py_DECREF(py_result); | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |         py_result = NULL; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |         /* now get the values back */ | 
					
						
							|  |  |  |         va_start(vargs, n); | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |         for (i = 0; i * 2 < n; i++) { | 
					
						
							| 
									
										
										
										
											2014-04-27 00:21:23 +10:00
										 |  |  |           const char *format = va_arg(vargs, char *); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |           void *ptr = va_arg(vargs, void *); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |           PyObject *item; | 
					
						
							|  |  |  |           PyObject *item_new; | 
					
						
							|  |  |  |           /* prepend the string formatting and remake the tuple */ | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |           item = PyList_GET_ITEM(values, i); | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |           if (PyTuple_CheckExact(item)) { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |             int ofs = PyTuple_GET_SIZE(item); | 
					
						
							|  |  |  |             item_new = PyTuple_New(ofs + 1); | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |             while (ofs--) { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |               PyObject *member = PyTuple_GET_ITEM(item, ofs); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |               PyTuple_SET_ITEM(item_new, ofs + 1, member); | 
					
						
							|  |  |  |               Py_INCREF(member); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |             PyTuple_SET_ITEM(item_new, 0, PyUnicode_FromString(format)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           else { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |             item_new = Py_BuildValue("sO", format, item); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |           ret = PyObject_Call(pack, item_new, NULL); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  |           if (ret) { | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |             /* copy the bytes back into memory */ | 
					
						
							|  |  |  |             memcpy(ptr, PyBytes_AS_STRING(ret), sizes[i]); | 
					
						
							|  |  |  |             Py_DECREF(ret); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           else { | 
					
						
							| 
									
										
										
										
											2015-11-25 22:56:49 +11:00
										 |  |  |             printf("%s error on arg '%d', line:%d\n", __func__, i, __LINE__); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |             PyC_ObSpit("failed converting:", item_new); | 
					
						
							|  |  |  |             PyErr_Print(); | 
					
						
							|  |  |  |             PyErr_Clear(); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |           Py_DECREF(item_new); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         va_end(vargs); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2015-11-25 22:56:49 +11:00
										 |  |  |         printf("%s error, 'values' not a list, line:%d\n", __func__, __LINE__); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2015-11-25 22:56:49 +11:00
										 |  |  |       printf("%s error line:%d\n", __func__, __LINE__); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |       PyErr_Print(); | 
					
						
							|  |  |  |       PyErr_Clear(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     Py_DECREF(calcsize); | 
					
						
							|  |  |  |     Py_DECREF(pack); | 
					
						
							|  |  |  |     Py_DECREF(unpack); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     PyMem_FREE(sizes); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  |     PyGILState_Release(gilstate); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-04-29 02:55:02 +10:00
										 |  |  |   else { | 
					
						
							|  |  |  |     fprintf(stderr, "%s: '%s' missing\n", __func__, filepath); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-02-20 22:04:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* generic function to avoid depending on RNA */ | 
					
						
							|  |  |  | void *PyC_RNA_AsPointer(PyObject *value, const char *type_name) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  |   PyObject *as_pointer; | 
					
						
							|  |  |  |   PyObject *pointer; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-10 06:18:03 +00:00
										 |  |  |   if (STREQ(Py_TYPE(value)->tp_name, type_name) && | 
					
						
							| 
									
										
										
										
											2012-02-20 22:04:29 +00:00
										 |  |  |       (as_pointer = PyObject_GetAttrString(value, "as_pointer")) != NULL && | 
					
						
							|  |  |  |       PyCallable_Check(as_pointer)) { | 
					
						
							|  |  |  |     void *result = NULL; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-20 22:04:29 +00:00
										 |  |  |     /* must be a 'type_name' object */ | 
					
						
							|  |  |  |     pointer = PyObject_CallObject(as_pointer, NULL); | 
					
						
							|  |  |  |     Py_DECREF(as_pointer); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-20 22:04:29 +00:00
										 |  |  |     if (!pointer) { | 
					
						
							|  |  |  |       PyErr_SetString(PyExc_SystemError, "value.as_pointer() failed"); | 
					
						
							|  |  |  |       return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     result = PyLong_AsVoidPtr(pointer); | 
					
						
							|  |  |  |     Py_DECREF(pointer); | 
					
						
							|  |  |  |     if (!result) { | 
					
						
							|  |  |  |       PyErr_SetString(PyExc_SystemError, "value.as_pointer() failed"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-20 22:04:29 +00:00
										 |  |  |     return result; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 12:41:06 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                "expected '%.200s' type found '%.200s' instead", | 
					
						
							|  |  |  |                type_name, | 
					
						
							|  |  |  |                Py_TYPE(value)->tp_name); | 
					
						
							|  |  |  |   return NULL; | 
					
						
							| 
									
										
										
										
											2012-02-20 22:04:29 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Flag Set Utilities (#PyC_FlagSet)
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Convert to/from Python set of strings to an int flag. | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-22 17:37:52 +11:00
										 |  |  | PyObject *PyC_FlagSet_AsString(PyC_FlagSet *item) | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-22 17:37:52 +11:00
										 |  |  |   PyObject *py_items = PyList_New(0); | 
					
						
							|  |  |  |   for (; item->identifier; item++) { | 
					
						
							|  |  |  |     PyList_APPEND(py_items, PyUnicode_FromString(item->identifier)); | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-10-22 17:37:52 +11:00
										 |  |  |   PyObject *py_string = PyObject_Repr(py_items); | 
					
						
							|  |  |  |   Py_DECREF(py_items); | 
					
						
							|  |  |  |   return py_string; | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-18 09:39:36 +11:00
										 |  |  | int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *r_value) | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  |   for (; item->identifier; item++) { | 
					
						
							| 
									
										
										
										
											2013-03-10 06:18:03 +00:00
										 |  |  |     if (STREQ(item->identifier, identifier)) { | 
					
						
							| 
									
										
										
										
											2017-03-18 09:39:36 +11:00
										 |  |  |       *r_value = item->value; | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |       return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-18 09:39:36 +11:00
										 |  |  | int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, | 
					
						
							|  |  |  |                             const char *identifier, | 
					
						
							|  |  |  |                             int *r_value, | 
					
						
							|  |  |  |                             const char *error_prefix) | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-03-18 09:39:36 +11:00
										 |  |  |   if (PyC_FlagSet_ValueFromID_int(item, identifier, r_value) == 0) { | 
					
						
							| 
									
										
										
										
											2019-10-22 17:37:52 +11:00
										 |  |  |     PyObject *enum_str = PyC_FlagSet_AsString(item); | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |     PyErr_Format( | 
					
						
							| 
									
										
										
										
											2019-10-22 17:37:52 +11:00
										 |  |  |         PyExc_ValueError, "%s: '%.200s' not found in (%U)", error_prefix, identifier, enum_str); | 
					
						
							|  |  |  |     Py_DECREF(enum_str); | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, | 
					
						
							|  |  |  |                            PyObject *value, | 
					
						
							|  |  |  |                            int *r_value, | 
					
						
							|  |  |  |                            const char *error_prefix) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* set of enum items, concatenate all values with OR */ | 
					
						
							|  |  |  |   int ret, flag = 0; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |   /* set looping */ | 
					
						
							|  |  |  |   Py_ssize_t pos = 0; | 
					
						
							|  |  |  |   Py_ssize_t hash = 0; | 
					
						
							|  |  |  |   PyObject *key; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-06 03:33:11 +00:00
										 |  |  |   if (!PySet_Check(value)) { | 
					
						
							|  |  |  |     PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                  "%.200s expected a set, not %.200s", | 
					
						
							|  |  |  |                  error_prefix, | 
					
						
							|  |  |  |                  Py_TYPE(value)->tp_name); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |   *r_value = 0; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |   while (_PySet_NextEntry(value, &pos, &key, &hash)) { | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |     const char *param = PyUnicode_AsUTF8(key); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |     if (param == NULL) { | 
					
						
							|  |  |  |       PyErr_Format(PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2012-10-06 03:33:11 +00:00
										 |  |  |                    "%.200s set must contain strings, not %.200s", | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |                    error_prefix, | 
					
						
							|  |  |  |                    Py_TYPE(key)->tp_name); | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |     if (PyC_FlagSet_ValueFromID(items, param, &ret, error_prefix) < 0) { | 
					
						
							|  |  |  |       return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |     flag |= ret; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |   *r_value = flag; | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PyObject *ret = PySet_New(NULL); | 
					
						
							|  |  |  |   PyObject *pystr; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |   for (; items->identifier; items++) { | 
					
						
							|  |  |  |     if (items->value & flag) { | 
					
						
							|  |  |  |       pystr = PyUnicode_FromString(items->identifier); | 
					
						
							|  |  |  |       PySet_Add(ret, pystr); | 
					
						
							|  |  |  |       Py_DECREF(pystr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Run String (Evaluate to Primitive Types)
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2015-12-31 21:15:29 +11:00
										 |  |  |  * \return success | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \note it is caller's responsibility to acquire & release GIL! | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-09-03 12:38:19 +10:00
										 |  |  | bool PyC_RunString_AsNumber(const char *imports[], | 
					
						
							|  |  |  |                             const char *expr, | 
					
						
							|  |  |  |                             const char *filename, | 
					
						
							|  |  |  |                             double *r_value) | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   PyObject *py_dict, *mod, *retval; | 
					
						
							| 
									
										
										
										
											2015-12-31 21:15:29 +11:00
										 |  |  |   bool ok = true; | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |   PyObject *main_mod = NULL; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |   PyC_MainModule_Backup(&main_mod); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |   py_dict = PyC_DefaultNameSpace(filename); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |   mod = PyImport_ImportModule("math"); | 
					
						
							|  |  |  |   if (mod) { | 
					
						
							|  |  |  |     PyDict_Merge(py_dict, PyModule_GetDict(mod), 0); /* 0 - don't overwrite existing values */ | 
					
						
							|  |  |  |     Py_DECREF(mod); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { /* highly unlikely but possibly */ | 
					
						
							|  |  |  |     PyErr_Print(); | 
					
						
							|  |  |  |     PyErr_Clear(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-03 12:38:19 +10:00
										 |  |  |   if (imports && (!PyC_NameSpace_ImportArray(py_dict, imports))) { | 
					
						
							|  |  |  |     ok = false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if ((retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict)) == NULL) { | 
					
						
							| 
									
										
										
										
											2015-12-31 21:15:29 +11:00
										 |  |  |     ok = false; | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     double val; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |     if (PyTuple_Check(retval)) { | 
					
						
							|  |  |  |       /* Users my have typed in 10km, 2m
 | 
					
						
							|  |  |  |        * add up all values */ | 
					
						
							|  |  |  |       int i; | 
					
						
							|  |  |  |       val = 0.0; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |       for (i = 0; i < PyTuple_GET_SIZE(retval); i++) { | 
					
						
							|  |  |  |         const double val_item = PyFloat_AsDouble(PyTuple_GET_ITEM(retval, i)); | 
					
						
							|  |  |  |         if (val_item == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |           val = -1; | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         val += val_item; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       val = PyFloat_AsDouble(retval); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(retval); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |     if (val == -1 && PyErr_Occurred()) { | 
					
						
							| 
									
										
										
										
											2015-12-31 21:15:29 +11:00
										 |  |  |       ok = false; | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-05-16 00:48:02 +02:00
										 |  |  |     else if (!isfinite(val)) { | 
					
						
							| 
									
										
										
										
											2017-03-18 09:39:36 +11:00
										 |  |  |       *r_value = 0.0; | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2017-03-18 09:39:36 +11:00
										 |  |  |       *r_value = val; | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  |   PyC_MainModule_Restore(main_mod); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-31 21:15:29 +11:00
										 |  |  |   return ok; | 
					
						
							| 
									
										
										
										
											2014-06-17 16:03:40 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-08-03 20:00:16 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-03 12:38:19 +10:00
										 |  |  | bool PyC_RunString_AsIntPtr(const char *imports[], | 
					
						
							|  |  |  |                             const char *expr, | 
					
						
							|  |  |  |                             const char *filename, | 
					
						
							|  |  |  |                             intptr_t *r_value) | 
					
						
							| 
									
										
										
										
											2018-08-31 14:21:32 +10:00
										 |  |  | { | 
					
						
							|  |  |  |   PyObject *py_dict, *retval; | 
					
						
							|  |  |  |   bool ok = true; | 
					
						
							|  |  |  |   PyObject *main_mod = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PyC_MainModule_Backup(&main_mod); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   py_dict = PyC_DefaultNameSpace(filename); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-03 12:38:19 +10:00
										 |  |  |   if (imports && (!PyC_NameSpace_ImportArray(py_dict, imports))) { | 
					
						
							|  |  |  |     ok = false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if ((retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict)) == NULL) { | 
					
						
							| 
									
										
										
										
											2018-08-31 14:21:32 +10:00
										 |  |  |     ok = false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     intptr_t val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     val = (intptr_t)PyLong_AsVoidPtr(retval); | 
					
						
							|  |  |  |     if (val == 0 && PyErr_Occurred()) { | 
					
						
							|  |  |  |       ok = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       *r_value = val; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(retval); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   PyC_MainModule_Restore(main_mod); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ok; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-11 18:04:44 +11:00
										 |  |  | bool PyC_RunString_AsStringAndSize(const char *imports[], | 
					
						
							|  |  |  |                                    const char *expr, | 
					
						
							|  |  |  |                                    const char *filename, | 
					
						
							|  |  |  |                                    char **r_value, | 
					
						
							|  |  |  |                                    size_t *r_value_size) | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11:00
										 |  |  | { | 
					
						
							|  |  |  |   PyObject *py_dict, *retval; | 
					
						
							|  |  |  |   bool ok = true; | 
					
						
							|  |  |  |   PyObject *main_mod = NULL; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11:00
										 |  |  |   PyC_MainModule_Backup(&main_mod); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11:00
										 |  |  |   py_dict = PyC_DefaultNameSpace(filename); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-03 12:38:19 +10:00
										 |  |  |   if (imports && (!PyC_NameSpace_ImportArray(py_dict, imports))) { | 
					
						
							|  |  |  |     ok = false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if ((retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict)) == NULL) { | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11:00
										 |  |  |     ok = false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     const char *val; | 
					
						
							|  |  |  |     Py_ssize_t val_len; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-13 22:57:01 +11:00
										 |  |  |     val = PyUnicode_AsUTF8AndSize(retval, &val_len); | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11:00
										 |  |  |     if (val == NULL && PyErr_Occurred()) { | 
					
						
							|  |  |  |       ok = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       char *val_alloc = MEM_mallocN(val_len + 1, __func__); | 
					
						
							|  |  |  |       memcpy(val_alloc, val, val_len + 1); | 
					
						
							|  |  |  |       *r_value = val_alloc; | 
					
						
							| 
									
										
										
										
											2019-12-11 18:04:44 +11:00
										 |  |  |       *r_value_size = val_len; | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11:00
										 |  |  |     Py_DECREF(retval); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11:00
										 |  |  |   PyC_MainModule_Restore(main_mod); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11:00
										 |  |  |   return ok; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-11 18:04:44 +11:00
										 |  |  | bool PyC_RunString_AsString(const char *imports[], | 
					
						
							|  |  |  |                             const char *expr, | 
					
						
							|  |  |  |                             const char *filename, | 
					
						
							|  |  |  |                             char **r_value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   size_t value_size; | 
					
						
							|  |  |  |   return PyC_RunString_AsStringAndSize(imports, expr, filename, r_value, &value_size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 11:07:26 +11:00
										 |  |  | #endif /* #ifndef MATH_STANDALONE */
 | 
					
						
							| 
									
										
										
										
											2017-08-20 15:39:08 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Int Conversion
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note Python doesn't provide overflow checks for specific bit-widths. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Compiler optimizes out redundant checks. */ | 
					
						
							|  |  |  | #ifdef __GNUC__
 | 
					
						
							|  |  |  | #  pragma warning(push)
 | 
					
						
							|  |  |  | #  pragma GCC diagnostic ignored "-Wtype-limits"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Don't use `bool` return type, so -1 can be used as an error value. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int PyC_Long_AsBool(PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-20 16:10:13 +10:00
										 |  |  |   const int test = _PyLong_AsInt(value); | 
					
						
							| 
									
										
										
										
											2017-08-20 15:39:08 +10:00
										 |  |  |   if (UNLIKELY((uint)test > 1)) { | 
					
						
							|  |  |  |     PyErr_SetString(PyExc_TypeError, "Python number not a bool (0/1)"); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return test; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int8_t PyC_Long_AsI8(PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-20 16:10:13 +10:00
										 |  |  |   const int test = _PyLong_AsInt(value); | 
					
						
							| 
									
										
										
										
											2017-08-20 15:39:08 +10:00
										 |  |  |   if (UNLIKELY(test < INT8_MIN || test > INT8_MAX)) { | 
					
						
							|  |  |  |     PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C int8"); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return (int8_t)test; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int16_t PyC_Long_AsI16(PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-20 16:10:13 +10:00
										 |  |  |   const int test = _PyLong_AsInt(value); | 
					
						
							| 
									
										
										
										
											2017-08-20 15:39:08 +10:00
										 |  |  |   if (UNLIKELY(test < INT16_MIN || test > INT16_MAX)) { | 
					
						
							|  |  |  |     PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C int16"); | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return (int16_t)test; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Inlined in header:
 | 
					
						
							|  |  |  |  * PyC_Long_AsI32 | 
					
						
							|  |  |  |  * PyC_Long_AsI64 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint8_t PyC_Long_AsU8(PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-20 16:10:13 +10:00
										 |  |  |   const ulong test = PyLong_AsUnsignedLong(value); | 
					
						
							| 
									
										
										
										
											2017-08-20 15:39:08 +10:00
										 |  |  |   if (UNLIKELY(test > UINT8_MAX)) { | 
					
						
							|  |  |  |     PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C uint8"); | 
					
						
							|  |  |  |     return (uint8_t)-1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return (uint8_t)test; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint16_t PyC_Long_AsU16(PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-20 16:10:13 +10:00
										 |  |  |   const ulong test = PyLong_AsUnsignedLong(value); | 
					
						
							| 
									
										
										
										
											2017-08-20 15:39:08 +10:00
										 |  |  |   if (UNLIKELY(test > UINT16_MAX)) { | 
					
						
							|  |  |  |     PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C uint16"); | 
					
						
							|  |  |  |     return (uint16_t)-1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return (uint16_t)test; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint32_t PyC_Long_AsU32(PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-20 16:10:13 +10:00
										 |  |  |   const ulong test = PyLong_AsUnsignedLong(value); | 
					
						
							| 
									
										
										
										
											2017-08-20 15:39:08 +10:00
										 |  |  |   if (UNLIKELY(test > UINT32_MAX)) { | 
					
						
							|  |  |  |     PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C uint32"); | 
					
						
							|  |  |  |     return (uint32_t)-1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return (uint32_t)test; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Inlined in header:
 | 
					
						
							|  |  |  |  * PyC_Long_AsU64 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:51:28 +10:00
										 |  |  | #ifdef __GNUC__
 | 
					
						
							|  |  |  | #  pragma warning(pop)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-07 12:22:17 -03:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Py_buffer Utils
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-08 08:37:32 +11:00
										 |  |  | char PyC_StructFmt_type_from_str(const char *typestr) | 
					
						
							| 
									
										
										
										
											2018-10-07 12:22:17 -03:00
										 |  |  | { | 
					
						
							|  |  |  |   switch (typestr[0]) { | 
					
						
							|  |  |  |     case '!': | 
					
						
							|  |  |  |     case '<': | 
					
						
							|  |  |  |     case '=': | 
					
						
							|  |  |  |     case '>': | 
					
						
							|  |  |  |     case '@': | 
					
						
							|  |  |  |       return typestr[1]; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return typestr[0]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-08 08:37:32 +11:00
										 |  |  | bool PyC_StructFmt_type_is_float_any(char format) | 
					
						
							| 
									
										
										
										
											2018-10-07 12:22:17 -03:00
										 |  |  | { | 
					
						
							|  |  |  |   switch (format) { | 
					
						
							|  |  |  |     case 'f': | 
					
						
							|  |  |  |     case 'd': | 
					
						
							|  |  |  |     case 'e': | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-08 08:37:32 +11:00
										 |  |  | bool PyC_StructFmt_type_is_int_any(char format) | 
					
						
							| 
									
										
										
										
											2018-10-07 12:22:17 -03:00
										 |  |  | { | 
					
						
							|  |  |  |   switch (format) { | 
					
						
							|  |  |  |     case 'i': | 
					
						
							|  |  |  |     case 'I': | 
					
						
							|  |  |  |     case 'l': | 
					
						
							|  |  |  |     case 'L': | 
					
						
							|  |  |  |     case 'h': | 
					
						
							|  |  |  |     case 'H': | 
					
						
							|  |  |  |     case 'b': | 
					
						
							|  |  |  |     case 'B': | 
					
						
							|  |  |  |     case 'q': | 
					
						
							|  |  |  |     case 'Q': | 
					
						
							|  |  |  |     case 'n': | 
					
						
							|  |  |  |     case 'N': | 
					
						
							|  |  |  |     case 'P': | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-08 08:37:32 +11:00
										 |  |  | bool PyC_StructFmt_type_is_byte(char format) | 
					
						
							| 
									
										
										
										
											2018-10-07 12:22:17 -03:00
										 |  |  | { | 
					
						
							|  |  |  |   switch (format) { | 
					
						
							|  |  |  |     case 'c': | 
					
						
							|  |  |  |     case 's': | 
					
						
							|  |  |  |     case 'p': | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-08 08:37:32 +11:00
										 |  |  | bool PyC_StructFmt_type_is_bool(char format) | 
					
						
							| 
									
										
										
										
											2018-10-07 12:22:17 -03:00
										 |  |  | { | 
					
						
							|  |  |  |   switch (format) { | 
					
						
							|  |  |  |     case '?': | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ |