--- source/blender/python/generic/py_capi_utils.h.orig 2015-03-25 21:01:17.000000000 +1000 +++ source/blender/python/generic/py_capi_utils.h 2016-01-07 23:41:12.118573813 +1000 @@ -32,13 +32,18 @@ void PyC_LineSpit(void); void PyC_StackSpit(void); PyObject * PyC_ExceptionBuffer(void); +PyObject * PyC_ExceptionBuffer_Simple(void); PyObject * PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...); PyObject * PyC_FrozenSetFromStrings(const char **strings); PyObject * PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...); void PyC_FileAndNum(const char **filename, int *lineno); void PyC_FileAndNum_Safe(const char **filename, int *lineno); /* checks python is running */ -int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length, - const PyTypeObject *type, const bool is_double, const char *error_prefix); +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); +int PyC_AsArray( + void *array, PyObject *value, const Py_ssize_t length, + const PyTypeObject *type, const bool is_double, const char *error_prefix); PyObject * PyC_FromArray(const void *array, int length, const PyTypeObject *type, const bool is_double, const char *error_prefix); void PyC_Tuple_Fill(PyObject *tuple, PyObject *value); @@ -74,6 +79,8 @@ int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix); PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag); -int PyC_RunString_AsNumber(const char *expr, double *value, const char *filename); +bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filename); + +int PyC_ParseBool(PyObject *o, void *p); #endif /* __PY_CAPI_UTILS_H__ */ --- source/blender/python/generic/py_capi_utils.c.orig 2015-03-25 21:01:17.000000000 +1000 +++ source/blender/python/generic/py_capi_utils.c 2016-01-07 23:41:12.114573720 +1000 @@ -29,7 +29,6 @@ * BLI_string_utf8() for unicode conversion. */ - #include #include @@ -37,10 +36,12 @@ #include "py_capi_utils.h" -#include "../generic/python_utildefines.h" +#include "python_utildefines.h" +#ifndef MATH_STANDALONE /* only for BLI_strncpy_wchar_from_utf8, should replace with py funcs but too late in release now */ #include "BLI_string_utf8.h" +#endif #ifdef _WIN32 #include "BLI_path_util.h" /* BLI_setenv() */ @@ -48,21 +49,17 @@ #endif /* array utility function */ -int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length, - const PyTypeObject *type, const bool is_double, const char *error_prefix) +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) { - PyObject *value_fast; - Py_ssize_t value_len; + const Py_ssize_t value_len = PySequence_Fast_GET_SIZE(value_fast); + PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); Py_ssize_t i; - if (!(value_fast = PySequence_Fast(value, error_prefix))) { - return -1; - } - - value_len = PySequence_Fast_GET_SIZE(value_fast); + BLI_assert(PyList_Check(value_fast) || PyTuple_Check(value_fast)); if (value_len != length) { - Py_DECREF(value); PyErr_Format(PyExc_TypeError, "%.200s: invalid sequence length. expected %d, got %d", error_prefix, length, value_len); @@ -74,13 +71,13 @@ if (is_double) { double *array_double = array; for (i = 0; i < length; i++) { - array_double[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i)); + array_double[i] = PyFloat_AsDouble(value_fast_items[i]); } } else { float *array_float = array; for (i = 0; i < length; i++) { - array_float[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i)); + array_float[i] = PyFloat_AsDouble(value_fast_items[i]); } } } @@ -88,25 +85,22 @@ /* could use is_double for 'long int' but no use now */ int *array_int = array; for (i = 0; i < length; i++) { - array_int[i] = PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)); + array_int[i] = PyLong_AsLong(value_fast_items[i]); } } else if (type == &PyBool_Type) { int *array_bool = array; for (i = 0; i < length; i++) { - array_bool[i] = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)) != 0); + array_bool[i] = (PyLong_AsLong(value_fast_items[i]) != 0); } } else { - Py_DECREF(value_fast); PyErr_Format(PyExc_TypeError, "%s: internal error %s is invalid", error_prefix, type->tp_name); return -1; } - Py_DECREF(value_fast); - if (PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "%s: one or more items could not be used as a %s", @@ -117,6 +111,22 @@ return 0; } +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; +} + /* array utility function */ PyObject *PyC_FromArray(const void *array, int length, const PyTypeObject *type, const bool is_double, const char *error_prefix) @@ -191,6 +201,27 @@ } } +/** + * Use with PyArg_ParseTuple's "O&" formatting. + */ +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; +} + + +#ifndef MATH_STANDALONE + /* for debugging */ void PyC_ObSpit(const char *name, PyObject *var) { @@ -478,6 +509,34 @@ } #endif +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( + "", Py_TYPE(error_value)->tp_name); + } + + PyErr_Restore(error_type, error_value, error_traceback); + + PyErr_Print(); + PyErr_Clear(); + return string_io_buf; +} /* string conversion, escape non-unicode chars, coerce must be set to NULL */ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) @@ -497,15 +556,6 @@ if (PyBytes_Check(py_str)) { return PyBytes_AS_STRING(py_str); } -#ifdef WIN32 - /* bug [#31856] oddly enough, Python3.2 --> 3.3 on Windows will throw an - * exception here this needs to be fixed in python: - * see: bugs.python.org/issue15859 */ - else if (!PyUnicode_Check(py_str)) { - PyErr_BadArgument(); - return NULL; - } -#endif else if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) { return PyBytes_AS_STRING(*coerce); } @@ -629,7 +679,8 @@ bool PyC_IsInterpreterActive(void) { - return (((PyThreadState *)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL); + /* instead of PyThreadState_Get, which calls Py_FatalError */ + return (PyThreadState_GetDict() != NULL); } /* Would be nice if python had this built in @@ -673,7 +724,7 @@ } if (ret == NULL) { - printf("PyC_InlineRun error, line:%d\n", __LINE__); + printf("%s error, line:%d\n", __func__, __LINE__); PyErr_Print(); PyErr_Clear(); @@ -747,7 +798,7 @@ Py_DECREF(ret); } else { - printf("PyC_InlineRun error on arg '%d', line:%d\n", i, __LINE__); + printf("%s error on arg '%d', line:%d\n", __func__, i, __LINE__); PyC_ObSpit("failed converting:", item_new); PyErr_Print(); PyErr_Clear(); @@ -758,11 +809,11 @@ va_end(vargs); } else { - printf("PyC_InlineRun error, 'values' not a list, line:%d\n", __LINE__); + printf("%s error, 'values' not a list, line:%d\n", __func__, __LINE__); } } else { - printf("PyC_InlineRun error line:%d\n", __LINE__); + printf("%s error line:%d\n", __func__, __LINE__); PyErr_Print(); PyErr_Clear(); } @@ -920,14 +971,14 @@ /** - * \return -1 on error, else 0 + * \return success * * \note it is caller's responsibility to acquire & release GIL! */ -int PyC_RunString_AsNumber(const char *expr, double *value, const char *filename) +bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filename) { PyObject *py_dict, *mod, *retval; - int error_ret = 0; + bool ok = true; PyObject *main_mod = NULL; PyC_MainModule_Backup(&main_mod); @@ -947,7 +998,7 @@ retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict); if (retval == NULL) { - error_ret = -1; + ok = false; } else { double val; @@ -973,7 +1024,7 @@ Py_DECREF(retval); if (val == -1 && PyErr_Occurred()) { - error_ret = -1; + ok = false; } else if (!finite(val)) { *value = 0.0; @@ -985,5 +1036,7 @@ PyC_MainModule_Restore(main_mod); - return error_ret; + return ok; } + +#endif /* #ifndef MATH_STANDALONE */