diff options
author | Hans Goudey <h.goudey@me.com> | 2020-08-12 04:59:16 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2020-08-12 04:59:16 +0300 |
commit | ef11238c743e6985fe325280fb13e05d6ec27378 (patch) | |
tree | 1dd2605a676bee52296535825b99f000a9c255eb /source/blender/python/generic/py_capi_utils.c | |
parent | 1f768bbe4145daed111636ca09dd53b25b8d29b5 (diff) | |
parent | ec5f39208785c1bbe723054ffe69e1ac2ab470dd (diff) |
Merge branch 'master' into property-search-uiproperty-search-ui
Diffstat (limited to 'source/blender/python/generic/py_capi_utils.c')
-rw-r--r-- | source/blender/python/generic/py_capi_utils.c | 204 |
1 files changed, 153 insertions, 51 deletions
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 406dbdafe22..caae5c4e122 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -51,6 +51,10 @@ # include "BLI_math_base.h" /* isfinite() */ #endif +/* -------------------------------------------------------------------- */ +/** \name Fast Python to C Array Conversion for Primitive Types + * \{ */ + /* array utility function */ int PyC_AsArray_FAST(void *array, PyObject *value_fast, @@ -137,11 +141,12 @@ int PyC_AsArray(void *array, return ret; } +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Typed Tuple Packing * * \note See #PyC_Tuple_Pack_* macros that take multiple arguments. - * * \{ */ /* array utility function */ @@ -192,6 +197,10 @@ PyObject *PyC_Tuple_PackArray_Bool(const bool *array, uint len) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Tuple/List Filling + * \{ */ + /** * Caller needs to ensure tuple is uninitialized. * Handy for filling a tuple with None for eg. @@ -218,6 +227,12 @@ void PyC_List_Fill(PyObject *list, PyObject *value) } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Bool/Enum Argument Parsing + * \{ */ + /** * Use with PyArg_ParseTuple's "O&" formatting. * @@ -274,8 +289,16 @@ int PyC_CheckArgs_DeepCopy(PyObject *args) return PyArg_ParseTuple(args, "|O!:__deepcopy__", &PyDict_Type, &dummy_pydict) != 0; } +/** \} */ + #ifndef MATH_STANDALONE +/* -------------------------------------------------------------------- */ +/** \name Simple Printing (for debugging) + * + * These are useful to run directly from a debugger to be able to inspect the state. + * \{ */ + /* for debugging */ void PyC_ObSpit(const char *name, PyObject *var) { @@ -352,14 +375,33 @@ void PyC_StackSpit(void) 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); + + /* lame but handy */ + PyGILState_STATE gilstate = PyGILState_Ensure(); + PyRun_SimpleString("__import__('traceback').print_stack()"); + PyGILState_Release(gilstate); +} + +void PyC_StackPrint(/* FILE */ void *fp) +{ + PyThreadState *tstate = PyGILState_GetThisThreadState(); + if (tstate != NULL && tstate->frame != NULL) { + PyFrameObject *frame = tstate->frame; + do { + const int line = PyCode_Addr2Line(frame->f_code, frame->f_lasti); + const char *filename = _PyUnicode_AsString(frame->f_code->co_filename); + const char *funcname = _PyUnicode_AsString(frame->f_code->co_name); + fprintf(fp, " File \"%s\", line %d in %s\n", filename, line, funcname); + } while ((frame = frame->f_back)); } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Access Current Frame File Name & Line Number + * \{ */ + void PyC_FileAndNum(const char **r_filename, int *r_lineno) { PyFrameObject *frame; @@ -419,6 +461,12 @@ void PyC_FileAndNum_Safe(const char **r_filename, int *r_lineno) PyC_FileAndNum(r_filename, r_lineno); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Access Utilities + * \{ */ + /* Would be nice if python had this built in */ PyObject *PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...) { @@ -447,6 +495,12 @@ PyObject *PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...) return item; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Frozen Set Creation + * \{ */ + PyObject *PyC_FrozenSetFromStrings(const char **strings) { const char **str; @@ -463,6 +517,12 @@ PyObject *PyC_FrozenSetFromStrings(const char **strings) return ret; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Exception Utilities + * \{ */ + /** * Similar to #PyErr_Format(), * @@ -528,6 +588,12 @@ void PyC_Err_PrintWithFunc(PyObject *py_func) _PyUnicode_AsString(((PyFunctionObject *)py_func)->func_name)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Exception Buffer Access + * \{ */ + /* returns the exception string as a new PyUnicode object, depends on external traceback module */ # if 0 @@ -673,6 +739,14 @@ PyObject *PyC_ExceptionBuffer_Simple(void) return string_io_buf; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Unicode Conversion + * + * In some cases we need to coerce strings, avoid doing this inline. + * \{ */ + /* string conversion, escape non-unicode chars, coerce must be set to NULL */ const char *PyC_UnicodeAsByteAndSize(PyObject *py_str, Py_ssize_t *size, PyObject **coerce) { @@ -685,22 +759,20 @@ const char *PyC_UnicodeAsByteAndSize(PyObject *py_str, Py_ssize_t *size, PyObjec * chars since blender doesn't limit this */ 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; - } + PyErr_Clear(); + + if (PyBytes_Check(py_str)) { + *size = PyBytes_GET_SIZE(py_str); + return PyBytes_AS_STRING(py_str); + } + if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) { + *size = PyBytes_GET_SIZE(*coerce); + return PyBytes_AS_STRING(*coerce); } + + /* leave error raised from EncodeFS */ + return NULL; } const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) @@ -714,20 +786,18 @@ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) * chars since blender doesn't limit this. */ return result; } - else { - PyErr_Clear(); - if (PyBytes_Check(py_str)) { - return PyBytes_AS_STRING(py_str); - } - else if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) { - return PyBytes_AS_STRING(*coerce); - } - else { - /* leave error raised from EncodeFS */ - return NULL; - } + PyErr_Clear(); + + if (PyBytes_Check(py_str)) { + return PyBytes_AS_STRING(py_str); } + if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) { + return PyBytes_AS_STRING(*coerce); + } + + /* leave error raised from EncodeFS */ + return NULL; } PyObject *PyC_UnicodeFromByteAndSize(const char *str, Py_ssize_t size) @@ -738,12 +808,11 @@ PyObject *PyC_UnicodeFromByteAndSize(const char *str, Py_ssize_t size) * chars since blender doesn't limit this */ return result; } - else { - PyErr_Clear(); - /* this means paths will always be accessible once converted, on all OS's */ - result = PyUnicode_DecodeFSDefaultAndSize(str, size); - return result; - } + + PyErr_Clear(); + /* this means paths will always be accessible once converted, on all OS's */ + result = PyUnicode_DecodeFSDefaultAndSize(str, size); + return result; } PyObject *PyC_UnicodeFromByte(const char *str) @@ -751,6 +820,12 @@ PyObject *PyC_UnicodeFromByte(const char *str) return PyC_UnicodeFromByteAndSize(str, strlen(str)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Name Space Creation/Manipulation + * \{ */ + /***************************************************************************** * Description: This function creates a new Python dictionary object. * note: dict is owned by sys.modules["__main__"] module, reference is borrowed @@ -816,6 +891,12 @@ void PyC_MainModule_Restore(PyObject *main_mod) Py_XDECREF(main_mod); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #Py_SetPythonHome Wrapper + * \{ */ + /** * - Must be called before #Py_Initialize. * - Expects output of `BKE_appdir_folder_id(BLENDER_PYTHON, NULL)`. @@ -867,6 +948,12 @@ bool PyC_IsInterpreterActive(void) return (PyThreadState_GetDict() != NULL); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #Py_SetPythonHome Wrapper + * \{ */ + /* Would be nice if python had this built in * See: https://wiki.blender.org/wiki/Tools/Debugging/PyFromC */ @@ -1043,15 +1130,22 @@ void *PyC_RNA_AsPointer(PyObject *value, const char *type_name) return result; } - else { - PyErr_Format(PyExc_TypeError, - "expected '%.200s' type found '%.200s' instead", - type_name, - Py_TYPE(value)->tp_name); - return NULL; - } + + PyErr_Format(PyExc_TypeError, + "expected '%.200s' type found '%.200s' instead", + type_name, + Py_TYPE(value)->tp_name); + return NULL; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Flag Set Utilities (#PyC_FlagSet) + * + * Convert to/from Python set of strings to an int flag. + * \{ */ + PyObject *PyC_FlagSet_AsString(PyC_FlagSet *item) { PyObject *py_items = PyList_New(0); @@ -1152,6 +1246,12 @@ PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag) return ret; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Run String (Evaluate to Primitive Types) + * \{ */ + /** * \return success * @@ -1315,6 +1415,8 @@ bool PyC_RunString_AsString(const char *imports[], return PyC_RunString_AsStringAndSize(imports, expr, filename, r_value, &value_size); } +/** \} */ + #endif /* #ifndef MATH_STANDALONE */ /* -------------------------------------------------------------------- */ @@ -1402,6 +1504,12 @@ uint32_t PyC_Long_AsU32(PyObject *value) * PyC_Long_AsU64 */ +#ifdef __GNUC__ +# pragma warning(pop) +#endif + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Py_buffer Utils * @@ -1478,9 +1586,3 @@ bool PyC_StructFmt_type_is_bool(char format) } /** \} */ - -#ifdef __GNUC__ -# pragma warning(pop) -#endif - -/** \} */ |