| 
									
										
										
										
											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
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-02 11:05:15 +02:00
										 |  |  | #include "BLI_string.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 11:07:26 +11:00
										 |  |  | #ifndef MATH_STANDALONE
 | 
					
						
							| 
									
										
										
										
											2012-02-05 02:04:26 +00:00
										 |  |  | /* only for BLI_strncpy_wchar_from_utf8, should replace with py funcs but too late in release now */ | 
					
						
							|  |  |  | #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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-29 09:31:53 +10:00
										 |  |  | 	BLI_assert(PyList_Check(value_fast) || PyTuple_Check(value_fast)); | 
					
						
							| 
									
										
										
										
											2011-06-17 05:45:46 +00: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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* 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
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		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
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 		             "%s: internal error %s is invalid", | 
					
						
							|  |  |  | 		             error_prefix, type->tp_name); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int tot = PyTuple_GET_SIZE(tuple); | 
					
						
							|  |  |  | 	unsigned int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int tot = PyList_GET_SIZE(list); | 
					
						
							|  |  |  | 	unsigned int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < tot; i++) { | 
					
						
							|  |  |  | 		PyList_SET_ITEM(list, i, value); | 
					
						
							|  |  |  | 		Py_INCREF(value); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*bool_p = value ? true : false; | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-26 09:26:52 +02:00
										 |  |  | /* silly function, we dont use arg. just check its compatible with __deepcopy__ */ | 
					
						
							|  |  |  | 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
										 |  |  | 
 | 
					
						
							|  |  |  | #ifndef MATH_STANDALONE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							|  |  |  | 			/* We could print error here, but this may be used for generating errors - so don't for now. */ | 
					
						
							|  |  |  | 			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, | 
					
						
							|  |  |  | 		        var_str ? _PyUnicode_AsString(var_str) : "<error>"); | 
					
						
							|  |  |  | 		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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* lame but handy */ | 
					
						
							|  |  |  | 		PyGILState_STATE gilstate = PyGILState_Ensure(); | 
					
						
							|  |  |  | 		PyRun_SimpleString("__import__('traceback').print_stack()"); | 
					
						
							|  |  |  | 		PyGILState_Release(gilstate); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | void PyC_FileAndNum(const char **filename, int *lineno) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-22 07:57:18 +00:00
										 |  |  | 	PyFrameObject *frame; | 
					
						
							| 
									
										
										
										
											2018-06-04 08:54:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 06:55:09 +00:00
										 |  |  | 	if (filename) *filename = NULL; | 
					
						
							|  |  |  | 	if (lineno)   *lineno = -1; | 
					
						
							| 
									
										
										
										
											2011-02-22 07:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 	if (!(frame = PyThreadState_GET()->frame)) { | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-02-22 07:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 	/* when executing a script */ | 
					
						
							|  |  |  | 	if (filename) { | 
					
						
							| 
									
										
										
										
											2011-02-22 07:57:18 +00:00
										 |  |  | 		*filename = _PyUnicode_AsString(frame->f_code->co_filename); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-02-22 07:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 	/* when executing a module */ | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  | 	if (filename && *filename == NULL) { | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 		/* try an alternative method to get the filename - module based
 | 
					
						
							|  |  |  | 		 * 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) { | 
					
						
							|  |  |  | 					*filename = _PyUnicode_AsString(mod_name); | 
					
						
							|  |  |  | 					Py_DECREF(mod_file); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							|  |  |  | 					PyErr_Clear(); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* unlikely, fallback */ | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  | 			if (*filename == NULL) { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 				*filename = _PyUnicode_AsString(mod_name); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-02-22 07:57:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 	if (lineno) { | 
					
						
							| 
									
										
										
										
											2011-02-22 07:57:18 +00:00
										 |  |  | 		*lineno = PyFrame_GetLineNumber(frame); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-20 00:48:00 +00:00
										 |  |  | void PyC_FileAndNum_Safe(const char **filename, int *lineno) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-09-18 23:21:24 +00:00
										 |  |  | 	if (!PyC_IsInterpreterActive()) { | 
					
						
							| 
									
										
										
										
											2011-10-20 00:48:00 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyC_FileAndNum(filename, lineno); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2018-06-04 08:54:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 	va_list vargs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2018-06-04 08:54:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (item) | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 			Py_DECREF(item); | 
					
						
							|  |  |  | 		else /* python will set the error value here */ | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2018-06-04 08:54:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	va_end(vargs); | 
					
						
							| 
									
										
										
										
											2018-06-04 08:54:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 	Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */ | 
					
						
							|  |  |  | 	return item; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-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, | 
					
						
							| 
									
										
										
										
											2019-01-17 08:43:57 +11:00
										 |  |  | 		                error_value_prefix); | 
					
						
							| 
									
										
										
										
											2011-09-15 10:43:55 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_XDECREF(error_value_prefix); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* 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(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* use py style error */ | 
					
						
							|  |  |  | 	fprintf(stderr, "File \"%s\", line %d, in %s\n", | 
					
						
							|  |  |  | 	        _PyUnicode_AsString(f_code->co_filename), | 
					
						
							|  |  |  | 	        f_code->co_firstlineno, | 
					
						
							|  |  |  | 	        _PyUnicode_AsString(((PyFunctionObject *)py_func)->func_name) | 
					
						
							|  |  |  | 	        ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-15 10:43:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 	PyObject *error_type, *error_value, *error_traceback; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyErr_Fetch(&error_type, &error_value, &error_traceback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyErr_Clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* import io
 | 
					
						
							|  |  |  | 	 * string_io = io.StringIO() | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 	if (!(string_io_mod = PyImport_ImportModule("io"))) { | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 		goto error_cleanup; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-07-01 13:39:36 +10:00
										 |  |  | 	else if (!(string_io = PyObject_CallMethod(string_io_mod, "StringIO", NULL))) { | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 		goto error_cleanup; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 	else if (!(string_io_getvalue = PyObject_GetAttrString(string_io, "getvalue"))) { | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 		goto error_cleanup; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  | 	Py_INCREF(stdout_backup); // since these were borrowed we don't want them freed when replaced.
 | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 	Py_INCREF(stderr_backup); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 00:41:09 +00:00
										 |  |  | 	PySys_SetObject("stdout", string_io); // both of these are freed when restoring
 | 
					
						
							| 
									
										
										
										
											2011-09-08 02:14:24 +00:00
										 |  |  | 	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(); | 
					
						
							|  |  |  | 	return string_io_buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *string_io_buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyObject *error_type, *error_value, *error_traceback; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyErr_Occurred()) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyErr_Fetch(&error_type, &error_value, &error_traceback); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (error_value == NULL) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	string_io_buf = PyObject_Str(error_value); | 
					
						
							|  |  |  | 	/* 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_Print(); | 
					
						
							|  |  |  | 	PyErr_Clear(); | 
					
						
							|  |  |  | 	return string_io_buf; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result = _PyUnicode_AsStringAndSize(py_str, size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (PyBytes_Check(py_str)) { | 
					
						
							|  |  |  | 			*size = PyBytes_GET_SIZE(py_str); | 
					
						
							|  |  |  | 			return PyBytes_AS_STRING(py_str); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) { | 
					
						
							|  |  |  | 			*size = PyBytes_GET_SIZE(*coerce); | 
					
						
							|  |  |  | 			return PyBytes_AS_STRING(*coerce); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			/* leave error raised from EncodeFS */ | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 	result = _PyUnicode_AsString(py_str); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00: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
 | 
					
						
							|  |  |  | 		 * chars since blender doesnt limit this */ | 
					
						
							|  |  |  | 		return result; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2011-09-27 04:07:48 +00:00
										 |  |  | 		PyErr_Clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-18 13:46:57 +00:00
										 |  |  | 		if (PyBytes_Check(py_str)) { | 
					
						
							| 
									
										
										
										
											2011-09-27 04:07:48 +00:00
										 |  |  | 			return PyBytes_AS_STRING(py_str); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 		else if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) { | 
					
						
							| 
									
										
										
										
											2011-11-22 14:05:08 +00:00
										 |  |  | 			return PyBytes_AS_STRING(*coerce); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-09-27 04:07:48 +00:00
										 |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2011-11-22 14:05:08 +00:00
										 |  |  | 			/* leave error raised from EncodeFS */ | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2011-09-27 04:07:48 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2010-12-05 09:20:18 +00:00
										 |  |  | 		/* this means paths will always be accessible once converted, on all OS's */ | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 		result = PyUnicode_DecodeFSDefaultAndSize(str, size); | 
					
						
							| 
									
										
										
										
											2010-09-01 14:13:48 +00:00
										 |  |  | 		return result; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											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)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 	PyInterpreterState *interp = PyThreadState_GET()->interp; | 
					
						
							|  |  |  | 	PyObject *mod_main = PyModule_New("__main__"); | 
					
						
							| 
									
										
										
										
											2010-09-18 15:30:03 +00:00
										 |  |  | 	PyDict_SetItemString(interp->modules, "__main__", mod_main); | 
					
						
							|  |  |  | 	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
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-09-18 15:30:03 +00:00
										 |  |  | 	PyModule_AddObject(mod_main, "__builtins__", interp->builtins); | 
					
						
							|  |  |  | 	Py_INCREF(interp->builtins); /* AddObject steals a reference */ | 
					
						
							|  |  |  | 	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); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!ok) { | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-01 12:37:53 +00:00
										 |  |  | /* restore MUST be called after this */ | 
					
						
							|  |  |  | void PyC_MainModule_Backup(PyObject **main_mod) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 	PyInterpreterState *interp = PyThreadState_GET()->interp; | 
					
						
							|  |  |  | 	*main_mod = PyDict_GetItemString(interp->modules, "__main__"); | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  | 	Py_XINCREF(*main_mod); /* don't free */ | 
					
						
							| 
									
										
										
										
											2011-02-01 12:37:53 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PyC_MainModule_Restore(PyObject *main_mod) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 	PyInterpreterState *interp = PyThreadState_GET()->interp; | 
					
						
							| 
									
										
										
										
											2011-02-01 12:37:53 +00:00
										 |  |  | 	PyDict_SetItemString(interp->modules, "__main__", main_mod); | 
					
						
							|  |  |  | 	Py_XDECREF(main_mod); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-23 15:54:29 +01:00
										 |  |  | /* must be called before Py_Initialize, expects output of BKE_appdir_folder_id(BLENDER_PYTHON, NULL) */ | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | void PyC_SetHomePath(const char *py_path_bundle) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 	if (py_path_bundle == NULL) { | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | 		/* Common enough to have bundled *nix python but complain on OSX/Win */ | 
					
						
							|  |  |  | #if defined(__APPLE__) || defined(_WIN32)
 | 
					
						
							| 
									
										
										
										
											2012-02-05 02:04:26 +00:00
										 |  |  | 		fprintf(stderr, "Warning! bundled python not found and is expected on this platform. " | 
					
						
							|  |  |  | 		        "(if you built with CMake: 'install' target may have not been built)\n"); | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* set the environment path */ | 
					
						
							|  |  |  | 	printf("found bundled python: %s\n", py_path_bundle); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __APPLE__
 | 
					
						
							|  |  |  | 	/* OSX allow file/directory names to contain : character (represented as / in the Finder)
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:36:09 +00:00
										 |  |  | 	 * but current Python lib (release 3.1.1) doesn't handle these correctly */ | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  | 	if (strchr(py_path_bundle, ':')) | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | 		printf("Warning : Blender application is located in a path containing : or / chars\
 | 
					
						
							| 
									
										
										
										
											2012-11-09 09:33:28 +00:00
										 |  |  | 		       \nThis may make python import function fail\n"); | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-19 10:10:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if 0 /* disable for now [#31506] - campbell */
 | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | 	/* cmake/MSVC debug build crashes without this, why only
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:36:09 +00:00
										 |  |  | 	 * in this case is unknown.. */ | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-05-28 21:36:29 +00:00
										 |  |  | 		/*BLI_setenv("PYTHONPATH", py_path_bundle)*/; | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-05-19 10:10:49 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		static wchar_t py_path_bundle_wchar[1024]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* cant use this, on linux gives bug: #23018, TODO: try LANG="en_US.UTF-8" /usr/bin/blender, suggested 22008 */ | 
					
						
							|  |  |  | 		/* mbstowcs(py_path_bundle_wchar, py_path_bundle, FILE_MAXDIR); */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-17 02:47:57 +10:00
										 |  |  | 		BLI_strncpy_wchar_from_utf8(py_path_bundle_wchar, py_path_bundle, ARRAY_SIZE(py_path_bundle_wchar)); | 
					
						
							| 
									
										
										
										
											2011-04-18 08:27:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Py_SetPythonHome(py_path_bundle_wchar); | 
					
						
							|  |  |  | 		// printf("found python (wchar_t) '%ls'\n", py_path_bundle_wchar);
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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"); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  | 	if (fp) { | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 		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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-16 21:39:56 +00:00
										 |  |  | 		int *sizes = PyMem_MALLOC(sizeof(int) * (n / 2)); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 		int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		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 */ | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		PyObject *py_result, *ret; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 */ | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		Py_DECREF(struct_mod); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		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 *); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-01 13:39:36 +10:00
										 |  |  | 			ret = PyObject_CallFunction(calcsize, "s", format); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00: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
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 16:42:22 +11:00
										 |  |  | 				PyList_SET_ITEM(values, i, Py_INCREF_RET(Py_None)); /* hold user */ | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00: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; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				PyList_SET_ITEM(values, i, ret); /* hold user */ | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		va_end(vargs); | 
					
						
							| 
									
										
										
										
											2018-06-04 08:54:17 +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); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		fclose(fp); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  | 		if (py_result) { | 
					
						
							| 
									
										
										
										
											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"); | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-13 01:29:08 +00:00
										 |  |  | 			if (values && PyList_Check(values)) { | 
					
						
							| 
									
										
										
										
											2010-09-19 14:02:45 +00: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; | 
					
						
							| 
									
										
										
										
											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 *); | 
					
						
							| 
									
										
										
										
											2018-06-04 08:54:17 +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); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						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
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					ret = PyObject_Call(pack, item_new, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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(); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					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(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Py_DECREF(calcsize); | 
					
						
							|  |  |  | 		Py_DECREF(pack); | 
					
						
							|  |  |  | 		Py_DECREF(unpack); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PyMem_FREE(sizes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2012-02-20 22:04:29 +00: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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* must be a 'type_name' object */ | 
					
						
							|  |  |  | 		pointer = PyObject_CallObject(as_pointer, NULL); | 
					
						
							|  |  |  | 		Py_DECREF(as_pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		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"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return result; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 		             "expected '%.200s' type found '%.200s' instead", | 
					
						
							|  |  |  | 		             type_name, Py_TYPE(value)->tp_name); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* PyC_FlagSet_* functions - so flags/sets can be interchanged in a generic way */ | 
					
						
							|  |  |  | #include "BLI_dynstr.h"
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *PyC_FlagSet_AsString(PyC_FlagSet *item) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	DynStr *dynstr = BLI_dynstr_new(); | 
					
						
							|  |  |  | 	PyC_FlagSet *e; | 
					
						
							|  |  |  | 	char *cstring; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (e = item; item->identifier; item++) { | 
					
						
							|  |  |  | 		BLI_dynstr_appendf(dynstr, (e == item) ? "'%s'" : ", '%s'", item->identifier); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cstring = BLI_dynstr_get_cstring(dynstr); | 
					
						
							|  |  |  | 	BLI_dynstr_free(dynstr); | 
					
						
							|  |  |  | 	return cstring; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  | 		const char *enum_str = PyC_FlagSet_AsString(item); | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  | 		             "%s: '%.200s' not found in (%s)", | 
					
						
							|  |  |  | 		             error_prefix, identifier, enum_str); | 
					
						
							|  |  |  | 		MEM_freeN((void *)enum_str); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* set looping */ | 
					
						
							|  |  |  | 	Py_ssize_t pos = 0; | 
					
						
							|  |  |  | 	Py_ssize_t hash = 0; | 
					
						
							|  |  |  | 	PyObject *key; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 09:15:46 +00:00
										 |  |  | 	*r_value = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (_PySet_NextEntry(value, &pos, &key, &hash)) { | 
					
						
							|  |  |  | 		const char *param = _PyUnicode_AsString(key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (PyC_FlagSet_ValueFromID(items, param, &ret, error_prefix) < 0) { | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		flag |= ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*r_value = flag; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *ret = PySet_New(NULL); | 
					
						
							|  |  |  | 	PyObject *pystr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for ( ; items->identifier; items++) { | 
					
						
							|  |  |  | 		if (items->value & flag) { | 
					
						
							|  |  |  | 			pystr = PyUnicode_FromString(items->identifier); | 
					
						
							|  |  |  | 			PySet_Add(ret, pystr); | 
					
						
							|  |  |  | 			Py_DECREF(pystr); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyC_MainModule_Backup(&main_mod); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	py_dict = PyC_DefaultNameSpace(filename); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (PyTuple_Check(retval)) { | 
					
						
							|  |  |  | 			/* Users my have typed in 10km, 2m
 | 
					
						
							|  |  |  | 			 * add up all values */ | 
					
						
							|  |  |  | 			int i; | 
					
						
							|  |  |  | 			val = 0.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			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); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		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
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyC_MainModule_Restore(main_mod); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-03 12:38:19 +10:00
										 |  |  | bool PyC_RunString_AsString(const char *imports[], const char *expr, const char *filename, char **r_value) | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11: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) { | 
					
						
							| 
									
										
										
										
											2017-03-18 12:19:03 +11:00
										 |  |  | 		ok = false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		const char *val; | 
					
						
							|  |  |  | 		Py_ssize_t val_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		val = _PyUnicode_AsStringAndSize(retval, &val_len); | 
					
						
							|  |  |  | 		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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Py_DECREF(retval); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyC_MainModule_Restore(main_mod); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ok; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int test = _PyLong_AsInt(value); | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int test = _PyLong_AsInt(value); | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int test = _PyLong_AsInt(value); | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ulong test = PyLong_AsUnsignedLong(value); | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ulong test = PyLong_AsUnsignedLong(value); | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ulong test = PyLong_AsUnsignedLong(value); | 
					
						
							|  |  |  | 	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 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-20 15:39:08 +10:00
										 |  |  | #ifdef __GNUC__
 | 
					
						
							|  |  |  | #  pragma warning(pop)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ |