diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/python/intern | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/python/intern')
67 files changed, 18464 insertions, 17618 deletions
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 95f3edb8045..7eb008efeef 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -19,293 +19,293 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - .. - ../../blenkernel - ../../blenlib - ../../blenloader - ../../blentranslation - ../../editors/include - ../../gpu - ../../imbuf - ../../makesdna - ../../makesrna - ../../windowmanager - ../../../../intern/clog - ../../../../intern/guardedalloc - ../../../../intern/opencolorio + .. + ../../blenkernel + ../../blenlib + ../../blenloader + ../../blentranslation + ../../editors/include + ../../gpu + ../../imbuf + ../../makesdna + ../../makesrna + ../../windowmanager + ../../../../intern/clog + ../../../../intern/guardedalloc + ../../../../intern/opencolorio ) set(INC_SYS - ${PYTHON_INCLUDE_DIRS} + ${PYTHON_INCLUDE_DIRS} ) set(SRC - bpy.c - bpy_app.c - bpy_app_alembic.c - bpy_app_build_options.c - bpy_app_ffmpeg.c - bpy_app_handlers.c - bpy_app_icons.c - bpy_app_ocio.c - bpy_app_oiio.c - bpy_app_opensubdiv.c - bpy_app_openvdb.c - bpy_app_sdl.c - bpy_app_timers.c - bpy_app_translations.c - bpy_capi_utils.c - bpy_driver.c - bpy_gizmo_wrap.c - bpy_interface.c - bpy_interface_atexit.c - bpy_intern_string.c - bpy_library_load.c - bpy_library_write.c - bpy_msgbus.c - bpy_operator.c - bpy_operator_wrap.c - bpy_path.c - bpy_props.c - bpy_rna.c - bpy_rna_anim.c - bpy_rna_array.c - bpy_rna_callback.c - bpy_rna_driver.c - bpy_rna_gizmo.c - bpy_rna_id_collection.c - bpy_traceback.c - bpy_utils_previews.c - bpy_utils_units.c - stubs.c - - bpy.h - bpy_app.h - bpy_app_alembic.h - bpy_app_build_options.h - bpy_app_ffmpeg.h - bpy_app_handlers.h - bpy_app_icons.h - bpy_app_ocio.h - bpy_app_oiio.h - bpy_app_opensubdiv.h - bpy_app_openvdb.h - bpy_app_sdl.h - bpy_app_timers.h - bpy_app_translations.h - bpy_capi_utils.h - bpy_driver.h - bpy_gizmo_wrap.h - bpy_intern_string.h - bpy_library.h - bpy_msgbus.h - bpy_operator.h - bpy_operator_wrap.h - bpy_path.h - bpy_props.h - bpy_rna.h - bpy_rna_anim.h - bpy_rna_callback.h - bpy_rna_driver.h - bpy_rna_gizmo.h - bpy_rna_id_collection.h - bpy_traceback.h - bpy_utils_previews.h - bpy_utils_units.h - ../BPY_extern.h - ../BPY_extern_clog.h + bpy.c + bpy_app.c + bpy_app_alembic.c + bpy_app_build_options.c + bpy_app_ffmpeg.c + bpy_app_handlers.c + bpy_app_icons.c + bpy_app_ocio.c + bpy_app_oiio.c + bpy_app_opensubdiv.c + bpy_app_openvdb.c + bpy_app_sdl.c + bpy_app_timers.c + bpy_app_translations.c + bpy_capi_utils.c + bpy_driver.c + bpy_gizmo_wrap.c + bpy_interface.c + bpy_interface_atexit.c + bpy_intern_string.c + bpy_library_load.c + bpy_library_write.c + bpy_msgbus.c + bpy_operator.c + bpy_operator_wrap.c + bpy_path.c + bpy_props.c + bpy_rna.c + bpy_rna_anim.c + bpy_rna_array.c + bpy_rna_callback.c + bpy_rna_driver.c + bpy_rna_gizmo.c + bpy_rna_id_collection.c + bpy_traceback.c + bpy_utils_previews.c + bpy_utils_units.c + stubs.c + + bpy.h + bpy_app.h + bpy_app_alembic.h + bpy_app_build_options.h + bpy_app_ffmpeg.h + bpy_app_handlers.h + bpy_app_icons.h + bpy_app_ocio.h + bpy_app_oiio.h + bpy_app_opensubdiv.h + bpy_app_openvdb.h + bpy_app_sdl.h + bpy_app_timers.h + bpy_app_translations.h + bpy_capi_utils.h + bpy_driver.h + bpy_gizmo_wrap.h + bpy_intern_string.h + bpy_library.h + bpy_msgbus.h + bpy_operator.h + bpy_operator_wrap.h + bpy_path.h + bpy_props.h + bpy_rna.h + bpy_rna_anim.h + bpy_rna_callback.h + bpy_rna_driver.h + bpy_rna_gizmo.h + bpy_rna_id_collection.h + bpy_traceback.h + bpy_utils_previews.h + bpy_utils_units.h + ../BPY_extern.h + ../BPY_extern_clog.h ) set(LIB - bf_editor_animation - bf_editor_interface - bf_editor_space_api - bf_python_gpu + bf_editor_animation + bf_editor_interface + bf_editor_space_api + bf_python_gpu ) # only to check if buildinfo is available if(WITH_BUILDINFO) - add_definitions(-DBUILD_DATE) + add_definitions(-DBUILD_DATE) endif() if(WITH_PYTHON_MODULE) - add_definitions(-DWITH_PYTHON_MODULE) + add_definitions(-DWITH_PYTHON_MODULE) endif() if(WITH_PYTHON_SAFETY) - add_definitions(-DWITH_PYTHON_SAFETY) + add_definitions(-DWITH_PYTHON_SAFETY) endif() if(WITH_AUDASPACE) - add_definitions(-DWITH_AUDASPACE) + add_definitions(-DWITH_AUDASPACE) endif() if(WITH_BULLET) - add_definitions(-DWITH_BULLET) + add_definitions(-DWITH_BULLET) endif() if(WITH_CODEC_AVI) - add_definitions(-DWITH_AVI) + add_definitions(-DWITH_AVI) endif() if(WITH_CODEC_FFMPEG) - list(APPEND INC_SYS - ${FFMPEG_INCLUDE_DIRS} - ) - add_definitions(-DWITH_FFMPEG) + list(APPEND INC_SYS + ${FFMPEG_INCLUDE_DIRS} + ) + add_definitions(-DWITH_FFMPEG) endif() if(WITH_CODEC_SNDFILE) - add_definitions(-DWITH_SNDFILE) + add_definitions(-DWITH_SNDFILE) endif() if(WITH_COMPOSITOR) - add_definitions(-DWITH_COMPOSITOR) + add_definitions(-DWITH_COMPOSITOR) endif() if(WITH_CYCLES) - list(APPEND INC - ../../../../intern/cycles/blender - ) - list(APPEND LIB - bf_intern_cycles - ) - add_definitions(-DWITH_CYCLES) + list(APPEND INC + ../../../../intern/cycles/blender + ) + list(APPEND LIB + bf_intern_cycles + ) + add_definitions(-DWITH_CYCLES) endif() if(WITH_CYCLES_OSL) - add_definitions(-DWITH_CYCLES_OSL) + add_definitions(-DWITH_CYCLES_OSL) endif() if(WITH_CYCLES_EMBREE) - add_definitions(-DWITH_CYCLES_EMBREE) + add_definitions(-DWITH_CYCLES_EMBREE) endif() if(WITH_FREESTYLE) - list(APPEND INC - ../../freestyle/intern/python - ) - add_definitions(-DWITH_FREESTYLE) + list(APPEND INC + ../../freestyle/intern/python + ) + add_definitions(-DWITH_FREESTYLE) endif() if(WITH_IMAGE_CINEON) - add_definitions(-DWITH_CINEON) + add_definitions(-DWITH_CINEON) endif() if(WITH_IMAGE_DDS) - add_definitions(-DWITH_DDS) + add_definitions(-DWITH_DDS) endif() if(WITH_IMAGE_HDR) - add_definitions(-DWITH_HDR) + add_definitions(-DWITH_HDR) endif() if(WITH_IMAGE_OPENEXR) - add_definitions(-DWITH_OPENEXR) + add_definitions(-DWITH_OPENEXR) endif() if(WITH_OPENIMAGEIO) - add_definitions(-DWITH_OPENIMAGEIO) + add_definitions(-DWITH_OPENIMAGEIO) endif() if(WITH_IMAGE_OPENJPEG) - add_definitions(-DWITH_OPENJPEG) + add_definitions(-DWITH_OPENJPEG) endif() if(WITH_IMAGE_TIFF) - add_definitions(-DWITH_TIFF) + add_definitions(-DWITH_TIFF) endif() if(WITH_INPUT_NDOF) - add_definitions(-DWITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) endif() if(WITH_INTERNATIONAL) - add_definitions(-DWITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) endif() if(WITH_OPENAL) - add_definitions(-DWITH_OPENAL) + add_definitions(-DWITH_OPENAL) endif() if(WITH_SDL) - list(APPEND INC_SYS - ${SDL_INCLUDE_DIR} - ) - add_definitions(-DWITH_SDL) + list(APPEND INC_SYS + ${SDL_INCLUDE_DIR} + ) + add_definitions(-DWITH_SDL) endif() if(WITH_SDL_DYNLOAD) - list(APPEND INC - ../../../../extern/sdlew/include - ) - add_definitions(-DWITH_SDL_DYNLOAD) + list(APPEND INC + ../../../../extern/sdlew/include + ) + add_definitions(-DWITH_SDL_DYNLOAD) endif() if(WITH_JACK) - add_definitions(-DWITH_JACK) + add_definitions(-DWITH_JACK) endif() if(WITH_LIBMV) - add_definitions(-DWITH_LIBMV) + add_definitions(-DWITH_LIBMV) endif() if(WITH_MOD_FLUID) - add_definitions(-DWITH_MOD_FLUID) + add_definitions(-DWITH_MOD_FLUID) endif() if(WITH_MOD_OCEANSIM) - add_definitions(-DWITH_OCEANSIM) + add_definitions(-DWITH_OCEANSIM) endif() if(WITH_MOD_REMESH) - add_definitions(-DWITH_MOD_REMESH) + add_definitions(-DWITH_MOD_REMESH) endif() if(WITH_MOD_SMOKE) - add_definitions(-DWITH_SMOKE) + add_definitions(-DWITH_SMOKE) endif() if(WITH_OPENCOLLADA) - add_definitions(-DWITH_COLLADA) + add_definitions(-DWITH_COLLADA) endif() if(WITH_ALEMBIC) - add_definitions(-DWITH_ALEMBIC) + add_definitions(-DWITH_ALEMBIC) endif() if(WITH_OPENCOLORIO) - add_definitions(-DWITH_OCIO) + add_definitions(-DWITH_OCIO) endif() if(WITH_OPENVDB) - add_definitions(-DWITH_OPENVDB) - list(APPEND INC - ../../../../intern/openvdb - ) + add_definitions(-DWITH_OPENVDB) + list(APPEND INC + ../../../../intern/openvdb + ) endif() if(WITH_ALEMBIC) - add_definitions(-DWITH_ALEMBIC) - list(APPEND INC - ../../alembic - ) + add_definitions(-DWITH_ALEMBIC) + list(APPEND INC + ../../alembic + ) endif() if(WITH_OPENIMAGEIO) - add_definitions(-DWITH_OPENIMAGEIO) - list(APPEND INC - ../../imbuf/intern/oiio - ) + add_definitions(-DWITH_OPENIMAGEIO) + list(APPEND INC + ../../imbuf/intern/oiio + ) endif() if(WITH_OPENSUBDIV) - add_definitions(-DWITH_OPENSUBDIV) - list(APPEND INC - ../../../../intern/opensubdiv - ) + add_definitions(-DWITH_OPENSUBDIV) + list(APPEND INC + ../../../../intern/opensubdiv + ) endif() add_definitions(${GL_DEFINITIONS}) diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index f67ed1a3713..ed576c553e4 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -61,320 +61,347 @@ PyObject *bpy_package_py = NULL; PyDoc_STRVAR(bpy_script_paths_doc, -".. function:: script_paths()\n" -"\n" -" Return 2 paths to blender scripts directories.\n" -"\n" -" :return: (system, user) strings will be empty when not found.\n" -" :rtype: tuple of strings\n" -); + ".. function:: script_paths()\n" + "\n" + " Return 2 paths to blender scripts directories.\n" + "\n" + " :return: (system, user) strings will be empty when not found.\n" + " :rtype: tuple of strings\n"); static PyObject *bpy_script_paths(PyObject *UNUSED(self)) { - PyObject *ret = PyTuple_New(2); - PyObject *item; - const char *path; - - path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, NULL); - item = PyC_UnicodeFromByte(path ? path : ""); - BLI_assert(item != NULL); - PyTuple_SET_ITEM(ret, 0, item); - path = BKE_appdir_folder_id(BLENDER_USER_SCRIPTS, NULL); - item = PyC_UnicodeFromByte(path ? path : ""); - BLI_assert(item != NULL); - PyTuple_SET_ITEM(ret, 1, item); - - return ret; + PyObject *ret = PyTuple_New(2); + PyObject *item; + const char *path; + + path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, NULL); + item = PyC_UnicodeFromByte(path ? path : ""); + BLI_assert(item != NULL); + PyTuple_SET_ITEM(ret, 0, item); + path = BKE_appdir_folder_id(BLENDER_USER_SCRIPTS, NULL); + item = PyC_UnicodeFromByte(path ? path : ""); + BLI_assert(item != NULL); + PyTuple_SET_ITEM(ret, 1, item); + + return ret; } static bool bpy_blend_paths_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src) { - PyList_APPEND((PyObject *)userdata, PyC_UnicodeFromByte(path_src)); - return false; /* never edits the path */ + PyList_APPEND((PyObject *)userdata, PyC_UnicodeFromByte(path_src)); + return false; /* never edits the path */ } PyDoc_STRVAR(bpy_blend_paths_doc, -".. function:: blend_paths(absolute=False, packed=False, local=False)\n" -"\n" -" Returns a list of paths to external files referenced by the loaded .blend file.\n" -"\n" -" :arg absolute: When true the paths returned are made absolute.\n" -" :type absolute: boolean\n" -" :arg packed: When true skip file paths for packed data.\n" -" :type packed: boolean\n" -" :arg local: When true skip linked library paths.\n" -" :type local: boolean\n" -" :return: path list.\n" -" :rtype: list of strings\n" -); + ".. function:: blend_paths(absolute=False, packed=False, local=False)\n" + "\n" + " Returns a list of paths to external files referenced by the loaded .blend file.\n" + "\n" + " :arg absolute: When true the paths returned are made absolute.\n" + " :type absolute: boolean\n" + " :arg packed: When true skip file paths for packed data.\n" + " :type packed: boolean\n" + " :arg local: When true skip linked library paths.\n" + " :type local: boolean\n" + " :return: path list.\n" + " :rtype: list of strings\n"); static PyObject *bpy_blend_paths(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - int flag = 0; - PyObject *list; - - bool absolute = false; - bool packed = false; - bool local = false; - - static const char *_keywords[] = {"absolute", "packed", "local", NULL}; - static _PyArg_Parser _parser = {"|O&O&O&:blend_paths", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - PyC_ParseBool, &absolute, - PyC_ParseBool, &packed, - PyC_ParseBool, &local)) - { - return NULL; - } - - if (absolute) { - flag |= BKE_BPATH_TRAVERSE_ABS; - } - if (!packed) { - flag |= BKE_BPATH_TRAVERSE_SKIP_PACKED; - } - if (local) { - flag |= BKE_BPATH_TRAVERSE_SKIP_LIBRARY; - } - - list = PyList_New(0); - - BKE_bpath_traverse_main(G_MAIN, bpy_blend_paths_visit_cb, flag, (void *)list); - - return list; + int flag = 0; + PyObject *list; + + bool absolute = false; + bool packed = false; + bool local = false; + + static const char *_keywords[] = {"absolute", "packed", "local", NULL}; + static _PyArg_Parser _parser = {"|O&O&O&:blend_paths", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + PyC_ParseBool, + &absolute, + PyC_ParseBool, + &packed, + PyC_ParseBool, + &local)) { + return NULL; + } + + if (absolute) { + flag |= BKE_BPATH_TRAVERSE_ABS; + } + if (!packed) { + flag |= BKE_BPATH_TRAVERSE_SKIP_PACKED; + } + if (local) { + flag |= BKE_BPATH_TRAVERSE_SKIP_LIBRARY; + } + + list = PyList_New(0); + + BKE_bpath_traverse_main(G_MAIN, bpy_blend_paths_visit_cb, flag, (void *)list); + + return list; } - // PyDoc_STRVAR(bpy_user_resource_doc[] = // now in bpy/utils.py static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - const char *type; - const char *subdir = NULL; - int folder_id; - - const char *path; - - static const char *_keywords[] = {"type", "subdir", NULL}; - static _PyArg_Parser _parser = {"s|s:user_resource", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &type, &subdir)) - { - return NULL; - } - - /* stupid string compare */ - if (STREQ(type, "DATAFILES")) { folder_id = BLENDER_USER_DATAFILES; } - else if (STREQ(type, "CONFIG")) { folder_id = BLENDER_USER_CONFIG; } - else if (STREQ(type, "SCRIPTS")) { folder_id = BLENDER_USER_SCRIPTS; } - else if (STREQ(type, "AUTOSAVE")) { folder_id = BLENDER_USER_AUTOSAVE; } - else { - PyErr_SetString(PyExc_ValueError, "invalid resource argument"); - return NULL; - } - - /* same logic as BKE_appdir_folder_id_create(), but best leave it up to the script author to create */ - path = BKE_appdir_folder_id_user_notest(folder_id, subdir); - - return PyC_UnicodeFromByte(path ? path : ""); + const char *type; + const char *subdir = NULL; + int folder_id; + + const char *path; + + static const char *_keywords[] = {"type", "subdir", NULL}; + static _PyArg_Parser _parser = {"s|s:user_resource", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &type, &subdir)) { + return NULL; + } + + /* stupid string compare */ + if (STREQ(type, "DATAFILES")) { + folder_id = BLENDER_USER_DATAFILES; + } + else if (STREQ(type, "CONFIG")) { + folder_id = BLENDER_USER_CONFIG; + } + else if (STREQ(type, "SCRIPTS")) { + folder_id = BLENDER_USER_SCRIPTS; + } + else if (STREQ(type, "AUTOSAVE")) { + folder_id = BLENDER_USER_AUTOSAVE; + } + else { + PyErr_SetString(PyExc_ValueError, "invalid resource argument"); + return NULL; + } + + /* same logic as BKE_appdir_folder_id_create(), but best leave it up to the script author to create */ + path = BKE_appdir_folder_id_user_notest(folder_id, subdir); + + return PyC_UnicodeFromByte(path ? path : ""); } -PyDoc_STRVAR(bpy_resource_path_doc, -".. function:: resource_path(type, major=bpy.app.version[0], minor=bpy.app.version[1])\n" -"\n" -" Return the base path for storing system files.\n" -"\n" -" :arg type: string in ['USER', 'LOCAL', 'SYSTEM'].\n" -" :type type: string\n" -" :arg major: major version, defaults to current.\n" -" :type major: int\n" -" :arg minor: minor version, defaults to current.\n" -" :type minor: string\n" -" :return: the resource path (not necessarily existing).\n" -" :rtype: string\n" -); +PyDoc_STRVAR( + bpy_resource_path_doc, + ".. function:: resource_path(type, major=bpy.app.version[0], minor=bpy.app.version[1])\n" + "\n" + " Return the base path for storing system files.\n" + "\n" + " :arg type: string in ['USER', 'LOCAL', 'SYSTEM'].\n" + " :type type: string\n" + " :arg major: major version, defaults to current.\n" + " :type major: int\n" + " :arg minor: minor version, defaults to current.\n" + " :type minor: string\n" + " :return: the resource path (not necessarily existing).\n" + " :rtype: string\n"); static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - const char *type; - int major = BLENDER_VERSION / 100, minor = BLENDER_VERSION % 100; - int folder_id; - const char *path; - - static const char *_keywords[] = {"type", "major", "minor", NULL}; - static _PyArg_Parser _parser = {"s|ii:resource_path", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &type, &major, &minor)) - { - return NULL; - } - - /* stupid string compare */ - if (STREQ(type, "USER")) { folder_id = BLENDER_RESOURCE_PATH_USER; } - else if (STREQ(type, "LOCAL")) { folder_id = BLENDER_RESOURCE_PATH_LOCAL; } - else if (STREQ(type, "SYSTEM")) { folder_id = BLENDER_RESOURCE_PATH_SYSTEM; } - else { - PyErr_SetString(PyExc_ValueError, "invalid resource argument"); - return NULL; - } - - path = BKE_appdir_folder_id_version(folder_id, (major * 100) + minor, false); - - return PyC_UnicodeFromByte(path ? path : ""); + const char *type; + int major = BLENDER_VERSION / 100, minor = BLENDER_VERSION % 100; + int folder_id; + const char *path; + + static const char *_keywords[] = {"type", "major", "minor", NULL}; + static _PyArg_Parser _parser = {"s|ii:resource_path", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &type, &major, &minor)) { + return NULL; + } + + /* stupid string compare */ + if (STREQ(type, "USER")) { + folder_id = BLENDER_RESOURCE_PATH_USER; + } + else if (STREQ(type, "LOCAL")) { + folder_id = BLENDER_RESOURCE_PATH_LOCAL; + } + else if (STREQ(type, "SYSTEM")) { + folder_id = BLENDER_RESOURCE_PATH_SYSTEM; + } + else { + PyErr_SetString(PyExc_ValueError, "invalid resource argument"); + return NULL; + } + + path = BKE_appdir_folder_id_version(folder_id, (major * 100) + minor, false); + + return PyC_UnicodeFromByte(path ? path : ""); } PyDoc_STRVAR(bpy_escape_identifier_doc, -".. function:: escape_identifier(string)\n" -"\n" -" Simple string escaping function used for animation paths.\n" -"\n" -" :arg string: text\n" -" :type string: string\n" -" :return: The escaped string.\n" -" :rtype: string\n" -); + ".. function:: escape_identifier(string)\n" + "\n" + " Simple string escaping function used for animation paths.\n" + "\n" + " :arg string: text\n" + " :type string: string\n" + " :return: The escaped string.\n" + " :rtype: string\n"); static PyObject *bpy_escape_identifier(PyObject *UNUSED(self), PyObject *value) { - const char *value_str; - Py_ssize_t value_str_len; + const char *value_str; + Py_ssize_t value_str_len; - char *value_escape_str; - Py_ssize_t value_escape_str_len; - PyObject *value_escape; - size_t size; + char *value_escape_str; + Py_ssize_t value_escape_str_len; + PyObject *value_escape; + size_t size; - value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); + value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); - if (value_str == NULL) { - PyErr_SetString(PyExc_TypeError, "expected a string"); - return NULL; - } + if (value_str == NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string"); + return NULL; + } - size = (value_str_len * 2) + 1; - value_escape_str = PyMem_MALLOC(size); - value_escape_str_len = BLI_strescape(value_escape_str, value_str, size); + size = (value_str_len * 2) + 1; + value_escape_str = PyMem_MALLOC(size); + value_escape_str_len = BLI_strescape(value_escape_str, value_str, size); - if (value_escape_str_len == value_str_len) { - Py_INCREF(value); - value_escape = value; - } - else { - value_escape = PyUnicode_FromStringAndSize(value_escape_str, value_escape_str_len); - } + if (value_escape_str_len == value_str_len) { + Py_INCREF(value); + value_escape = value; + } + else { + value_escape = PyUnicode_FromStringAndSize(value_escape_str, value_escape_str_len); + } - PyMem_FREE(value_escape_str); + PyMem_FREE(value_escape_str); - return value_escape; + return value_escape; } -static PyMethodDef meth_bpy_script_paths = - {"script_paths", (PyCFunction)bpy_script_paths, METH_NOARGS, bpy_script_paths_doc}; -static PyMethodDef meth_bpy_blend_paths = - {"blend_paths", (PyCFunction)bpy_blend_paths, METH_VARARGS | METH_KEYWORDS, bpy_blend_paths_doc}; -static PyMethodDef meth_bpy_user_resource = - {"user_resource", (PyCFunction)bpy_user_resource, METH_VARARGS | METH_KEYWORDS, NULL}; -static PyMethodDef meth_bpy_resource_path = - {"resource_path", (PyCFunction)bpy_resource_path, METH_VARARGS | METH_KEYWORDS, bpy_resource_path_doc}; -static PyMethodDef meth_bpy_escape_identifier = - {"escape_identifier", (PyCFunction)bpy_escape_identifier, METH_O, bpy_escape_identifier_doc}; +static PyMethodDef meth_bpy_script_paths = { + "script_paths", (PyCFunction)bpy_script_paths, METH_NOARGS, bpy_script_paths_doc}; +static PyMethodDef meth_bpy_blend_paths = {"blend_paths", + (PyCFunction)bpy_blend_paths, + METH_VARARGS | METH_KEYWORDS, + bpy_blend_paths_doc}; +static PyMethodDef meth_bpy_user_resource = { + "user_resource", (PyCFunction)bpy_user_resource, METH_VARARGS | METH_KEYWORDS, NULL}; +static PyMethodDef meth_bpy_resource_path = {"resource_path", + (PyCFunction)bpy_resource_path, + METH_VARARGS | METH_KEYWORDS, + bpy_resource_path_doc}; +static PyMethodDef meth_bpy_escape_identifier = { + "escape_identifier", (PyCFunction)bpy_escape_identifier, METH_O, bpy_escape_identifier_doc}; static PyObject *bpy_import_test(const char *modname) { - PyObject *mod = PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0); - if (mod) { - Py_DECREF(mod); - } - else { - PyErr_Print(); - PyErr_Clear(); - } - - return mod; + PyObject *mod = PyImport_ImportModuleLevel(modname, NULL, NULL, NULL, 0); + if (mod) { + Py_DECREF(mod); + } + else { + PyErr_Print(); + PyErr_Clear(); + } + + return mod; } - /****************************************************************************** * Description: Creates the bpy module and adds it to sys.modules for importing ******************************************************************************/ void BPy_init_modules(void) { - PointerRNA ctx_ptr; - PyObject *mod; - - /* Needs to be first since this dir is needed for future modules */ - const char * const modpath = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "modules"); - if (modpath) { - // printf("bpy: found module path '%s'.\n", modpath); - PyObject *sys_path = PySys_GetObject("path"); /* borrow */ - PyObject *py_modpath = PyUnicode_FromString(modpath); - PyList_Insert(sys_path, 0, py_modpath); /* add first */ - Py_DECREF(py_modpath); - } - else { - printf("bpy: couldnt find 'scripts/modules', blender probably wont start.\n"); - } - /* stand alone utility modules not related to blender directly */ - IDProp_Init_Types(); /* not actually a submodule, just types */ + PointerRNA ctx_ptr; + PyObject *mod; + + /* Needs to be first since this dir is needed for future modules */ + const char *const modpath = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "modules"); + if (modpath) { + // printf("bpy: found module path '%s'.\n", modpath); + PyObject *sys_path = PySys_GetObject("path"); /* borrow */ + PyObject *py_modpath = PyUnicode_FromString(modpath); + PyList_Insert(sys_path, 0, py_modpath); /* add first */ + Py_DECREF(py_modpath); + } + else { + printf("bpy: couldnt find 'scripts/modules', blender probably wont start.\n"); + } + /* stand alone utility modules not related to blender directly */ + IDProp_Init_Types(); /* not actually a submodule, just types */ #ifdef WITH_FREESTYLE - Freestyle_Init(); + Freestyle_Init(); #endif - mod = PyModule_New("_bpy"); - - /* add the module so we can import it */ - PyDict_SetItemString(PyImport_GetModuleDict(), "_bpy", mod); - Py_DECREF(mod); - - /* run first, initializes rna types */ - BPY_rna_init(); - - /* needs to be first so bpy_types can run */ - PyModule_AddObject(mod, "types", BPY_rna_types()); - - /* needs to be first so bpy_types can run */ - BPY_library_load_module(mod); - BPY_library_write_module(mod); - - BPY_rna_id_collection_module(mod); - - BPY_rna_gizmo_module(mod); - - bpy_import_test("bpy_types"); - PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */ - bpy_import_test("bpy_types"); - PyModule_AddObject(mod, "props", BPY_rna_props()); - /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */ - PyModule_AddObject(mod, "ops", BPY_operator_module()); - PyModule_AddObject(mod, "app", BPY_app_struct()); - PyModule_AddObject(mod, "_utils_units", BPY_utils_units()); - PyModule_AddObject(mod, "_utils_previews", BPY_utils_previews_module()); - PyModule_AddObject(mod, "msgbus", BPY_msgbus_module()); - - /* bpy context */ - RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), &ctx_ptr); - bpy_context_module = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ctx_ptr); - /* odd that this is needed, 1 ref on creation and another for the module - * but without we get a crash on exit */ - Py_INCREF(bpy_context_module); - - PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module); - - /* register bpy/rna classmethod callbacks */ - BPY_rna_register_cb(); - - /* utility func's that have nowhere else to go */ - PyModule_AddObject(mod, meth_bpy_script_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_script_paths, NULL)); - PyModule_AddObject(mod, meth_bpy_blend_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_blend_paths, NULL)); - PyModule_AddObject(mod, meth_bpy_user_resource.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_user_resource, NULL)); - PyModule_AddObject(mod, meth_bpy_resource_path.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_resource_path, NULL)); - PyModule_AddObject(mod, meth_bpy_escape_identifier.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_escape_identifier, NULL)); - - /* register funcs (bpy_rna.c) */ - PyModule_AddObject(mod, meth_bpy_register_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_register_class, NULL)); - PyModule_AddObject(mod, meth_bpy_unregister_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_unregister_class, NULL)); - - PyModule_AddObject(mod, meth_bpy_owner_id_get.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_owner_id_get, NULL)); - PyModule_AddObject(mod, meth_bpy_owner_id_set.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_owner_id_set, NULL)); - - /* add our own modules dir, this is a python package */ - bpy_package_py = bpy_import_test("bpy"); + mod = PyModule_New("_bpy"); + + /* add the module so we can import it */ + PyDict_SetItemString(PyImport_GetModuleDict(), "_bpy", mod); + Py_DECREF(mod); + + /* run first, initializes rna types */ + BPY_rna_init(); + + /* needs to be first so bpy_types can run */ + PyModule_AddObject(mod, "types", BPY_rna_types()); + + /* needs to be first so bpy_types can run */ + BPY_library_load_module(mod); + BPY_library_write_module(mod); + + BPY_rna_id_collection_module(mod); + + BPY_rna_gizmo_module(mod); + + bpy_import_test("bpy_types"); + PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */ + bpy_import_test("bpy_types"); + PyModule_AddObject(mod, "props", BPY_rna_props()); + /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */ + PyModule_AddObject(mod, "ops", BPY_operator_module()); + PyModule_AddObject(mod, "app", BPY_app_struct()); + PyModule_AddObject(mod, "_utils_units", BPY_utils_units()); + PyModule_AddObject(mod, "_utils_previews", BPY_utils_previews_module()); + PyModule_AddObject(mod, "msgbus", BPY_msgbus_module()); + + /* bpy context */ + RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), &ctx_ptr); + bpy_context_module = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ctx_ptr); + /* odd that this is needed, 1 ref on creation and another for the module + * but without we get a crash on exit */ + Py_INCREF(bpy_context_module); + + PyModule_AddObject(mod, "context", (PyObject *)bpy_context_module); + + /* register bpy/rna classmethod callbacks */ + BPY_rna_register_cb(); + + /* utility func's that have nowhere else to go */ + PyModule_AddObject(mod, + meth_bpy_script_paths.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_script_paths, NULL)); + PyModule_AddObject( + mod, meth_bpy_blend_paths.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_blend_paths, NULL)); + PyModule_AddObject(mod, + meth_bpy_user_resource.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_user_resource, NULL)); + PyModule_AddObject(mod, + meth_bpy_resource_path.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_resource_path, NULL)); + PyModule_AddObject(mod, + meth_bpy_escape_identifier.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_escape_identifier, NULL)); + + /* register funcs (bpy_rna.c) */ + PyModule_AddObject(mod, + meth_bpy_register_class.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_register_class, NULL)); + PyModule_AddObject(mod, + meth_bpy_unregister_class.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_unregister_class, NULL)); + + PyModule_AddObject(mod, + meth_bpy_owner_id_get.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_owner_id_get, NULL)); + PyModule_AddObject(mod, + meth_bpy_owner_id_set.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_owner_id_set, NULL)); + + /* add our own modules dir, this is a python package */ + bpy_package_py = bpy_import_test("bpy"); } diff --git a/source/blender/python/intern/bpy.h b/source/blender/python/intern/bpy.h index bd0212cb52a..88d1db6f8bc 100644 --- a/source/blender/python/intern/bpy.h +++ b/source/blender/python/intern/bpy.h @@ -31,4 +31,4 @@ void BPY_atexit_unregister(void); extern struct CLG_LogRef *BPY_LOG_CONTEXT; extern struct CLG_LogRef *BPY_LOG_RNA; -#endif /* __BPY_H__ */ +#endif /* __BPY_H__ */ diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 2cd3086dae1..f0a3c7f4d5f 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -22,7 +22,6 @@ * however some writable variables have been added such as 'debug' and 'tempdir' */ - #include <Python.h> #include "bpy_app.h" @@ -82,407 +81,504 @@ extern char build_system[]; static PyTypeObject BlenderAppType; static PyStructSequence_Field app_info_fields[] = { - {(char *)"version", (char *)"The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"}, - {(char *)"version_string", (char *)"The Blender version formatted as a string"}, - {(char *)"version_char", (char *)"The Blender version character (for minor releases)"}, - {(char *)"version_cycle", (char *)"The release status of this build alpha/beta/rc/release"}, - {(char *)"binary_path", (char *)"The location of blenders executable, useful for utilities that spawn new instances"}, - {(char *)"background", (char *)"Boolean, True when blender is running without a user interface (started with -b)"}, - {(char *)"factory_startup", (char *)"Boolean, True when blender is running with --factory-startup)"}, - - /* buildinfo */ - {(char *)"build_date", (char *)"The date this blender instance was built"}, - {(char *)"build_time", (char *)"The time this blender instance was built"}, - {(char *)"build_commit_timestamp", (char *)"The unix timestamp of commit this blender instance was built"}, - {(char *)"build_commit_date", (char *)"The date of commit this blender instance was built"}, - {(char *)"build_commit_time", (char *)"The time of commit this blender instance was built"}, - {(char *)"build_hash", (char *)"The commit hash this blender instance was built with"}, - {(char *)"build_branch", (char *)"The branch this blender instance was built from"}, - {(char *)"build_platform", (char *)"The platform this blender instance was built for"}, - {(char *)"build_type", (char *)"The type of build (Release, Debug)"}, - {(char *)"build_cflags", (char *)"C compiler flags"}, - {(char *)"build_cxxflags", (char *)"C++ compiler flags"}, - {(char *)"build_linkflags", (char *)"Binary linking flags"}, - {(char *)"build_system", (char *)"Build system used"}, - - /* submodules */ - {(char *)"alembic", (char *)"Alembic library information backend"}, - {(char *)"ffmpeg", (char *)"FFmpeg library information backend"}, - {(char *)"ocio", (char *)"OpenColorIO library information backend"}, - {(char *)"oiio", (char *)"OpenImageIO library information backend"}, - {(char *)"opensubdiv", (char *)"OpenSubdiv library information backend"}, - {(char *)"openvdb", (char *)"OpenVDB library information backend"}, - {(char *)"sdl", (char *)"SDL library information backend"}, - {(char *)"build_options", (char *)"A set containing most important enabled optional build features"}, - {(char *)"handlers", (char *)"Application handler callbacks"}, - {(char *)"translations", (char *)"Application and addons internationalization API"}, - - /* Modules (not struct sequence). */ - {(char *)"icons", (char *)"Manage custom icons"}, - {(char *)"timers", (char *)"Manage timers"}, - {NULL}, + {(char *)"version", (char *)"The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"}, + {(char *)"version_string", (char *)"The Blender version formatted as a string"}, + {(char *)"version_char", (char *)"The Blender version character (for minor releases)"}, + {(char *)"version_cycle", (char *)"The release status of this build alpha/beta/rc/release"}, + {(char *)"binary_path", + (char *)"The location of blenders executable, useful for utilities that spawn new instances"}, + {(char *)"background", + (char *)"Boolean, True when blender is running without a user interface (started with -b)"}, + {(char *)"factory_startup", + (char *)"Boolean, True when blender is running with --factory-startup)"}, + + /* buildinfo */ + {(char *)"build_date", (char *)"The date this blender instance was built"}, + {(char *)"build_time", (char *)"The time this blender instance was built"}, + {(char *)"build_commit_timestamp", + (char *)"The unix timestamp of commit this blender instance was built"}, + {(char *)"build_commit_date", (char *)"The date of commit this blender instance was built"}, + {(char *)"build_commit_time", (char *)"The time of commit this blender instance was built"}, + {(char *)"build_hash", (char *)"The commit hash this blender instance was built with"}, + {(char *)"build_branch", (char *)"The branch this blender instance was built from"}, + {(char *)"build_platform", (char *)"The platform this blender instance was built for"}, + {(char *)"build_type", (char *)"The type of build (Release, Debug)"}, + {(char *)"build_cflags", (char *)"C compiler flags"}, + {(char *)"build_cxxflags", (char *)"C++ compiler flags"}, + {(char *)"build_linkflags", (char *)"Binary linking flags"}, + {(char *)"build_system", (char *)"Build system used"}, + + /* submodules */ + {(char *)"alembic", (char *)"Alembic library information backend"}, + {(char *)"ffmpeg", (char *)"FFmpeg library information backend"}, + {(char *)"ocio", (char *)"OpenColorIO library information backend"}, + {(char *)"oiio", (char *)"OpenImageIO library information backend"}, + {(char *)"opensubdiv", (char *)"OpenSubdiv library information backend"}, + {(char *)"openvdb", (char *)"OpenVDB library information backend"}, + {(char *)"sdl", (char *)"SDL library information backend"}, + {(char *)"build_options", + (char *)"A set containing most important enabled optional build features"}, + {(char *)"handlers", (char *)"Application handler callbacks"}, + {(char *)"translations", (char *)"Application and addons internationalization API"}, + + /* Modules (not struct sequence). */ + {(char *)"icons", (char *)"Manage custom icons"}, + {(char *)"timers", (char *)"Manage timers"}, + {NULL}, }; PyDoc_STRVAR(bpy_app_doc, -"This module contains application values that remain unchanged during runtime.\n" -"\n" -"Submodules:\n" -"\n" -".. toctree::\n" -" :maxdepth: 1\n" -"\n" -" bpy.app.handlers.rst\n" -" bpy.app.icons.rst\n" -" bpy.app.timers.rst\n" -" bpy.app.translations.rst\n" -); + "This module contains application values that remain unchanged during runtime.\n" + "\n" + "Submodules:\n" + "\n" + ".. toctree::\n" + " :maxdepth: 1\n" + "\n" + " bpy.app.handlers.rst\n" + " bpy.app.icons.rst\n" + " bpy.app.timers.rst\n" + " bpy.app.translations.rst\n"); static PyStructSequence_Desc app_info_desc = { - (char *)"bpy.app", /* name */ - bpy_app_doc, /* doc */ - app_info_fields, /* fields */ - ARRAY_SIZE(app_info_fields) - 1, + (char *)"bpy.app", /* name */ + bpy_app_doc, /* doc */ + app_info_fields, /* fields */ + ARRAY_SIZE(app_info_fields) - 1, }; static PyObject *make_app_info(void) { - PyObject *app_info; - int pos = 0; - - app_info = PyStructSequence_New(&BlenderAppType); - if (app_info == NULL) { - return NULL; - } -#define SetIntItem(flag) \ - PyStructSequence_SET_ITEM(app_info, pos++, PyLong_FromLong(flag)) -#define SetStrItem(str) \ - PyStructSequence_SET_ITEM(app_info, pos++, PyUnicode_FromString(str)) -#define SetBytesItem(str) \ - PyStructSequence_SET_ITEM(app_info, pos++, PyBytes_FromString(str)) -#define SetObjItem(obj) \ - PyStructSequence_SET_ITEM(app_info, pos++, obj) - - SetObjItem(PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION)); - SetObjItem(PyUnicode_FromFormat("%d.%02d (sub %d)", - BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION)); - - SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR)); - SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE)); - SetStrItem(BKE_appdir_program_path()); - SetObjItem(PyBool_FromLong(G.background)); - SetObjItem(PyBool_FromLong(G.factory_startup)); - - /* build info, use bytes since we can't assume _any_ encoding: - * see patch [#30154] for issue */ + PyObject *app_info; + int pos = 0; + + app_info = PyStructSequence_New(&BlenderAppType); + if (app_info == NULL) { + return NULL; + } +#define SetIntItem(flag) PyStructSequence_SET_ITEM(app_info, pos++, PyLong_FromLong(flag)) +#define SetStrItem(str) PyStructSequence_SET_ITEM(app_info, pos++, PyUnicode_FromString(str)) +#define SetBytesItem(str) PyStructSequence_SET_ITEM(app_info, pos++, PyBytes_FromString(str)) +#define SetObjItem(obj) PyStructSequence_SET_ITEM(app_info, pos++, obj) + + SetObjItem(PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION)); + SetObjItem(PyUnicode_FromFormat( + "%d.%02d (sub %d)", BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION)); + + SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR)); + SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE)); + SetStrItem(BKE_appdir_program_path()); + SetObjItem(PyBool_FromLong(G.background)); + SetObjItem(PyBool_FromLong(G.factory_startup)); + + /* build info, use bytes since we can't assume _any_ encoding: + * see patch [#30154] for issue */ #ifdef BUILD_DATE - SetBytesItem(build_date); - SetBytesItem(build_time); - SetIntItem(build_commit_timestamp); - SetBytesItem(build_commit_date); - SetBytesItem(build_commit_time); - SetBytesItem(build_hash); - SetBytesItem(build_branch); - SetBytesItem(build_platform); - SetBytesItem(build_type); - SetBytesItem(build_cflags); - SetBytesItem(build_cxxflags); - SetBytesItem(build_linkflags); - SetBytesItem(build_system); + SetBytesItem(build_date); + SetBytesItem(build_time); + SetIntItem(build_commit_timestamp); + SetBytesItem(build_commit_date); + SetBytesItem(build_commit_time); + SetBytesItem(build_hash); + SetBytesItem(build_branch); + SetBytesItem(build_platform); + SetBytesItem(build_type); + SetBytesItem(build_cflags); + SetBytesItem(build_cxxflags); + SetBytesItem(build_linkflags); + SetBytesItem(build_system); #else - SetBytesItem("Unknown"); - SetBytesItem("Unknown"); - SetIntItem(0); - SetBytesItem("Unknown"); - SetBytesItem("Unknown"); - SetBytesItem("Unknown"); - SetBytesItem("Unknown"); - SetBytesItem("Unknown"); - SetBytesItem("Unknown"); - SetBytesItem("Unknown"); - SetBytesItem("Unknown"); - SetBytesItem("Unknown"); - SetBytesItem("Unknown"); + SetBytesItem("Unknown"); + SetBytesItem("Unknown"); + SetIntItem(0); + SetBytesItem("Unknown"); + SetBytesItem("Unknown"); + SetBytesItem("Unknown"); + SetBytesItem("Unknown"); + SetBytesItem("Unknown"); + SetBytesItem("Unknown"); + SetBytesItem("Unknown"); + SetBytesItem("Unknown"); + SetBytesItem("Unknown"); + SetBytesItem("Unknown"); #endif - SetObjItem(BPY_app_alembic_struct()); - SetObjItem(BPY_app_ffmpeg_struct()); - SetObjItem(BPY_app_ocio_struct()); - SetObjItem(BPY_app_oiio_struct()); - SetObjItem(BPY_app_opensubdiv_struct()); - SetObjItem(BPY_app_openvdb_struct()); - SetObjItem(BPY_app_sdl_struct()); - SetObjItem(BPY_app_build_options_struct()); - SetObjItem(BPY_app_handlers_struct()); - SetObjItem(BPY_app_translations_struct()); - - /* modules */ - SetObjItem(BPY_app_icons_module()); - SetObjItem(BPY_app_timers_module()); + SetObjItem(BPY_app_alembic_struct()); + SetObjItem(BPY_app_ffmpeg_struct()); + SetObjItem(BPY_app_ocio_struct()); + SetObjItem(BPY_app_oiio_struct()); + SetObjItem(BPY_app_opensubdiv_struct()); + SetObjItem(BPY_app_openvdb_struct()); + SetObjItem(BPY_app_sdl_struct()); + SetObjItem(BPY_app_build_options_struct()); + SetObjItem(BPY_app_handlers_struct()); + SetObjItem(BPY_app_translations_struct()); + + /* modules */ + SetObjItem(BPY_app_icons_module()); + SetObjItem(BPY_app_timers_module()); #undef SetIntItem #undef SetStrItem #undef SetBytesItem #undef SetObjItem - if (PyErr_Occurred()) { - Py_CLEAR(app_info); - return NULL; - } - return app_info; + if (PyErr_Occurred()) { + Py_CLEAR(app_info); + return NULL; + } + return app_info; } /* a few getsets because it makes sense for them to be in bpy.app even though * they are not static */ -PyDoc_STRVAR(bpy_app_debug_doc, -"Boolean, for debug info (started with --debug / --debug_* matching this attribute name)" -); +PyDoc_STRVAR( + bpy_app_debug_doc, + "Boolean, for debug info (started with --debug / --debug_* matching this attribute name)"); static PyObject *bpy_app_debug_get(PyObject *UNUSED(self), void *closure) { - const int flag = POINTER_AS_INT(closure); - return PyBool_FromLong(G.debug & flag); + const int flag = POINTER_AS_INT(closure); + return PyBool_FromLong(G.debug & flag); } static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *closure) { - const int flag = POINTER_AS_INT(closure); - const int param = PyObject_IsTrue(value); - - if (param == -1) { - PyErr_SetString(PyExc_TypeError, "bpy.app.debug can only be True/False"); - return -1; - } - - if (param) { - G.debug |= flag; - } - else { - G.debug &= ~flag; - } - - return 0; + const int flag = POINTER_AS_INT(closure); + const int param = PyObject_IsTrue(value); + + if (param == -1) { + PyErr_SetString(PyExc_TypeError, "bpy.app.debug can only be True/False"); + return -1; + } + + if (param) { + G.debug |= flag; + } + else { + G.debug &= ~flag; + } + + return 0; } -PyDoc_STRVAR(bpy_app_global_flag_doc, -"Boolean, for application behavior (started with --enable-* matching this attribute name)" -); +PyDoc_STRVAR( + bpy_app_global_flag_doc, + "Boolean, for application behavior (started with --enable-* matching this attribute name)"); static PyObject *bpy_app_global_flag_get(PyObject *UNUSED(self), void *closure) { - const int flag = POINTER_AS_INT(closure); - return PyBool_FromLong(G.f & flag); + const int flag = POINTER_AS_INT(closure); + return PyBool_FromLong(G.f & flag); } static int bpy_app_global_flag_set(PyObject *UNUSED(self), PyObject *value, void *closure) { - const int flag = POINTER_AS_INT(closure); - const int param = PyObject_IsTrue(value); - - if (param == -1) { - PyErr_SetString(PyExc_TypeError, "bpy.app.use_* can only be True/False"); - return -1; - } - - if (param) { - G.f |= flag; - } - else { - G.f &= ~flag; - } - - return 0; + const int flag = POINTER_AS_INT(closure); + const int param = PyObject_IsTrue(value); + + if (param == -1) { + PyErr_SetString(PyExc_TypeError, "bpy.app.use_* can only be True/False"); + return -1; + } + + if (param) { + G.f |= flag; + } + else { + G.f &= ~flag; + } + + return 0; } -static int bpy_app_global_flag_set__only_disable(PyObject *UNUSED(self), PyObject *value, void *closure) +static int bpy_app_global_flag_set__only_disable(PyObject *UNUSED(self), + PyObject *value, + void *closure) { - const int param = PyObject_IsTrue(value); - if (param == 1) { - PyErr_SetString(PyExc_ValueError, "This bpy.app.use_* option can only be disabled"); - return -1; - } - return bpy_app_global_flag_set(NULL, value, closure); + const int param = PyObject_IsTrue(value); + if (param == 1) { + PyErr_SetString(PyExc_ValueError, "This bpy.app.use_* option can only be disabled"); + return -1; + } + return bpy_app_global_flag_set(NULL, value, closure); } #define BROKEN_BINARY_PATH_PYTHON_HACK PyDoc_STRVAR(bpy_app_binary_path_python_doc, -"String, the path to the python executable (read-only)" -); + "String, the path to the python executable (read-only)"); static PyObject *bpy_app_binary_path_python_get(PyObject *self, void *UNUSED(closure)) { - /* refcount is held in BlenderAppType.tp_dict */ - static PyObject *ret = NULL; - - if (ret == NULL) { - /* only run once */ - char fullpath[1024]; - BKE_appdir_program_python_search( - fullpath, sizeof(fullpath), - PY_MAJOR_VERSION, PY_MINOR_VERSION); - ret = PyC_UnicodeFromByte(fullpath); + /* refcount is held in BlenderAppType.tp_dict */ + static PyObject *ret = NULL; + + if (ret == NULL) { + /* only run once */ + char fullpath[1024]; + BKE_appdir_program_python_search( + fullpath, sizeof(fullpath), PY_MAJOR_VERSION, PY_MINOR_VERSION); + ret = PyC_UnicodeFromByte(fullpath); #ifdef BROKEN_BINARY_PATH_PYTHON_HACK - Py_INCREF(ret); - UNUSED_VARS(self); + Py_INCREF(ret); + UNUSED_VARS(self); #else - PyDict_SetItem(BlenderAppType.tp_dict, /* XXX BAAAADDDDDD! self is not a PyDescr at all! it's bpy.app!!! */ PyDescr_NAME(self), ret); + PyDict_SetItem( + BlenderAppType.tp_dict, + /* XXX BAAAADDDDDD! self is not a PyDescr at all! it's bpy.app!!! */ PyDescr_NAME(self), + ret); #endif - } - else { - Py_INCREF(ret); - } + } + else { + Py_INCREF(ret); + } - return ret; + return ret; } PyDoc_STRVAR(bpy_app_debug_value_doc, -"Short, number which can be set to non-zero values for testing purposes" -); + "Short, number which can be set to non-zero values for testing purposes"); static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - return PyLong_FromLong(G.debug_value); + return PyLong_FromLong(G.debug_value); } static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure)) { - short param = PyC_Long_AsI16(value); + short param = PyC_Long_AsI16(value); - if (param == -1 && PyErr_Occurred()) { - PyC_Err_SetString_Prefix( - PyExc_TypeError, - "bpy.app.debug_value can only be set to a whole number"); - return -1; - } + if (param == -1 && PyErr_Occurred()) { + PyC_Err_SetString_Prefix(PyExc_TypeError, + "bpy.app.debug_value can only be set to a whole number"); + return -1; + } - G.debug_value = param; + G.debug_value = param; - WM_main_add_notifier(NC_WINDOW, NULL); + WM_main_add_notifier(NC_WINDOW, NULL); - return 0; + return 0; } -PyDoc_STRVAR(bpy_app_tempdir_doc, -"String, the temp directory used by blender (read-only)" -); +PyDoc_STRVAR(bpy_app_tempdir_doc, "String, the temp directory used by blender (read-only)"); static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - return PyC_UnicodeFromByte(BKE_tempdir_session()); + return PyC_UnicodeFromByte(BKE_tempdir_session()); } -PyDoc_STRVAR(bpy_app_driver_dict_doc, -"Dictionary for drivers namespace, editable in-place, reset on file load (read-only)" -); +PyDoc_STRVAR( + bpy_app_driver_dict_doc, + "Dictionary for drivers namespace, editable in-place, reset on file load (read-only)"); static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - if (bpy_pydriver_Dict == NULL) { - if (bpy_pydriver_create_dict() != 0) { - PyErr_SetString(PyExc_RuntimeError, "bpy.app.driver_namespace failed to create dictionary"); - return NULL; - } - } - - return Py_INCREF_RET(bpy_pydriver_Dict); + if (bpy_pydriver_Dict == NULL) { + if (bpy_pydriver_create_dict() != 0) { + PyErr_SetString(PyExc_RuntimeError, "bpy.app.driver_namespace failed to create dictionary"); + return NULL; + } + } + + return Py_INCREF_RET(bpy_pydriver_Dict); } PyDoc_STRVAR(bpy_app_preview_render_size_doc, -"Reference size for icon/preview renders (read-only)" -); + "Reference size for icon/preview renders (read-only)"); static PyObject *bpy_app_preview_render_size_get(PyObject *UNUSED(self), void *closure) { - return PyLong_FromLong((long)UI_preview_render_size(POINTER_AS_INT(closure))); + return PyLong_FromLong((long)UI_preview_render_size(POINTER_AS_INT(closure))); } static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - return PyC_UnicodeFromByte(G.autoexec_fail); + return PyC_UnicodeFromByte(G.autoexec_fail); } - PyDoc_STRVAR(bpy_app_use_static_override_doc, -"Boolean, whether static override is exposed in UI or not." -); + "Boolean, whether static override is exposed in UI or not."); static PyObject *bpy_app_use_static_override_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - return PyBool_FromLong((long)BKE_override_static_is_enabled()); + return PyBool_FromLong((long)BKE_override_static_is_enabled()); } -static int bpy_app_use_static_override_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure)) +static int bpy_app_use_static_override_set(PyObject *UNUSED(self), + PyObject *value, + void *UNUSED(closure)) { - const int param = PyC_Long_AsBool(value); + const int param = PyC_Long_AsBool(value); - if (param == -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "bpy.app.use_static_override must be a boolean"); - return -1; - } + if (param == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "bpy.app.use_static_override must be a boolean"); + return -1; + } - BKE_override_static_enable((const bool)param); + BKE_override_static_enable((const bool)param); - return 0; + return 0; } - static PyGetSetDef bpy_app_getsets[] = { - {(char *)"debug", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG}, - {(char *)"debug_ffmpeg", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FFMPEG}, - {(char *)"debug_freestyle", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FREESTYLE}, - {(char *)"debug_python", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_PYTHON}, - {(char *)"debug_events", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_EVENTS}, - {(char *)"debug_handlers", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_HANDLERS}, - {(char *)"debug_wm", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM}, - {(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH}, - {(char *)"debug_depsgraph_build", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_BUILD}, - {(char *)"debug_depsgraph_eval", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_EVAL}, - {(char *)"debug_depsgraph_tag", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TAG}, - {(char *)"debug_depsgraph_time", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TIME}, - {(char *)"debug_depsgraph_pretty", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_PRETTY}, - {(char *)"debug_simdata", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA}, - {(char *)"debug_gpumem", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM}, - {(char *)"debug_io", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_IO}, - - {(char *)"use_static_override", bpy_app_use_static_override_get, bpy_app_use_static_override_set, (char *)bpy_app_use_static_override_doc, NULL}, - {(char *)"use_event_simulate", bpy_app_global_flag_get, bpy_app_global_flag_set__only_disable, (char *)bpy_app_global_flag_doc, (void *)G_FLAG_EVENT_SIMULATE}, - - {(char *)"binary_path_python", bpy_app_binary_path_python_get, NULL, (char *)bpy_app_binary_path_python_doc, NULL}, - - {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL}, - {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL}, - {(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)bpy_app_driver_dict_doc, NULL}, - - {(char *)"render_icon_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_ICON}, - {(char *)"render_preview_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_PREVIEW}, - - /* security */ - {(char *)"autoexec_fail", bpy_app_global_flag_get, NULL, NULL, (void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL}, - {(char *)"autoexec_fail_quiet", bpy_app_global_flag_get, NULL, NULL, (void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET}, - {(char *)"autoexec_fail_message", bpy_app_autoexec_fail_message_get, NULL, NULL, NULL}, - {NULL, NULL, NULL, NULL, NULL}, + {(char *)"debug", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG}, + {(char *)"debug_ffmpeg", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_FFMPEG}, + {(char *)"debug_freestyle", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_FREESTYLE}, + {(char *)"debug_python", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_PYTHON}, + {(char *)"debug_events", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_EVENTS}, + {(char *)"debug_handlers", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_HANDLERS}, + {(char *)"debug_wm", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_WM}, + {(char *)"debug_depsgraph", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_DEPSGRAPH}, + {(char *)"debug_depsgraph_build", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_DEPSGRAPH_BUILD}, + {(char *)"debug_depsgraph_eval", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_DEPSGRAPH_EVAL}, + {(char *)"debug_depsgraph_tag", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_DEPSGRAPH_TAG}, + {(char *)"debug_depsgraph_time", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_DEPSGRAPH_TIME}, + {(char *)"debug_depsgraph_pretty", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_DEPSGRAPH_PRETTY}, + {(char *)"debug_simdata", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_SIMDATA}, + {(char *)"debug_gpumem", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_GPU_MEM}, + {(char *)"debug_io", + bpy_app_debug_get, + bpy_app_debug_set, + (char *)bpy_app_debug_doc, + (void *)G_DEBUG_IO}, + + {(char *)"use_static_override", + bpy_app_use_static_override_get, + bpy_app_use_static_override_set, + (char *)bpy_app_use_static_override_doc, + NULL}, + {(char *)"use_event_simulate", + bpy_app_global_flag_get, + bpy_app_global_flag_set__only_disable, + (char *)bpy_app_global_flag_doc, + (void *)G_FLAG_EVENT_SIMULATE}, + + {(char *)"binary_path_python", + bpy_app_binary_path_python_get, + NULL, + (char *)bpy_app_binary_path_python_doc, + NULL}, + + {(char *)"debug_value", + bpy_app_debug_value_get, + bpy_app_debug_value_set, + (char *)bpy_app_debug_value_doc, + NULL}, + {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL}, + {(char *)"driver_namespace", + bpy_app_driver_dict_get, + NULL, + (char *)bpy_app_driver_dict_doc, + NULL}, + + {(char *)"render_icon_size", + bpy_app_preview_render_size_get, + NULL, + (char *)bpy_app_preview_render_size_doc, + (void *)ICON_SIZE_ICON}, + {(char *)"render_preview_size", + bpy_app_preview_render_size_get, + NULL, + (char *)bpy_app_preview_render_size_doc, + (void *)ICON_SIZE_PREVIEW}, + + /* security */ + {(char *)"autoexec_fail", + bpy_app_global_flag_get, + NULL, + NULL, + (void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL}, + {(char *)"autoexec_fail_quiet", + bpy_app_global_flag_get, + NULL, + NULL, + (void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET}, + {(char *)"autoexec_fail_message", bpy_app_autoexec_fail_message_get, NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL, NULL}, }; static void py_struct_seq_getset_init(void) { - /* tricky dynamic members, not to py-spec! */ - for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) { - PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset); - PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(item), item); - Py_DECREF(item); - } + /* tricky dynamic members, not to py-spec! */ + for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) { + PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset); + PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(item), item); + Py_DECREF(item); + } } /* end dynamic bpy.app */ - PyObject *BPY_app_struct(void) { - PyObject *ret; + PyObject *ret; - PyStructSequence_InitType(&BlenderAppType, &app_info_desc); + PyStructSequence_InitType(&BlenderAppType, &app_info_desc); - ret = make_app_info(); + ret = make_app_info(); - /* prevent user from creating new instances */ - BlenderAppType.tp_init = NULL; - BlenderAppType.tp_new = NULL; - BlenderAppType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + /* prevent user from creating new instances */ + BlenderAppType.tp_init = NULL; + BlenderAppType.tp_new = NULL; + BlenderAppType.tp_hash = (hashfunc) + _Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ - /* kindof a hack ontop of PyStructSequence */ - py_struct_seq_getset_init(); + /* kindof a hack ontop of PyStructSequence */ + py_struct_seq_getset_init(); - return ret; + return ret; } diff --git a/source/blender/python/intern/bpy_app.h b/source/blender/python/intern/bpy_app.h index e9ab3cd2858..b46de025599 100644 --- a/source/blender/python/intern/bpy_app.h +++ b/source/blender/python/intern/bpy_app.h @@ -23,4 +23,4 @@ PyObject *BPY_app_struct(void); -#endif /* __BPY_APP_H__ */ +#endif /* __BPY_APP_H__ */ diff --git a/source/blender/python/intern/bpy_app_alembic.c b/source/blender/python/intern/bpy_app_alembic.c index 6f2874dcefa..6032e062d09 100644 --- a/source/blender/python/intern/bpy_app_alembic.c +++ b/source/blender/python/intern/bpy_app_alembic.c @@ -35,73 +35,72 @@ static PyTypeObject BlenderAppABCType; static PyStructSequence_Field app_alembic_info_fields[] = { - {(char *)"supported", (char *)"Boolean, True when Blender is built with Alembic support"}, - {(char *)"version", (char *)"The Alembic version as a tuple of 3 numbers"}, - {(char *)"version_string", (char *)"The Alembic version formatted as a string"}, - {NULL}, + {(char *)"supported", (char *)"Boolean, True when Blender is built with Alembic support"}, + {(char *)"version", (char *)"The Alembic version as a tuple of 3 numbers"}, + {(char *)"version_string", (char *)"The Alembic version formatted as a string"}, + {NULL}, }; static PyStructSequence_Desc app_alembic_info_desc = { - (char *)"bpy.app.alembic", /* name */ - (char *)"This module contains information about Alembic blender is linked against", /* doc */ - app_alembic_info_fields, /* fields */ - ARRAY_SIZE(app_alembic_info_fields) - 1, + (char *)"bpy.app.alembic", /* name */ + (char *)"This module contains information about Alembic blender is linked against", /* doc */ + app_alembic_info_fields, /* fields */ + ARRAY_SIZE(app_alembic_info_fields) - 1, }; static PyObject *make_alembic_info(void) { - PyObject *alembic_info = PyStructSequence_New(&BlenderAppABCType); + PyObject *alembic_info = PyStructSequence_New(&BlenderAppABCType); - if (alembic_info == NULL) { - return NULL; - } + if (alembic_info == NULL) { + return NULL; + } - int pos = 0; + int pos = 0; #ifndef WITH_ALEMBIC -# define SetStrItem(str) \ - PyStructSequence_SET_ITEM(alembic_info, pos++, PyUnicode_FromString(str)) +# define SetStrItem(str) PyStructSequence_SET_ITEM(alembic_info, pos++, PyUnicode_FromString(str)) #endif -#define SetObjItem(obj) \ - PyStructSequence_SET_ITEM(alembic_info, pos++, obj) +#define SetObjItem(obj) PyStructSequence_SET_ITEM(alembic_info, pos++, obj) #ifdef WITH_ALEMBIC - const int curversion = ABC_get_version(); - const int major = curversion / 10000; - const int minor = (curversion / 100) - (major * 100); - const int patch = curversion - ((curversion / 100 ) * 100); - - SetObjItem(PyBool_FromLong(1)); - SetObjItem(PyC_Tuple_Pack_I32(major, minor, patch)); - SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", major, minor, patch)); + const int curversion = ABC_get_version(); + const int major = curversion / 10000; + const int minor = (curversion / 100) - (major * 100); + const int patch = curversion - ((curversion / 100) * 100); + + SetObjItem(PyBool_FromLong(1)); + SetObjItem(PyC_Tuple_Pack_I32(major, minor, patch)); + SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", major, minor, patch)); #else - SetObjItem(PyBool_FromLong(0)); - SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); - SetStrItem("Unknown"); + SetObjItem(PyBool_FromLong(0)); + SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); + SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(alembic_info); - return NULL; - } + if (PyErr_Occurred()) { + Py_CLEAR(alembic_info); + return NULL; + } #undef SetStrItem #undef SetObjItem - return alembic_info; + return alembic_info; } PyObject *BPY_app_alembic_struct(void) { - PyStructSequence_InitType(&BlenderAppABCType, &app_alembic_info_desc); + PyStructSequence_InitType(&BlenderAppABCType, &app_alembic_info_desc); - PyObject *ret = make_alembic_info(); + PyObject *ret = make_alembic_info(); - /* prevent user from creating new instances */ - BlenderAppABCType.tp_init = NULL; - BlenderAppABCType.tp_new = NULL; - BlenderAppABCType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + /* prevent user from creating new instances */ + BlenderAppABCType.tp_init = NULL; + BlenderAppABCType.tp_new = NULL; + BlenderAppABCType.tp_hash = (hashfunc) + _Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ - return ret; + return ret; } diff --git a/source/blender/python/intern/bpy_app_alembic.h b/source/blender/python/intern/bpy_app_alembic.h index dfa652c8d15..4cc890ec64d 100644 --- a/source/blender/python/intern/bpy_app_alembic.h +++ b/source/blender/python/intern/bpy_app_alembic.h @@ -26,4 +26,4 @@ PyObject *BPY_app_alembic_struct(void); -#endif /* __BPY_APP_ALEMBIC_H__ */ +#endif /* __BPY_APP_ALEMBIC_H__ */ diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c index a80156a23bf..a841e974e85 100644 --- a/source/blender/python/intern/bpy_app_build_options.c +++ b/source/blender/python/intern/bpy_app_build_options.c @@ -27,265 +27,265 @@ static PyTypeObject BlenderAppBuildOptionsType; static PyStructSequence_Field app_builtopts_info_fields[] = { - /* names mostly follow CMake options, lowercase, after WITH_ */ - {(char *)"bullet", NULL}, - {(char *)"codec_avi", NULL}, - {(char *)"codec_ffmpeg", NULL}, - {(char *)"codec_sndfile", NULL}, - {(char *)"compositor", NULL}, - {(char *)"cycles", NULL}, - {(char *)"cycles_osl", NULL}, - {(char *)"freestyle", NULL}, - {(char *)"image_cineon", NULL}, - {(char *)"image_dds", NULL}, - {(char *)"image_hdr", NULL}, - {(char *)"image_openexr", NULL}, - {(char *)"image_openjpeg", NULL}, - {(char *)"image_tiff", NULL}, - {(char *)"input_ndof", NULL}, - {(char *)"audaspace", NULL}, - {(char *)"international", NULL}, - {(char *)"openal", NULL}, - {(char *)"sdl", NULL}, - {(char *)"sdl_dynload", NULL}, - {(char *)"jack", NULL}, - {(char *)"libmv", NULL}, - {(char *)"mod_fluid", NULL}, - {(char *)"mod_oceansim", NULL}, - {(char *)"mod_remesh", NULL}, - {(char *)"mod_smoke", NULL}, - {(char *)"collada", NULL}, - {(char *)"opencolorio", NULL}, - {(char *)"openmp", NULL}, - {(char *)"openvdb", NULL}, - {(char *)"alembic", NULL}, - {NULL}, + /* names mostly follow CMake options, lowercase, after WITH_ */ + {(char *)"bullet", NULL}, + {(char *)"codec_avi", NULL}, + {(char *)"codec_ffmpeg", NULL}, + {(char *)"codec_sndfile", NULL}, + {(char *)"compositor", NULL}, + {(char *)"cycles", NULL}, + {(char *)"cycles_osl", NULL}, + {(char *)"freestyle", NULL}, + {(char *)"image_cineon", NULL}, + {(char *)"image_dds", NULL}, + {(char *)"image_hdr", NULL}, + {(char *)"image_openexr", NULL}, + {(char *)"image_openjpeg", NULL}, + {(char *)"image_tiff", NULL}, + {(char *)"input_ndof", NULL}, + {(char *)"audaspace", NULL}, + {(char *)"international", NULL}, + {(char *)"openal", NULL}, + {(char *)"sdl", NULL}, + {(char *)"sdl_dynload", NULL}, + {(char *)"jack", NULL}, + {(char *)"libmv", NULL}, + {(char *)"mod_fluid", NULL}, + {(char *)"mod_oceansim", NULL}, + {(char *)"mod_remesh", NULL}, + {(char *)"mod_smoke", NULL}, + {(char *)"collada", NULL}, + {(char *)"opencolorio", NULL}, + {(char *)"openmp", NULL}, + {(char *)"openvdb", NULL}, + {(char *)"alembic", NULL}, + {NULL}, }; - static PyStructSequence_Desc app_builtopts_info_desc = { - (char *)"bpy.app.build_options", /* name */ - (char *)"This module contains information about options blender is built with", /* doc */ - app_builtopts_info_fields, /* fields */ - ARRAY_SIZE(app_builtopts_info_fields) - 1, + (char *)"bpy.app.build_options", /* name */ + (char *)"This module contains information about options blender is built with", /* doc */ + app_builtopts_info_fields, /* fields */ + ARRAY_SIZE(app_builtopts_info_fields) - 1, }; static PyObject *make_builtopts_info(void) { - PyObject *builtopts_info; - int pos = 0; + PyObject *builtopts_info; + int pos = 0; - builtopts_info = PyStructSequence_New(&BlenderAppBuildOptionsType); - if (builtopts_info == NULL) { - return NULL; - } + builtopts_info = PyStructSequence_New(&BlenderAppBuildOptionsType); + if (builtopts_info == NULL) { + return NULL; + } #define SetObjIncref(item) \ - PyStructSequence_SET_ITEM(builtopts_info, pos++, (Py_IncRef(item), item)) + PyStructSequence_SET_ITEM(builtopts_info, pos++, (Py_IncRef(item), item)) #ifdef WITH_BULLET - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_AVI - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_FFMPEG - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_SNDFILE - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_COMPOSITOR - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_CYCLES - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_CYCLES_OSL - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_FREESTYLE - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_CINEON - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_DDS - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_HDR - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_OPENEXR - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_OPENJPEG - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_TIFF - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_INPUT_NDOF - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_AUDASPACE - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_INTERNATIONAL - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_OPENAL - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_SDL - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_SDL_DYNLOAD - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_JACK - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_LIBMV - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_MOD_FLUID - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_OCEANSIM - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_MOD_REMESH - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_SMOKE - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_COLLADA - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_OCIO - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef _OPENMP - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_OPENVDB - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #ifdef WITH_ALEMBIC - SetObjIncref(Py_True); + SetObjIncref(Py_True); #else - SetObjIncref(Py_False); + SetObjIncref(Py_False); #endif #undef SetObjIncref - return builtopts_info; + return builtopts_info; } PyObject *BPY_app_build_options_struct(void) { - PyObject *ret; + PyObject *ret; - PyStructSequence_InitType(&BlenderAppBuildOptionsType, &app_builtopts_info_desc); + PyStructSequence_InitType(&BlenderAppBuildOptionsType, &app_builtopts_info_desc); - ret = make_builtopts_info(); + ret = make_builtopts_info(); - /* prevent user from creating new instances */ - BlenderAppBuildOptionsType.tp_init = NULL; - BlenderAppBuildOptionsType.tp_new = NULL; - BlenderAppBuildOptionsType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + /* prevent user from creating new instances */ + BlenderAppBuildOptionsType.tp_init = NULL; + BlenderAppBuildOptionsType.tp_new = NULL; + BlenderAppBuildOptionsType.tp_hash = (hashfunc) + _Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ - return ret; + return ret; } diff --git a/source/blender/python/intern/bpy_app_build_options.h b/source/blender/python/intern/bpy_app_build_options.h index e15887d9caf..52c2e57c12a 100644 --- a/source/blender/python/intern/bpy_app_build_options.h +++ b/source/blender/python/intern/bpy_app_build_options.h @@ -23,4 +23,4 @@ PyObject *BPY_app_build_options_struct(void); -#endif /* __BPY_APP_BUILD_OPTIONS_H__ */ +#endif /* __BPY_APP_BUILD_OPTIONS_H__ */ diff --git a/source/blender/python/intern/bpy_app_ffmpeg.c b/source/blender/python/intern/bpy_app_ffmpeg.c index 6fb53f60f90..d1aa7817538 100644 --- a/source/blender/python/intern/bpy_app_ffmpeg.c +++ b/source/blender/python/intern/bpy_app_ffmpeg.c @@ -26,116 +26,121 @@ #include "../generic/py_capi_utils.h" #ifdef WITH_FFMPEG -#include <libavcodec/avcodec.h> -#include <libavdevice/avdevice.h> -#include <libavformat/avformat.h> -#include <libavutil/avutil.h> -#include <libswscale/swscale.h> +# include <libavcodec/avcodec.h> +# include <libavdevice/avdevice.h> +# include <libavformat/avformat.h> +# include <libavutil/avutil.h> +# include <libswscale/swscale.h> #endif static PyTypeObject BlenderAppFFmpegType; #define DEF_FFMPEG_LIB_VERSION(lib) \ - {(char *)(#lib "_version"), (char *)("The " #lib " version as a tuple of 3 numbers")}, \ - {(char *)(#lib "_version_string"), (char *)("The " #lib " version formatted as a string")} + {(char *)(#lib "_version"), (char *)("The " #lib " version as a tuple of 3 numbers")}, \ + { \ + (char *)(#lib "_version_string"), (char *)("The " #lib " version formatted as a string") \ + } static PyStructSequence_Field app_ffmpeg_info_fields[] = { - {(char *)"supported", (char *)("Boolean, True when Blender is built with FFmpeg support")}, - - DEF_FFMPEG_LIB_VERSION(avcodec), - DEF_FFMPEG_LIB_VERSION(avdevice), - DEF_FFMPEG_LIB_VERSION(avformat), - DEF_FFMPEG_LIB_VERSION(avutil), - DEF_FFMPEG_LIB_VERSION(swscale), - {NULL}, + {(char *)"supported", (char *)("Boolean, True when Blender is built with FFmpeg support")}, + + DEF_FFMPEG_LIB_VERSION(avcodec), + DEF_FFMPEG_LIB_VERSION(avdevice), + DEF_FFMPEG_LIB_VERSION(avformat), + DEF_FFMPEG_LIB_VERSION(avutil), + DEF_FFMPEG_LIB_VERSION(swscale), + {NULL}, }; #undef DEF_FFMPEG_LIB_VERSION static PyStructSequence_Desc app_ffmpeg_info_desc = { - (char *)"bpy.app.ffmpeg", /* name */ - (char *)"This module contains information about FFmpeg blender is linked against", /* doc */ - app_ffmpeg_info_fields, /* fields */ - ARRAY_SIZE(app_ffmpeg_info_fields) - 1, + (char *)"bpy.app.ffmpeg", /* name */ + (char *)"This module contains information about FFmpeg blender is linked against", /* doc */ + app_ffmpeg_info_fields, /* fields */ + ARRAY_SIZE(app_ffmpeg_info_fields) - 1, }; static PyObject *make_ffmpeg_info(void) { - PyObject *ffmpeg_info; - int pos = 0; + PyObject *ffmpeg_info; + int pos = 0; #ifdef WITH_FFMPEG - int curversion; + int curversion; #endif - ffmpeg_info = PyStructSequence_New(&BlenderAppFFmpegType); - if (ffmpeg_info == NULL) { - return NULL; - } + ffmpeg_info = PyStructSequence_New(&BlenderAppFFmpegType); + if (ffmpeg_info == NULL) { + return NULL; + } -#if 0 // UNUSED -#define SetIntItem(flag) \ - PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyLong_FromLong(flag)) +#if 0 // UNUSED +# define SetIntItem(flag) PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyLong_FromLong(flag)) #endif #ifndef WITH_FFMPEG -#define SetStrItem(str) \ - PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyUnicode_FromString(str)) +# define SetStrItem(str) PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyUnicode_FromString(str)) #endif -#define SetObjItem(obj) \ - PyStructSequence_SET_ITEM(ffmpeg_info, pos++, obj) +#define SetObjItem(obj) PyStructSequence_SET_ITEM(ffmpeg_info, pos++, obj) #ifdef WITH_FFMPEG -# define FFMPEG_LIB_VERSION(lib) { \ - curversion = lib ## _version(); \ - SetObjItem(PyC_Tuple_Pack_I32(curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \ - SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", \ - curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \ -} (void)0 +# define FFMPEG_LIB_VERSION(lib) \ + { \ + curversion = lib##_version(); \ + SetObjItem( \ + PyC_Tuple_Pack_I32(curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \ + SetObjItem(PyUnicode_FromFormat( \ + "%2d, %2d, %2d", curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \ + } \ + (void)0 #else -# define FFMPEG_LIB_VERSION(lib) { \ - SetStrItem("Unknown"); \ - SetStrItem("Unknown"); \ -} (void)0 +# define FFMPEG_LIB_VERSION(lib) \ + { \ + SetStrItem("Unknown"); \ + SetStrItem("Unknown"); \ + } \ + (void)0 #endif #ifdef WITH_FFMPEG - SetObjItem(PyBool_FromLong(1)); + SetObjItem(PyBool_FromLong(1)); #else - SetObjItem(PyBool_FromLong(0)); + SetObjItem(PyBool_FromLong(0)); #endif - FFMPEG_LIB_VERSION(avcodec); - FFMPEG_LIB_VERSION(avdevice); - FFMPEG_LIB_VERSION(avformat); - FFMPEG_LIB_VERSION(avutil); - FFMPEG_LIB_VERSION(swscale); + FFMPEG_LIB_VERSION(avcodec); + FFMPEG_LIB_VERSION(avdevice); + FFMPEG_LIB_VERSION(avformat); + FFMPEG_LIB_VERSION(avutil); + FFMPEG_LIB_VERSION(swscale); #undef FFMPEG_LIB_VERSION - if (PyErr_Occurred()) { - Py_CLEAR(ffmpeg_info); - return NULL; - } + if (PyErr_Occurred()) { + Py_CLEAR(ffmpeg_info); + return NULL; + } // #undef SetIntItem #undef SetStrItem #undef SetObjItem - return ffmpeg_info; + return ffmpeg_info; } PyObject *BPY_app_ffmpeg_struct(void) { - PyObject *ret; + PyObject *ret; - PyStructSequence_InitType(&BlenderAppFFmpegType, &app_ffmpeg_info_desc); + PyStructSequence_InitType(&BlenderAppFFmpegType, &app_ffmpeg_info_desc); - ret = make_ffmpeg_info(); + ret = make_ffmpeg_info(); - /* prevent user from creating new instances */ - BlenderAppFFmpegType.tp_init = NULL; - BlenderAppFFmpegType.tp_new = NULL; - BlenderAppFFmpegType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + /* prevent user from creating new instances */ + BlenderAppFFmpegType.tp_init = NULL; + BlenderAppFFmpegType.tp_new = NULL; + BlenderAppFFmpegType.tp_hash = (hashfunc) + _Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ - return ret; + return ret; } diff --git a/source/blender/python/intern/bpy_app_ffmpeg.h b/source/blender/python/intern/bpy_app_ffmpeg.h index 063781a54a5..63fff2b1b4b 100644 --- a/source/blender/python/intern/bpy_app_ffmpeg.h +++ b/source/blender/python/intern/bpy_app_ffmpeg.h @@ -23,4 +23,4 @@ PyObject *BPY_app_ffmpeg_struct(void); -#endif /* __BPY_APP_FFMPEG_H__ */ +#endif /* __BPY_APP_FFMPEG_H__ */ diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index c91c0d69a16..7134bf520ac 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -40,40 +40,42 @@ void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg); static PyTypeObject BlenderAppCbType; static PyStructSequence_Field app_cb_info_fields[] = { - {(char *)"frame_change_pre", (char *)"on frame change for playback and rendering (before)"}, - {(char *)"frame_change_post", (char *)"on frame change for playback and rendering (after)"}, - {(char *)"render_pre", (char *)"on render (before)"}, - {(char *)"render_post", (char *)"on render (after)"}, - {(char *)"render_write", (char *)"on writing a render frame (directly after the frame is written)"}, - {(char *)"render_stats", (char *)"on printing render statistics"}, - {(char *)"render_init", (char *)"on initialization of a render job"}, - {(char *)"render_complete", (char *)"on completion of render job"}, - {(char *)"render_cancel", (char *)"on canceling a render job"}, - {(char *)"load_pre", (char *)"on loading a new blend file (before)"}, - {(char *)"load_post", (char *)"on loading a new blend file (after)"}, - {(char *)"save_pre", (char *)"on saving a blend file (before)"}, - {(char *)"save_post", (char *)"on saving a blend file (after)"}, - {(char *)"undo_pre", (char *)"on loading an undo step (before)"}, - {(char *)"undo_post", (char *)"on loading an undo step (after)"}, - {(char *)"redo_pre", (char *)"on loading a redo step (before)"}, - {(char *)"redo_post", (char *)"on loading a redo step (after)"}, - {(char *)"depsgraph_update_pre", (char *)"on depsgraph update (pre)"}, - {(char *)"depsgraph_update_post", (char *)"on depsgraph update (post)"}, - {(char *)"version_update", (char *)"on ending the versioning code"}, - {(char *)"load_factory_startup_post", (char *)"on loading factory startup (after)"}, - - /* sets the permanent tag */ + {(char *)"frame_change_pre", (char *)"on frame change for playback and rendering (before)"}, + {(char *)"frame_change_post", (char *)"on frame change for playback and rendering (after)"}, + {(char *)"render_pre", (char *)"on render (before)"}, + {(char *)"render_post", (char *)"on render (after)"}, + {(char *)"render_write", + (char *)"on writing a render frame (directly after the frame is written)"}, + {(char *)"render_stats", (char *)"on printing render statistics"}, + {(char *)"render_init", (char *)"on initialization of a render job"}, + {(char *)"render_complete", (char *)"on completion of render job"}, + {(char *)"render_cancel", (char *)"on canceling a render job"}, + {(char *)"load_pre", (char *)"on loading a new blend file (before)"}, + {(char *)"load_post", (char *)"on loading a new blend file (after)"}, + {(char *)"save_pre", (char *)"on saving a blend file (before)"}, + {(char *)"save_post", (char *)"on saving a blend file (after)"}, + {(char *)"undo_pre", (char *)"on loading an undo step (before)"}, + {(char *)"undo_post", (char *)"on loading an undo step (after)"}, + {(char *)"redo_pre", (char *)"on loading a redo step (before)"}, + {(char *)"redo_post", (char *)"on loading a redo step (after)"}, + {(char *)"depsgraph_update_pre", (char *)"on depsgraph update (pre)"}, + {(char *)"depsgraph_update_post", (char *)"on depsgraph update (post)"}, + {(char *)"version_update", (char *)"on ending the versioning code"}, + {(char *)"load_factory_startup_post", (char *)"on loading factory startup (after)"}, + +/* sets the permanent tag */ #define APP_CB_OTHER_FIELDS 1 - {(char *)"persistent", (char *)"Function decorator for callback functions not to be removed when loading new files"}, + {(char *)"persistent", + (char *)"Function decorator for callback functions not to be removed when loading new files"}, - {NULL}, + {NULL}, }; static PyStructSequence_Desc app_cb_info_desc = { - (char *)"bpy.app.handlers", /* name */ - (char *)"This module contains callback lists", /* doc */ - app_cb_info_fields, /* fields */ - ARRAY_SIZE(app_cb_info_fields) - 1, + (char *)"bpy.app.handlers", /* name */ + (char *)"This module contains callback lists", /* doc */ + app_cb_info_fields, /* fields */ + ARRAY_SIZE(app_cb_info_fields) - 1, }; #if 0 @@ -86,251 +88,250 @@ static PyStructSequence_Desc app_cb_info_desc = { /* permanent tagging code */ #define PERMINENT_CB_ID "_bpy_persistent" -static PyObject *bpy_app_handlers_persistent_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *UNUSED(kwds)) +static PyObject *bpy_app_handlers_persistent_new(PyTypeObject *UNUSED(type), + PyObject *args, + PyObject *UNUSED(kwds)) { - PyObject *value; - - if (!PyArg_ParseTuple(args, "O:bpy.app.handlers.persistent", &value)) { - return NULL; - } - - if (PyFunction_Check(value)) { - PyObject **dict_ptr = _PyObject_GetDictPtr(value); - if (dict_ptr == NULL) { - PyErr_SetString(PyExc_ValueError, - "bpy.app.handlers.persistent wasn't able to " - "get the dictionary from the function passed"); - return NULL; - } - else { - /* set id */ - if (*dict_ptr == NULL) { - *dict_ptr = PyDict_New(); - } - - PyDict_SetItemString(*dict_ptr, PERMINENT_CB_ID, Py_None); - } - - Py_INCREF(value); - return value; - } - else { - PyErr_SetString(PyExc_ValueError, - "bpy.app.handlers.persistent expected a function"); - return NULL; - } + PyObject *value; + + if (!PyArg_ParseTuple(args, "O:bpy.app.handlers.persistent", &value)) { + return NULL; + } + + if (PyFunction_Check(value)) { + PyObject **dict_ptr = _PyObject_GetDictPtr(value); + if (dict_ptr == NULL) { + PyErr_SetString(PyExc_ValueError, + "bpy.app.handlers.persistent wasn't able to " + "get the dictionary from the function passed"); + return NULL; + } + else { + /* set id */ + if (*dict_ptr == NULL) { + *dict_ptr = PyDict_New(); + } + + PyDict_SetItemString(*dict_ptr, PERMINENT_CB_ID, Py_None); + } + + Py_INCREF(value); + return value; + } + else { + PyErr_SetString(PyExc_ValueError, "bpy.app.handlers.persistent expected a function"); + return NULL; + } } /* dummy type because decorators can't be PyCFunctions */ static PyTypeObject BPyPersistent_Type = { #if defined(_MSC_VER) - PyVarObject_HEAD_INIT(NULL, 0) + PyVarObject_HEAD_INIT(NULL, 0) #else - PyVarObject_HEAD_INIT(&PyType_Type, 0) + PyVarObject_HEAD_INIT(&PyType_Type, 0) #endif - "persistent", /* tp_name */ - 0, /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - bpy_app_handlers_persistent_new, /* tp_new */ - 0, /* tp_free */ + "persistent", /* tp_name */ + 0, /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + bpy_app_handlers_persistent_new, /* tp_new */ + 0, /* tp_free */ }; static PyObject *py_cb_array[BLI_CB_EVT_TOT] = {NULL}; static PyObject *make_app_cb_info(void) { - PyObject *app_cb_info; - int pos; - - app_cb_info = PyStructSequence_New(&BlenderAppCbType); - if (app_cb_info == NULL) { - return NULL; - } - - for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) { - if (app_cb_info_fields[pos].name == NULL) { - Py_FatalError("invalid callback slots 1"); - } - PyStructSequence_SET_ITEM(app_cb_info, pos, (py_cb_array[pos] = PyList_New(0))); - } - if (app_cb_info_fields[pos + APP_CB_OTHER_FIELDS].name != NULL) { - Py_FatalError("invalid callback slots 2"); - } - - /* custom function */ - PyStructSequence_SET_ITEM(app_cb_info, pos++, (PyObject *)&BPyPersistent_Type); - - return app_cb_info; + PyObject *app_cb_info; + int pos; + + app_cb_info = PyStructSequence_New(&BlenderAppCbType); + if (app_cb_info == NULL) { + return NULL; + } + + for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) { + if (app_cb_info_fields[pos].name == NULL) { + Py_FatalError("invalid callback slots 1"); + } + PyStructSequence_SET_ITEM(app_cb_info, pos, (py_cb_array[pos] = PyList_New(0))); + } + if (app_cb_info_fields[pos + APP_CB_OTHER_FIELDS].name != NULL) { + Py_FatalError("invalid callback slots 2"); + } + + /* custom function */ + PyStructSequence_SET_ITEM(app_cb_info, pos++, (PyObject *)&BPyPersistent_Type); + + return app_cb_info; } PyObject *BPY_app_handlers_struct(void) { - PyObject *ret; + PyObject *ret; #if defined(_MSC_VER) - BPyPersistent_Type.ob_base.ob_base.ob_type = &PyType_Type; + BPyPersistent_Type.ob_base.ob_base.ob_type = &PyType_Type; #endif - if (PyType_Ready(&BPyPersistent_Type) < 0) { - BLI_assert(!"error initializing 'bpy.app.handlers.persistent'"); - } + if (PyType_Ready(&BPyPersistent_Type) < 0) { + BLI_assert(!"error initializing 'bpy.app.handlers.persistent'"); + } - PyStructSequence_InitType(&BlenderAppCbType, &app_cb_info_desc); + PyStructSequence_InitType(&BlenderAppCbType, &app_cb_info_desc); - ret = make_app_cb_info(); + ret = make_app_cb_info(); - /* prevent user from creating new instances */ - BlenderAppCbType.tp_init = NULL; - BlenderAppCbType.tp_new = NULL; - BlenderAppCbType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + /* prevent user from creating new instances */ + BlenderAppCbType.tp_init = NULL; + BlenderAppCbType.tp_new = NULL; + BlenderAppCbType.tp_hash = (hashfunc) + _Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ - /* assign the C callbacks */ - if (ret) { - static bCallbackFuncStore funcstore_array[BLI_CB_EVT_TOT] = {{NULL}}; - bCallbackFuncStore *funcstore; - int pos = 0; + /* assign the C callbacks */ + if (ret) { + static bCallbackFuncStore funcstore_array[BLI_CB_EVT_TOT] = {{NULL}}; + bCallbackFuncStore *funcstore; + int pos = 0; - for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) { - funcstore = &funcstore_array[pos]; - funcstore->func = bpy_app_generic_callback; - funcstore->alloc = 0; - funcstore->arg = POINTER_FROM_INT(pos); - BLI_callback_add(funcstore, pos); - } - } + for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) { + funcstore = &funcstore_array[pos]; + funcstore->func = bpy_app_generic_callback; + funcstore->alloc = 0; + funcstore->arg = POINTER_FROM_INT(pos); + BLI_callback_add(funcstore, pos); + } + } - return ret; + return ret; } void BPY_app_handlers_reset(const short do_all) { - PyGILState_STATE gilstate; - int pos = 0; - - gilstate = PyGILState_Ensure(); - - if (do_all) { - for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) { - /* clear list */ - PyList_SetSlice(py_cb_array[pos], 0, PY_SSIZE_T_MAX, NULL); - } - } - else { - /* save string conversion thrashing */ - PyObject *perm_id_str = PyUnicode_FromString(PERMINENT_CB_ID); - - for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) { - /* clear only items without PERMINENT_CB_ID */ - PyObject *ls = py_cb_array[pos]; - Py_ssize_t i; - - PyObject *item; - PyObject **dict_ptr; - - for (i = PyList_GET_SIZE(ls) - 1; i >= 0; i--) { - - if ((PyFunction_Check((item = PyList_GET_ITEM(ls, i)))) && - (dict_ptr = _PyObject_GetDictPtr(item)) && - (*dict_ptr) && - (PyDict_GetItem(*dict_ptr, perm_id_str) != NULL)) - { - /* keep */ - } - else { - /* remove */ - /* PySequence_DelItem(ls, i); */ /* more obvious buw slower */ - PyList_SetSlice(ls, i, i + 1, NULL); - } - } - } - - Py_DECREF(perm_id_str); - } - - PyGILState_Release(gilstate); + PyGILState_STATE gilstate; + int pos = 0; + + gilstate = PyGILState_Ensure(); + + if (do_all) { + for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) { + /* clear list */ + PyList_SetSlice(py_cb_array[pos], 0, PY_SSIZE_T_MAX, NULL); + } + } + else { + /* save string conversion thrashing */ + PyObject *perm_id_str = PyUnicode_FromString(PERMINENT_CB_ID); + + for (pos = 0; pos < BLI_CB_EVT_TOT; pos++) { + /* clear only items without PERMINENT_CB_ID */ + PyObject *ls = py_cb_array[pos]; + Py_ssize_t i; + + PyObject *item; + PyObject **dict_ptr; + + for (i = PyList_GET_SIZE(ls) - 1; i >= 0; i--) { + + if ((PyFunction_Check((item = PyList_GET_ITEM(ls, i)))) && + (dict_ptr = _PyObject_GetDictPtr(item)) && (*dict_ptr) && + (PyDict_GetItem(*dict_ptr, perm_id_str) != NULL)) { + /* keep */ + } + else { + /* remove */ + /* PySequence_DelItem(ls, i); */ /* more obvious buw slower */ + PyList_SetSlice(ls, i, i + 1, NULL); + } + } + } + + Py_DECREF(perm_id_str); + } + + PyGILState_Release(gilstate); } /* the actual callback - not necessarily called from py */ void bpy_app_generic_callback(struct Main *UNUSED(main), struct ID *id, void *arg) { - PyObject *cb_list = py_cb_array[POINTER_AS_INT(arg)]; - if (PyList_GET_SIZE(cb_list) > 0) { - PyGILState_STATE gilstate = PyGILState_Ensure(); - - PyObject *args = PyTuple_New(1); /* save python creating each call */ - PyObject *func; - PyObject *ret; - Py_ssize_t pos; - - /* setup arguments */ - if (id) { - PointerRNA id_ptr; - RNA_id_pointer_create(id, &id_ptr); - PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&id_ptr)); - } - else { - PyTuple_SET_ITEM(args, 0, Py_INCREF_RET(Py_None)); - } - - /* Iterate the list and run the callbacks - * note: don't store the list size since the scripts may remove themselves */ - for (pos = 0; pos < PyList_GET_SIZE(cb_list); pos++) { - func = PyList_GET_ITEM(cb_list, pos); - ret = PyObject_Call(func, args, NULL); - if (ret == NULL) { - /* Don't set last system variables because they might cause some - * dangling pointers to external render engines (when exception - * happens during rendering) which will break logic of render pipeline - * which expects to be the only user of render engine when rendering - * is finished. - */ - PyErr_PrintEx(0); - PyErr_Clear(); - } - else { - Py_DECREF(ret); - } - } - - Py_DECREF(args); - - PyGILState_Release(gilstate); - } + PyObject *cb_list = py_cb_array[POINTER_AS_INT(arg)]; + if (PyList_GET_SIZE(cb_list) > 0) { + PyGILState_STATE gilstate = PyGILState_Ensure(); + + PyObject *args = PyTuple_New(1); /* save python creating each call */ + PyObject *func; + PyObject *ret; + Py_ssize_t pos; + + /* setup arguments */ + if (id) { + PointerRNA id_ptr; + RNA_id_pointer_create(id, &id_ptr); + PyTuple_SET_ITEM(args, 0, pyrna_struct_CreatePyObject(&id_ptr)); + } + else { + PyTuple_SET_ITEM(args, 0, Py_INCREF_RET(Py_None)); + } + + /* Iterate the list and run the callbacks + * note: don't store the list size since the scripts may remove themselves */ + for (pos = 0; pos < PyList_GET_SIZE(cb_list); pos++) { + func = PyList_GET_ITEM(cb_list, pos); + ret = PyObject_Call(func, args, NULL); + if (ret == NULL) { + /* Don't set last system variables because they might cause some + * dangling pointers to external render engines (when exception + * happens during rendering) which will break logic of render pipeline + * which expects to be the only user of render engine when rendering + * is finished. + */ + PyErr_PrintEx(0); + PyErr_Clear(); + } + else { + Py_DECREF(ret); + } + } + + Py_DECREF(args); + + PyGILState_Release(gilstate); + } } diff --git a/source/blender/python/intern/bpy_app_icons.c b/source/blender/python/intern/bpy_app_icons.c index 863d11ff84d..2e688609961 100644 --- a/source/blender/python/intern/bpy_app_icons.c +++ b/source/blender/python/intern/bpy_app_icons.c @@ -33,151 +33,149 @@ #include "bpy_app_icons.h" /* We may want to load direct from file. */ -PyDoc_STRVAR(bpy_app_icons_new_triangles_doc, -".. function:: new_triangles(range, coords, colors)" -"\n" -" Create a new icon from triangle geometry.\n" -"\n" -" :arg range: Pair of ints.\n" -" :type range: tuple.\n" -" :arg coords: Sequence of bytes (6 floats for one triangle) for (X, Y) coordinates.\n" -" :type coords: byte sequence.\n" -" :arg colors: Sequence of ints (12 for one triangles) for RGBA.\n" -" :type colors: byte sequence.\n" -" :return: Unique icon value (pass to interface ``icon_value`` argument).\n" -" :rtype: int\n" -); +PyDoc_STRVAR( + bpy_app_icons_new_triangles_doc, + ".. function:: new_triangles(range, coords, colors)" + "\n" + " Create a new icon from triangle geometry.\n" + "\n" + " :arg range: Pair of ints.\n" + " :type range: tuple.\n" + " :arg coords: Sequence of bytes (6 floats for one triangle) for (X, Y) coordinates.\n" + " :type coords: byte sequence.\n" + " :arg colors: Sequence of ints (12 for one triangles) for RGBA.\n" + " :type colors: byte sequence.\n" + " :return: Unique icon value (pass to interface ``icon_value`` argument).\n" + " :rtype: int\n"); static PyObject *bpy_app_icons_new_triangles(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - /* bytes */ - uchar coords_range[2]; - PyObject *py_coords, *py_colors; - - static const char *_keywords[] = {"range", "coords", "colors", NULL}; - static _PyArg_Parser _parser = {"(BB)SS:new_triangles", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &coords_range[0], &coords_range[1], &py_coords, &py_colors)) - { - return NULL; - } - - const int coords_len = PyBytes_GET_SIZE(py_coords); - const int tris_len = coords_len / 6; - if (tris_len * 6 != coords_len) { - PyErr_SetString(PyExc_ValueError, "coords must be multiple of 6"); - return NULL; - } - if (PyBytes_GET_SIZE(py_colors) != 2 * coords_len) { - PyErr_SetString(PyExc_ValueError, "colors must be twice size of coords"); - return NULL; - } - - int coords_size = sizeof(uchar[2]) * tris_len * 3; - int colors_size = sizeof(uchar[4]) * tris_len * 3; - uchar (*coords)[2] = MEM_mallocN(coords_size, __func__); - uchar (*colors)[4] = MEM_mallocN(colors_size, __func__); - - memcpy(coords, PyBytes_AS_STRING(py_coords), coords_size); - memcpy(colors, PyBytes_AS_STRING(py_colors), colors_size); - - struct Icon_Geom *geom = MEM_mallocN(sizeof(*geom), __func__); - geom->coords_len = tris_len; - geom->coords_range[0] = coords_range[0]; - geom->coords_range[1] = coords_range[1]; - geom->coords = coords; - geom->colors = colors; - geom->icon_id = 0; - int icon_id = BKE_icon_geom_ensure(geom); - return PyLong_FromLong(icon_id); + /* bytes */ + uchar coords_range[2]; + PyObject *py_coords, *py_colors; + + static const char *_keywords[] = {"range", "coords", "colors", NULL}; + static _PyArg_Parser _parser = {"(BB)SS:new_triangles", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast( + args, kw, &_parser, &coords_range[0], &coords_range[1], &py_coords, &py_colors)) { + return NULL; + } + + const int coords_len = PyBytes_GET_SIZE(py_coords); + const int tris_len = coords_len / 6; + if (tris_len * 6 != coords_len) { + PyErr_SetString(PyExc_ValueError, "coords must be multiple of 6"); + return NULL; + } + if (PyBytes_GET_SIZE(py_colors) != 2 * coords_len) { + PyErr_SetString(PyExc_ValueError, "colors must be twice size of coords"); + return NULL; + } + + int coords_size = sizeof(uchar[2]) * tris_len * 3; + int colors_size = sizeof(uchar[4]) * tris_len * 3; + uchar(*coords)[2] = MEM_mallocN(coords_size, __func__); + uchar(*colors)[4] = MEM_mallocN(colors_size, __func__); + + memcpy(coords, PyBytes_AS_STRING(py_coords), coords_size); + memcpy(colors, PyBytes_AS_STRING(py_colors), colors_size); + + struct Icon_Geom *geom = MEM_mallocN(sizeof(*geom), __func__); + geom->coords_len = tris_len; + geom->coords_range[0] = coords_range[0]; + geom->coords_range[1] = coords_range[1]; + geom->coords = coords; + geom->colors = colors; + geom->icon_id = 0; + int icon_id = BKE_icon_geom_ensure(geom); + return PyLong_FromLong(icon_id); } PyDoc_STRVAR(bpy_app_icons_new_triangles_from_file_doc, -".. function:: new_triangles_from_file(filename)" -"\n" -" Create a new icon from triangle geometry.\n" -"\n" -" :arg filename: File path.\n" -" :type filename: string.\n" -" :return: Unique icon value (pass to interface ``icon_value`` argument).\n" -" :rtype: int\n" -); -static PyObject *bpy_app_icons_new_triangles_from_file(PyObject *UNUSED(self), PyObject *args, PyObject *kw) + ".. function:: new_triangles_from_file(filename)" + "\n" + " Create a new icon from triangle geometry.\n" + "\n" + " :arg filename: File path.\n" + " :type filename: string.\n" + " :return: Unique icon value (pass to interface ``icon_value`` argument).\n" + " :rtype: int\n"); +static PyObject *bpy_app_icons_new_triangles_from_file(PyObject *UNUSED(self), + PyObject *args, + PyObject *kw) { - /* bytes */ - char *filename; - - static const char *_keywords[] = {"filename", NULL}; - static _PyArg_Parser _parser = {"s:new_triangles_from_file", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &filename)) - { - return NULL; - } - - struct Icon_Geom *geom = BKE_icon_geom_from_file(filename); - if (geom == NULL) { - PyErr_SetString(PyExc_ValueError, "Unable to load from file"); - return NULL; - } - int icon_id = BKE_icon_geom_ensure(geom); - return PyLong_FromLong(icon_id); + /* bytes */ + char *filename; + + static const char *_keywords[] = {"filename", NULL}; + static _PyArg_Parser _parser = {"s:new_triangles_from_file", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &filename)) { + return NULL; + } + + struct Icon_Geom *geom = BKE_icon_geom_from_file(filename); + if (geom == NULL) { + PyErr_SetString(PyExc_ValueError, "Unable to load from file"); + return NULL; + } + int icon_id = BKE_icon_geom_ensure(geom); + return PyLong_FromLong(icon_id); } PyDoc_STRVAR(bpy_app_icons_release_doc, -".. function:: release(icon_id)" -"\n" -" Release the icon.\n" -); + ".. function:: release(icon_id)" + "\n" + " Release the icon.\n"); static PyObject *bpy_app_icons_release(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - int icon_id; - static const char *_keywords[] = {"icon_id", NULL}; - static _PyArg_Parser _parser = {"i:release", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &icon_id)) - { - return NULL; - } - - if (!BKE_icon_delete_unmanaged(icon_id)) { - PyErr_SetString(PyExc_ValueError, "invalid icon_id"); - return NULL; - } - Py_RETURN_NONE; + int icon_id; + static const char *_keywords[] = {"icon_id", NULL}; + static _PyArg_Parser _parser = {"i:release", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &icon_id)) { + return NULL; + } + + if (!BKE_icon_delete_unmanaged(icon_id)) { + PyErr_SetString(PyExc_ValueError, "invalid icon_id"); + return NULL; + } + Py_RETURN_NONE; } static struct PyMethodDef M_AppIcons_methods[] = { - {"new_triangles", (PyCFunction)bpy_app_icons_new_triangles, - METH_VARARGS | METH_KEYWORDS, bpy_app_icons_new_triangles_doc}, - {"new_triangles_from_file", (PyCFunction)bpy_app_icons_new_triangles_from_file, - METH_VARARGS | METH_KEYWORDS, bpy_app_icons_new_triangles_from_file_doc}, - {"release", (PyCFunction)bpy_app_icons_release, - METH_VARARGS | METH_KEYWORDS, bpy_app_icons_release_doc}, - {NULL, NULL, 0, NULL}, + {"new_triangles", + (PyCFunction)bpy_app_icons_new_triangles, + METH_VARARGS | METH_KEYWORDS, + bpy_app_icons_new_triangles_doc}, + {"new_triangles_from_file", + (PyCFunction)bpy_app_icons_new_triangles_from_file, + METH_VARARGS | METH_KEYWORDS, + bpy_app_icons_new_triangles_from_file_doc}, + {"release", + (PyCFunction)bpy_app_icons_release, + METH_VARARGS | METH_KEYWORDS, + bpy_app_icons_release_doc}, + {NULL, NULL, 0, NULL}, }; static struct PyModuleDef M_AppIcons_module_def = { - PyModuleDef_HEAD_INIT, - "bpy.app.icons", /* m_name */ - NULL, /* m_doc */ - 0, /* m_size */ - M_AppIcons_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + PyModuleDef_HEAD_INIT, + "bpy.app.icons", /* m_name */ + NULL, /* m_doc */ + 0, /* m_size */ + M_AppIcons_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; PyObject *BPY_app_icons_module(void) { - PyObject *sys_modules = PyImport_GetModuleDict(); + PyObject *sys_modules = PyImport_GetModuleDict(); - PyObject *mod = PyModule_Create(&M_AppIcons_module_def); + PyObject *mod = PyModule_Create(&M_AppIcons_module_def); - PyDict_SetItem(sys_modules, PyModule_GetNameObject(mod), mod); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(mod), mod); - return mod; + return mod; } diff --git a/source/blender/python/intern/bpy_app_ocio.c b/source/blender/python/intern/bpy_app_ocio.c index deb025e0e33..2a56075e00e 100644 --- a/source/blender/python/intern/bpy_app_ocio.c +++ b/source/blender/python/intern/bpy_app_ocio.c @@ -32,76 +32,78 @@ static PyTypeObject BlenderAppOCIOType; static PyStructSequence_Field app_ocio_info_fields[] = { - {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenColorIO support")}, - {(char *)("version"), (char *)("The OpenColorIO version as a tuple of 3 numbers")}, - {(char *)("version_string"), (char *)("The OpenColorIO version formatted as a string")}, - {NULL}, + {(char *)"supported", + (char *)("Boolean, True when Blender is built with OpenColorIO support")}, + {(char *)("version"), (char *)("The OpenColorIO version as a tuple of 3 numbers")}, + {(char *)("version_string"), (char *)("The OpenColorIO version formatted as a string")}, + {NULL}, }; static PyStructSequence_Desc app_ocio_info_desc = { - (char *)"bpy.app.ocio", /* name */ - (char *)"This module contains information about OpenColorIO blender is linked against", /* doc */ - app_ocio_info_fields, /* fields */ - ARRAY_SIZE(app_ocio_info_fields) - 1, + (char *)"bpy.app.ocio", /* name */ + (char + *)"This module contains information about OpenColorIO blender is linked against", /* doc */ + app_ocio_info_fields, /* fields */ + ARRAY_SIZE(app_ocio_info_fields) - 1, }; static PyObject *make_ocio_info(void) { - PyObject *ocio_info; - int pos = 0; + PyObject *ocio_info; + int pos = 0; #ifdef WITH_OCIO - int curversion; + int curversion; #endif - ocio_info = PyStructSequence_New(&BlenderAppOCIOType); - if (ocio_info == NULL) { - return NULL; - } + ocio_info = PyStructSequence_New(&BlenderAppOCIOType); + if (ocio_info == NULL) { + return NULL; + } #ifndef WITH_OCIO -#define SetStrItem(str) \ - PyStructSequence_SET_ITEM(ocio_info, pos++, PyUnicode_FromString(str)) +# define SetStrItem(str) PyStructSequence_SET_ITEM(ocio_info, pos++, PyUnicode_FromString(str)) #endif -#define SetObjItem(obj) \ - PyStructSequence_SET_ITEM(ocio_info, pos++, obj) +#define SetObjItem(obj) PyStructSequence_SET_ITEM(ocio_info, pos++, obj) #ifdef WITH_OCIO - curversion = OCIO_getVersionHex(); - SetObjItem(PyBool_FromLong(1)); - SetObjItem(PyC_Tuple_Pack_I32(curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256)); - SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", - curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256)); + curversion = OCIO_getVersionHex(); + SetObjItem(PyBool_FromLong(1)); + SetObjItem( + PyC_Tuple_Pack_I32(curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256)); + SetObjItem(PyUnicode_FromFormat( + "%2d, %2d, %2d", curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256)); #else - SetObjItem(PyBool_FromLong(0)); - SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); - SetStrItem("Unknown"); + SetObjItem(PyBool_FromLong(0)); + SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); + SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(ocio_info); - return NULL; - } + if (PyErr_Occurred()) { + Py_CLEAR(ocio_info); + return NULL; + } #undef SetStrItem #undef SetObjItem - return ocio_info; + return ocio_info; } PyObject *BPY_app_ocio_struct(void) { - PyObject *ret; + PyObject *ret; - PyStructSequence_InitType(&BlenderAppOCIOType, &app_ocio_info_desc); + PyStructSequence_InitType(&BlenderAppOCIOType, &app_ocio_info_desc); - ret = make_ocio_info(); + ret = make_ocio_info(); - /* prevent user from creating new instances */ - BlenderAppOCIOType.tp_init = NULL; - BlenderAppOCIOType.tp_new = NULL; - BlenderAppOCIOType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + /* prevent user from creating new instances */ + BlenderAppOCIOType.tp_init = NULL; + BlenderAppOCIOType.tp_new = NULL; + BlenderAppOCIOType.tp_hash = (hashfunc) + _Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ - return ret; + return ret; } diff --git a/source/blender/python/intern/bpy_app_ocio.h b/source/blender/python/intern/bpy_app_ocio.h index 54ecad2c5ed..66fc03657c1 100644 --- a/source/blender/python/intern/bpy_app_ocio.h +++ b/source/blender/python/intern/bpy_app_ocio.h @@ -23,4 +23,4 @@ PyObject *BPY_app_ocio_struct(void); -#endif /* __BPY_APP_OCIO_H__ */ +#endif /* __BPY_APP_OCIO_H__ */ diff --git a/source/blender/python/intern/bpy_app_oiio.c b/source/blender/python/intern/bpy_app_oiio.c index 5701a8def92..05c192f6e2e 100644 --- a/source/blender/python/intern/bpy_app_oiio.c +++ b/source/blender/python/intern/bpy_app_oiio.c @@ -32,76 +32,77 @@ static PyTypeObject BlenderAppOIIOType; static PyStructSequence_Field app_oiio_info_fields[] = { - {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenImageIO support")}, - {(char *)("version"), (char *)("The OpenImageIO version as a tuple of 3 numbers")}, - {(char *)("version_string"), (char *)("The OpenImageIO version formatted as a string")}, - {NULL}, + {(char *)"supported", + (char *)("Boolean, True when Blender is built with OpenImageIO support")}, + {(char *)("version"), (char *)("The OpenImageIO version as a tuple of 3 numbers")}, + {(char *)("version_string"), (char *)("The OpenImageIO version formatted as a string")}, + {NULL}, }; static PyStructSequence_Desc app_oiio_info_desc = { - (char *)"bpy.app.oiio", /* name */ - (char *)"This module contains information about OpeImageIO blender is linked against", /* doc */ - app_oiio_info_fields, /* fields */ - ARRAY_SIZE(app_oiio_info_fields) - 1, + (char *)"bpy.app.oiio", /* name */ + (char + *)"This module contains information about OpeImageIO blender is linked against", /* doc */ + app_oiio_info_fields, /* fields */ + ARRAY_SIZE(app_oiio_info_fields) - 1, }; static PyObject *make_oiio_info(void) { - PyObject *oiio_info; - int pos = 0; + PyObject *oiio_info; + int pos = 0; #ifdef WITH_OPENIMAGEIO - int curversion; + int curversion; #endif - oiio_info = PyStructSequence_New(&BlenderAppOIIOType); - if (oiio_info == NULL) { - return NULL; - } + oiio_info = PyStructSequence_New(&BlenderAppOIIOType); + if (oiio_info == NULL) { + return NULL; + } #ifndef WITH_OPENIMAGEIO -#define SetStrItem(str) \ - PyStructSequence_SET_ITEM(oiio_info, pos++, PyUnicode_FromString(str)) +# define SetStrItem(str) PyStructSequence_SET_ITEM(oiio_info, pos++, PyUnicode_FromString(str)) #endif -#define SetObjItem(obj) \ - PyStructSequence_SET_ITEM(oiio_info, pos++, obj) +#define SetObjItem(obj) PyStructSequence_SET_ITEM(oiio_info, pos++, obj) #ifdef WITH_OPENIMAGEIO - curversion = OIIO_getVersionHex(); - SetObjItem(PyBool_FromLong(1)); - SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100)); - SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", - curversion / 10000, (curversion / 100) % 100, curversion % 100)); + curversion = OIIO_getVersionHex(); + SetObjItem(PyBool_FromLong(1)); + SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100)); + SetObjItem(PyUnicode_FromFormat( + "%2d, %2d, %2d", curversion / 10000, (curversion / 100) % 100, curversion % 100)); #else - SetObjItem(PyBool_FromLong(0)); - SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); - SetStrItem("Unknown"); + SetObjItem(PyBool_FromLong(0)); + SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); + SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(oiio_info); - return NULL; - } + if (PyErr_Occurred()) { + Py_CLEAR(oiio_info); + return NULL; + } #undef SetStrItem #undef SetObjItem - return oiio_info; + return oiio_info; } PyObject *BPY_app_oiio_struct(void) { - PyObject *ret; + PyObject *ret; - PyStructSequence_InitType(&BlenderAppOIIOType, &app_oiio_info_desc); + PyStructSequence_InitType(&BlenderAppOIIOType, &app_oiio_info_desc); - ret = make_oiio_info(); + ret = make_oiio_info(); - /* prevent user from creating new instances */ - BlenderAppOIIOType.tp_init = NULL; - BlenderAppOIIOType.tp_new = NULL; - BlenderAppOIIOType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + /* prevent user from creating new instances */ + BlenderAppOIIOType.tp_init = NULL; + BlenderAppOIIOType.tp_new = NULL; + BlenderAppOIIOType.tp_hash = (hashfunc) + _Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ - return ret; + return ret; } diff --git a/source/blender/python/intern/bpy_app_oiio.h b/source/blender/python/intern/bpy_app_oiio.h index f2832b23936..4b08652dff5 100644 --- a/source/blender/python/intern/bpy_app_oiio.h +++ b/source/blender/python/intern/bpy_app_oiio.h @@ -23,4 +23,4 @@ PyObject *BPY_app_oiio_struct(void); -#endif /* __BPY_APP_OIIO_H__ */ +#endif /* __BPY_APP_OIIO_H__ */ diff --git a/source/blender/python/intern/bpy_app_opensubdiv.c b/source/blender/python/intern/bpy_app_opensubdiv.c index 7c084605fd3..e6e84ac30c0 100644 --- a/source/blender/python/intern/bpy_app_opensubdiv.c +++ b/source/blender/python/intern/bpy_app_opensubdiv.c @@ -32,73 +32,73 @@ static PyTypeObject BlenderAppOpenSubdivType; static PyStructSequence_Field app_opensubdiv_info_fields[] = { - {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenSubdiv support")}, - {(char *)("version"), (char *)("The OpenSubdiv version as a tuple of 3 numbers")}, - {(char *)("version_string"), (char *)("The OpenSubdiv version formatted as a string")}, - {NULL}, + {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenSubdiv support")}, + {(char *)("version"), (char *)("The OpenSubdiv version as a tuple of 3 numbers")}, + {(char *)("version_string"), (char *)("The OpenSubdiv version formatted as a string")}, + {NULL}, }; static PyStructSequence_Desc app_opensubdiv_info_desc = { - (char *)"bpy.app.opensubdiv", /* name */ - (char *)"This module contains information about OpenSubdiv blender is linked against", /* doc */ - app_opensubdiv_info_fields, /* fields */ - ARRAY_SIZE(app_opensubdiv_info_fields) - 1, + (char *)"bpy.app.opensubdiv", /* name */ + (char + *)"This module contains information about OpenSubdiv blender is linked against", /* doc */ + app_opensubdiv_info_fields, /* fields */ + ARRAY_SIZE(app_opensubdiv_info_fields) - 1, }; static PyObject *make_opensubdiv_info(void) { - PyObject *opensubdiv_info; - int pos = 0; + PyObject *opensubdiv_info; + int pos = 0; - opensubdiv_info = PyStructSequence_New(&BlenderAppOpenSubdivType); - if (opensubdiv_info == NULL) { - return NULL; - } + opensubdiv_info = PyStructSequence_New(&BlenderAppOpenSubdivType); + if (opensubdiv_info == NULL) { + return NULL; + } #ifndef WITH_OPENSUBDIV -#define SetStrItem(str) \ - PyStructSequence_SET_ITEM(opensubdiv_info, pos++, PyUnicode_FromString(str)) +# define SetStrItem(str) \ + PyStructSequence_SET_ITEM(opensubdiv_info, pos++, PyUnicode_FromString(str)) #endif -#define SetObjItem(obj) \ - PyStructSequence_SET_ITEM(opensubdiv_info, pos++, obj) +#define SetObjItem(obj) PyStructSequence_SET_ITEM(opensubdiv_info, pos++, obj) #ifdef WITH_OPENSUBDIV - int curversion = openSubdiv_getVersionHex(); - SetObjItem(PyBool_FromLong(1)); - SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100)); - SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", - curversion / 10000, (curversion / 100) % 100, curversion % 100)); + int curversion = openSubdiv_getVersionHex(); + SetObjItem(PyBool_FromLong(1)); + SetObjItem(PyC_Tuple_Pack_I32(curversion / 10000, (curversion / 100) % 100, curversion % 100)); + SetObjItem(PyUnicode_FromFormat( + "%2d, %2d, %2d", curversion / 10000, (curversion / 100) % 100, curversion % 100)); #else - SetObjItem(PyBool_FromLong(0)); - SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); - SetStrItem("Unknown"); + SetObjItem(PyBool_FromLong(0)); + SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); + SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(opensubdiv_info); - return NULL; - } + if (PyErr_Occurred()) { + Py_CLEAR(opensubdiv_info); + return NULL; + } #undef SetStrItem #undef SetObjItem - return opensubdiv_info; + return opensubdiv_info; } PyObject *BPY_app_opensubdiv_struct(void) { - PyObject *ret; + PyObject *ret; - PyStructSequence_InitType(&BlenderAppOpenSubdivType, &app_opensubdiv_info_desc); + PyStructSequence_InitType(&BlenderAppOpenSubdivType, &app_opensubdiv_info_desc); - ret = make_opensubdiv_info(); + ret = make_opensubdiv_info(); - /* prevent user from creating new instances */ - BlenderAppOpenSubdivType.tp_init = NULL; - BlenderAppOpenSubdivType.tp_new = NULL; - /* without this we can't do set(sys.modules) [#29635] */ - BlenderAppOpenSubdivType.tp_hash = (hashfunc)_Py_HashPointer; + /* prevent user from creating new instances */ + BlenderAppOpenSubdivType.tp_init = NULL; + BlenderAppOpenSubdivType.tp_new = NULL; + /* without this we can't do set(sys.modules) [#29635] */ + BlenderAppOpenSubdivType.tp_hash = (hashfunc)_Py_HashPointer; - return ret; + return ret; } diff --git a/source/blender/python/intern/bpy_app_opensubdiv.h b/source/blender/python/intern/bpy_app_opensubdiv.h index 6f349c66794..f04fa6fb44d 100644 --- a/source/blender/python/intern/bpy_app_opensubdiv.h +++ b/source/blender/python/intern/bpy_app_opensubdiv.h @@ -23,4 +23,4 @@ PyObject *BPY_app_opensubdiv_struct(void); -#endif /* __BPY_APP_OPENSUBDIV_H__ */ +#endif /* __BPY_APP_OPENSUBDIV_H__ */ diff --git a/source/blender/python/intern/bpy_app_openvdb.c b/source/blender/python/intern/bpy_app_openvdb.c index 049cfba8bba..a3d02294c07 100644 --- a/source/blender/python/intern/bpy_app_openvdb.c +++ b/source/blender/python/intern/bpy_app_openvdb.c @@ -35,76 +35,76 @@ static PyTypeObject BlenderAppOVDBType; static PyStructSequence_Field app_openvdb_info_fields[] = { - {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenVDB support")}, - {(char *)("version"), (char *)("The OpenVDB version as a tuple of 3 numbers")}, - {(char *)("version_string"), (char *)("The OpenVDB version formatted as a string")}, - {NULL}, + {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenVDB support")}, + {(char *)("version"), (char *)("The OpenVDB version as a tuple of 3 numbers")}, + {(char *)("version_string"), (char *)("The OpenVDB version formatted as a string")}, + {NULL}, }; static PyStructSequence_Desc app_openvdb_info_desc = { - (char *)"bpy.app.openvdb", /* name */ - (char *)"This module contains information about OpenVDB blender is linked against", /* doc */ - app_openvdb_info_fields, /* fields */ - ARRAY_SIZE(app_openvdb_info_fields) - 1, + (char *)"bpy.app.openvdb", /* name */ + (char *)"This module contains information about OpenVDB blender is linked against", /* doc */ + app_openvdb_info_fields, /* fields */ + ARRAY_SIZE(app_openvdb_info_fields) - 1, }; static PyObject *make_openvdb_info(void) { - PyObject *openvdb_info; - int pos = 0; + PyObject *openvdb_info; + int pos = 0; #ifdef WITH_OPENVDB - int curversion; + int curversion; #endif - openvdb_info = PyStructSequence_New(&BlenderAppOVDBType); - if (openvdb_info == NULL) { - return NULL; - } + openvdb_info = PyStructSequence_New(&BlenderAppOVDBType); + if (openvdb_info == NULL) { + return NULL; + } #ifndef WITH_OPENVDB -#define SetStrItem(str) \ - PyStructSequence_SET_ITEM(openvdb_info, pos++, PyUnicode_FromString(str)) +# define SetStrItem(str) PyStructSequence_SET_ITEM(openvdb_info, pos++, PyUnicode_FromString(str)) #endif -#define SetObjItem(obj) \ - PyStructSequence_SET_ITEM(openvdb_info, pos++, obj) +#define SetObjItem(obj) PyStructSequence_SET_ITEM(openvdb_info, pos++, obj) #ifdef WITH_OPENVDB - curversion = OpenVDB_getVersionHex(); - SetObjItem(PyBool_FromLong(1)); - SetObjItem(PyC_Tuple_Pack_I32(curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256)); - SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", - curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256)); + curversion = OpenVDB_getVersionHex(); + SetObjItem(PyBool_FromLong(1)); + SetObjItem( + PyC_Tuple_Pack_I32(curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256)); + SetObjItem(PyUnicode_FromFormat( + "%2d, %2d, %2d", curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256)); #else - SetObjItem(PyBool_FromLong(0)); - SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); - SetStrItem("Unknown"); + SetObjItem(PyBool_FromLong(0)); + SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); + SetStrItem("Unknown"); #endif - if (PyErr_Occurred()) { - Py_CLEAR(openvdb_info); - return NULL; - } + if (PyErr_Occurred()) { + Py_CLEAR(openvdb_info); + return NULL; + } #undef SetStrItem #undef SetObjItem - return openvdb_info; + return openvdb_info; } PyObject *BPY_app_openvdb_struct(void) { - PyObject *ret; + PyObject *ret; - PyStructSequence_InitType(&BlenderAppOVDBType, &app_openvdb_info_desc); + PyStructSequence_InitType(&BlenderAppOVDBType, &app_openvdb_info_desc); - ret = make_openvdb_info(); + ret = make_openvdb_info(); - /* prevent user from creating new instances */ - BlenderAppOVDBType.tp_init = NULL; - BlenderAppOVDBType.tp_new = NULL; - BlenderAppOVDBType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + /* prevent user from creating new instances */ + BlenderAppOVDBType.tp_init = NULL; + BlenderAppOVDBType.tp_new = NULL; + BlenderAppOVDBType.tp_hash = (hashfunc) + _Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ - return ret; + return ret; } diff --git a/source/blender/python/intern/bpy_app_openvdb.h b/source/blender/python/intern/bpy_app_openvdb.h index b002e5e04a6..333d79142f7 100644 --- a/source/blender/python/intern/bpy_app_openvdb.h +++ b/source/blender/python/intern/bpy_app_openvdb.h @@ -26,4 +26,4 @@ PyObject *BPY_app_openvdb_struct(void); -#endif /* __BPY_APP_OPENVDB_H__ */ +#endif /* __BPY_APP_OPENVDB_H__ */ diff --git a/source/blender/python/intern/bpy_app_sdl.c b/source/blender/python/intern/bpy_app_sdl.c index 09e13e4a116..7e3d02076f2 100644 --- a/source/blender/python/intern/bpy_app_sdl.c +++ b/source/blender/python/intern/bpy_app_sdl.c @@ -46,98 +46,98 @@ static PyTypeObject BlenderAppSDLType; static PyStructSequence_Field app_sdl_info_fields[] = { - {(char *)"supported", (char *)("Boolean, True when Blender is built with SDL support")}, - {(char *)"version", (char *)("The SDL version as a tuple of 3 numbers")}, - {(char *)"version_string", (char *)("The SDL version formatted as a string")}, - {(char *)"available", (char *)("Boolean, True when SDL is available. This is False when " - "either *supported* is False, or *dynload* is True and " - "Blender cannot find the correct library.")}, - {NULL}, + {(char *)"supported", (char *)("Boolean, True when Blender is built with SDL support")}, + {(char *)"version", (char *)("The SDL version as a tuple of 3 numbers")}, + {(char *)"version_string", (char *)("The SDL version formatted as a string")}, + {(char *)"available", + (char *)("Boolean, True when SDL is available. This is False when " + "either *supported* is False, or *dynload* is True and " + "Blender cannot find the correct library.")}, + {NULL}, }; static PyStructSequence_Desc app_sdl_info_desc = { - (char *)"bpy.app.sdl", /* name */ - (char *)"This module contains information about SDL blender is linked against", /* doc */ - app_sdl_info_fields, /* fields */ - ARRAY_SIZE(app_sdl_info_fields) - 1, + (char *)"bpy.app.sdl", /* name */ + (char *)"This module contains information about SDL blender is linked against", /* doc */ + app_sdl_info_fields, /* fields */ + ARRAY_SIZE(app_sdl_info_fields) - 1, }; static PyObject *make_sdl_info(void) { - PyObject *sdl_info; - int pos = 0; + PyObject *sdl_info; + int pos = 0; #ifdef WITH_SDL - bool sdl_available = false; - SDL_version version = {0, 0, 0}; + bool sdl_available = false; + SDL_version version = {0, 0, 0}; #endif - sdl_info = PyStructSequence_New(&BlenderAppSDLType); - if (sdl_info == NULL) { - return NULL; - } + sdl_info = PyStructSequence_New(&BlenderAppSDLType); + if (sdl_info == NULL) { + return NULL; + } -#define SetStrItem(str) \ - PyStructSequence_SET_ITEM(sdl_info, pos++, PyUnicode_FromString(str)) +#define SetStrItem(str) PyStructSequence_SET_ITEM(sdl_info, pos++, PyUnicode_FromString(str)) -#define SetObjItem(obj) \ - PyStructSequence_SET_ITEM(sdl_info, pos++, obj) +#define SetObjItem(obj) PyStructSequence_SET_ITEM(sdl_info, pos++, obj) #ifdef WITH_SDL - SetObjItem(PyBool_FromLong(1)); - -# ifdef WITH_SDL_DYNLOAD - if (sdlewInit() == SDLEW_SUCCESS) { - SDL_GetVersion(&version); - sdl_available = true; - } -# else // WITH_SDL_DYNLOAD=OFF - sdl_available = true; -# if SDL_MAJOR_VERSION >= 2 - SDL_GetVersion(&version); -# else - SDL_VERSION(&version); + SetObjItem(PyBool_FromLong(1)); + +# ifdef WITH_SDL_DYNLOAD + if (sdlewInit() == SDLEW_SUCCESS) { + SDL_GetVersion(&version); + sdl_available = true; + } +# else // WITH_SDL_DYNLOAD=OFF + sdl_available = true; +# if SDL_MAJOR_VERSION >= 2 + SDL_GetVersion(&version); +# else + SDL_VERSION(&version); +# endif # endif -# endif - - SetObjItem(PyC_Tuple_Pack_I32(version.major, version.minor, version.patch)); - if (sdl_available) { - SetObjItem(PyUnicode_FromFormat("%d.%d.%d", version.major, version.minor, version.patch)); - } - else { - SetStrItem("Unknown"); - } - SetObjItem(PyBool_FromLong(sdl_available)); - -#else // WITH_SDL=OFF - SetObjItem(PyBool_FromLong(0)); - SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); - SetStrItem("Unknown"); - SetObjItem(PyBool_FromLong(0)); + + SetObjItem(PyC_Tuple_Pack_I32(version.major, version.minor, version.patch)); + if (sdl_available) { + SetObjItem(PyUnicode_FromFormat("%d.%d.%d", version.major, version.minor, version.patch)); + } + else { + SetStrItem("Unknown"); + } + SetObjItem(PyBool_FromLong(sdl_available)); + +#else // WITH_SDL=OFF + SetObjItem(PyBool_FromLong(0)); + SetObjItem(PyC_Tuple_Pack_I32(0, 0, 0)); + SetStrItem("Unknown"); + SetObjItem(PyBool_FromLong(0)); #endif - if (PyErr_Occurred()) { - Py_CLEAR(sdl_info); - return NULL; - } + if (PyErr_Occurred()) { + Py_CLEAR(sdl_info); + return NULL; + } #undef SetStrItem #undef SetObjItem - return sdl_info; + return sdl_info; } PyObject *BPY_app_sdl_struct(void) { - PyObject *ret; + PyObject *ret; - PyStructSequence_InitType(&BlenderAppSDLType, &app_sdl_info_desc); + PyStructSequence_InitType(&BlenderAppSDLType, &app_sdl_info_desc); - ret = make_sdl_info(); + ret = make_sdl_info(); - /* prevent user from creating new instances */ - BlenderAppSDLType.tp_init = NULL; - BlenderAppSDLType.tp_new = NULL; - BlenderAppSDLType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + /* prevent user from creating new instances */ + BlenderAppSDLType.tp_init = NULL; + BlenderAppSDLType.tp_new = NULL; + BlenderAppSDLType.tp_hash = (hashfunc) + _Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ - return ret; + return ret; } diff --git a/source/blender/python/intern/bpy_app_sdl.h b/source/blender/python/intern/bpy_app_sdl.h index 7df0dd4b686..453c1c0c1a3 100644 --- a/source/blender/python/intern/bpy_app_sdl.h +++ b/source/blender/python/intern/bpy_app_sdl.h @@ -23,4 +23,4 @@ PyObject *BPY_app_sdl_struct(void); -#endif /* __BPY_APP_SDL_H__ */ +#endif /* __BPY_APP_SDL_H__ */ diff --git a/source/blender/python/intern/bpy_app_timers.c b/source/blender/python/intern/bpy_app_timers.c index 38a785d0d82..c3c56e4fb66 100644 --- a/source/blender/python/intern/bpy_app_timers.c +++ b/source/blender/python/intern/bpy_app_timers.c @@ -29,167 +29,161 @@ #include "../generic/py_capi_utils.h" #include "../generic/python_utildefines.h" - static double handle_returned_value(PyObject *function, PyObject *ret) { - if (ret == NULL) { - PyErr_PrintEx(0); - PyErr_Clear(); - return -1; - } - - if (ret == Py_None) { - return -1; - } - - double value = PyFloat_AsDouble(ret); - if (value == -1.0f && PyErr_Occurred()) { - PyErr_Clear(); - printf("Error: 'bpy.app.timers' callback "); - PyObject_Print(function, stdout, Py_PRINT_RAW); - printf(" did not return None or float.\n"); - return -1; - } - - if (value < 0.0) { - value = 0.0; - } - - return value; + if (ret == NULL) { + PyErr_PrintEx(0); + PyErr_Clear(); + return -1; + } + + if (ret == Py_None) { + return -1; + } + + double value = PyFloat_AsDouble(ret); + if (value == -1.0f && PyErr_Occurred()) { + PyErr_Clear(); + printf("Error: 'bpy.app.timers' callback "); + PyObject_Print(function, stdout, Py_PRINT_RAW); + printf(" did not return None or float.\n"); + return -1; + } + + if (value < 0.0) { + value = 0.0; + } + + return value; } static double py_timer_execute(uintptr_t UNUSED(uuid), void *user_data) { - PyObject *function = user_data; + PyObject *function = user_data; - PyGILState_STATE gilstate; - gilstate = PyGILState_Ensure(); + PyGILState_STATE gilstate; + gilstate = PyGILState_Ensure(); - PyObject *py_ret = PyObject_CallObject(function, NULL); - double ret = handle_returned_value(function, py_ret); + PyObject *py_ret = PyObject_CallObject(function, NULL); + double ret = handle_returned_value(function, py_ret); - PyGILState_Release(gilstate); + PyGILState_Release(gilstate); - return ret; + return ret; } static void py_timer_free(uintptr_t UNUSED(uuid), void *user_data) { - PyObject *function = user_data; + PyObject *function = user_data; - PyGILState_STATE gilstate; - gilstate = PyGILState_Ensure(); + PyGILState_STATE gilstate; + gilstate = PyGILState_Ensure(); - Py_DECREF(function); + Py_DECREF(function); - PyGILState_Release(gilstate); + PyGILState_Release(gilstate); } - -PyDoc_STRVAR(bpy_app_timers_register_doc, -".. function:: register(function, first_interval=0, persistent=False)\n" -"\n" -" Add a new function that will be called after the specified amount of seconds.\n" -" The function gets no arguments and is expected to return either None or a float.\n" -" If ``None`` is returned, the timer will be unregistered.\n" -" A returned number specifies the delay until the function is called again.\n" -" ``functools.partial`` can be used to assign some parameters.\n" -"\n" -" :arg function: The function that should called.\n" -" :type function: Callable[[], Union[float, None]]\n" -" :arg first_interval: Seconds until the callback should be called the first time.\n" -" :type first_interval: float\n" -" :arg persistent: Don't remove timer when a new file is loaded.\n" -" :type persistent: bool\n" -); +PyDoc_STRVAR( + bpy_app_timers_register_doc, + ".. function:: register(function, first_interval=0, persistent=False)\n" + "\n" + " Add a new function that will be called after the specified amount of seconds.\n" + " The function gets no arguments and is expected to return either None or a float.\n" + " If ``None`` is returned, the timer will be unregistered.\n" + " A returned number specifies the delay until the function is called again.\n" + " ``functools.partial`` can be used to assign some parameters.\n" + "\n" + " :arg function: The function that should called.\n" + " :type function: Callable[[], Union[float, None]]\n" + " :arg first_interval: Seconds until the callback should be called the first time.\n" + " :type first_interval: float\n" + " :arg persistent: Don't remove timer when a new file is loaded.\n" + " :type persistent: bool\n"); static PyObject *bpy_app_timers_register(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - PyObject *function; - double first_interval = 0; - int persistent = false; - - static const char *_keywords[] = {"function", "first_interval", "persistent", NULL}; - static _PyArg_Parser _parser = {"O|$dp:register", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &function, &first_interval, &persistent)) - { - return NULL; - } - - if (!PyCallable_Check(function)) { - PyErr_SetString(PyExc_TypeError, "function is not callable"); - return NULL; - } - - Py_INCREF(function); - BLI_timer_register( - (intptr_t)function, - py_timer_execute, function, py_timer_free, - first_interval, persistent); - Py_RETURN_NONE; + PyObject *function; + double first_interval = 0; + int persistent = false; + + static const char *_keywords[] = {"function", "first_interval", "persistent", NULL}; + static _PyArg_Parser _parser = {"O|$dp:register", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast( + args, kw, &_parser, &function, &first_interval, &persistent)) { + return NULL; + } + + if (!PyCallable_Check(function)) { + PyErr_SetString(PyExc_TypeError, "function is not callable"); + return NULL; + } + + Py_INCREF(function); + BLI_timer_register( + (intptr_t)function, py_timer_execute, function, py_timer_free, first_interval, persistent); + Py_RETURN_NONE; } PyDoc_STRVAR(bpy_app_timers_unregister_doc, -".. function:: unregister(function)\n" -"\n" -" Unregister timer.\n" -"\n" -" :arg function: Function to unregister.\n" -" :type function: function\n" -); + ".. function:: unregister(function)\n" + "\n" + " Unregister timer.\n" + "\n" + " :arg function: Function to unregister.\n" + " :type function: function\n"); static PyObject *bpy_app_timers_unregister(PyObject *UNUSED(self), PyObject *function) { - if (!BLI_timer_unregister((intptr_t)function)) { - PyErr_SetString(PyExc_ValueError, "Error: function is not registered"); - return NULL; - } - Py_RETURN_NONE; + if (!BLI_timer_unregister((intptr_t)function)) { + PyErr_SetString(PyExc_ValueError, "Error: function is not registered"); + return NULL; + } + Py_RETURN_NONE; } PyDoc_STRVAR(bpy_app_timers_is_registered_doc, -".. function:: is_registered(function)\n" -"\n" -" Check if this function is registered as a timer.\n" -"\n" -" :arg function: Function to check.\n" -" :type function: int\n" -" :return: True when this function is registered, otherwise False.\n" -" :rtype: bool\n" -); + ".. function:: is_registered(function)\n" + "\n" + " Check if this function is registered as a timer.\n" + "\n" + " :arg function: Function to check.\n" + " :type function: int\n" + " :return: True when this function is registered, otherwise False.\n" + " :rtype: bool\n"); static PyObject *bpy_app_timers_is_registered(PyObject *UNUSED(self), PyObject *function) { - bool ret = BLI_timer_is_registered((intptr_t)function); - return PyBool_FromLong(ret); + bool ret = BLI_timer_is_registered((intptr_t)function); + return PyBool_FromLong(ret); } - static struct PyMethodDef M_AppTimers_methods[] = { - {"register", (PyCFunction)bpy_app_timers_register, - METH_VARARGS | METH_KEYWORDS, bpy_app_timers_register_doc}, - {"unregister", (PyCFunction)bpy_app_timers_unregister, - METH_O, bpy_app_timers_unregister_doc}, - {"is_registered", (PyCFunction)bpy_app_timers_is_registered, - METH_O, bpy_app_timers_is_registered_doc}, - {NULL, NULL, 0, NULL}, + {"register", + (PyCFunction)bpy_app_timers_register, + METH_VARARGS | METH_KEYWORDS, + bpy_app_timers_register_doc}, + {"unregister", (PyCFunction)bpy_app_timers_unregister, METH_O, bpy_app_timers_unregister_doc}, + {"is_registered", + (PyCFunction)bpy_app_timers_is_registered, + METH_O, + bpy_app_timers_is_registered_doc}, + {NULL, NULL, 0, NULL}, }; static struct PyModuleDef M_AppTimers_module_def = { - PyModuleDef_HEAD_INIT, - "bpy.app.timers", /* m_name */ - NULL, /* m_doc */ - 0, /* m_size */ - M_AppTimers_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + PyModuleDef_HEAD_INIT, + "bpy.app.timers", /* m_name */ + NULL, /* m_doc */ + 0, /* m_size */ + M_AppTimers_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; PyObject *BPY_app_timers_module(void) { - PyObject *sys_modules = PyImport_GetModuleDict(); - PyObject *mod = PyModule_Create(&M_AppTimers_module_def); - PyDict_SetItem(sys_modules, PyModule_GetNameObject(mod), mod); - return mod; + PyObject *sys_modules = PyImport_GetModuleDict(); + PyObject *mod = PyModule_Create(&M_AppTimers_module_def); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(mod), mod); + return mod; } diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index f571caee8ec..56de6dd1405 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -46,15 +46,15 @@ #endif typedef struct { - PyObject_HEAD - /* The string used to separate context from actual message in PY_TRANSLATE RNA props. */ - const char *context_separator; - /* A "named tuple" (StructSequence actually...) containing all C-defined contexts. */ - PyObject *contexts; - /* A readonly mapping {C context id: python id} (actually, a MappingProxy). */ - PyObject *contexts_C_to_py; - /* A py dict containing all registered py dicts (order is more or less random, first match wins!). */ - PyObject *py_messages; + PyObject_HEAD + /* The string used to separate context from actual message in PY_TRANSLATE RNA props. */ + const char *context_separator; + /* A "named tuple" (StructSequence actually...) containing all C-defined contexts. */ + PyObject *contexts; + /* A readonly mapping {C context id: python id} (actually, a MappingProxy). */ + PyObject *contexts_C_to_py; + /* A py dict containing all registered py dicts (order is more or less random, first match wins!). */ + PyObject *py_messages; } BlenderAppTranslations; /* Our singleton instance pointer */ @@ -64,48 +64,49 @@ static BlenderAppTranslations *_translations = NULL; /***** Helpers for ghash *****/ typedef struct GHashKey { - const char *msgctxt; - const char *msgid; + const char *msgctxt; + const char *msgid; } GHashKey; static GHashKey *_ghashutil_keyalloc(const void *msgctxt, const void *msgid) { - GHashKey *key = MEM_mallocN(sizeof(GHashKey), "Py i18n GHashKey"); - key->msgctxt = BLI_strdup(BLT_is_default_context(msgctxt) ? BLT_I18NCONTEXT_DEFAULT_BPYRNA : msgctxt); - key->msgid = BLI_strdup(msgid); - return key; + GHashKey *key = MEM_mallocN(sizeof(GHashKey), "Py i18n GHashKey"); + key->msgctxt = BLI_strdup(BLT_is_default_context(msgctxt) ? BLT_I18NCONTEXT_DEFAULT_BPYRNA : + msgctxt); + key->msgid = BLI_strdup(msgid); + return key; } static unsigned int _ghashutil_keyhash(const void *ptr) { - const GHashKey *key = ptr; - unsigned int hash = BLI_ghashutil_strhash(key->msgctxt); - return hash ^ BLI_ghashutil_strhash(key->msgid); + const GHashKey *key = ptr; + unsigned int hash = BLI_ghashutil_strhash(key->msgctxt); + return hash ^ BLI_ghashutil_strhash(key->msgid); } static bool _ghashutil_keycmp(const void *a, const void *b) { - const GHashKey *A = a; - const GHashKey *B = b; - - /* Note: comparing msgid first, most of the time it will be enough! */ - if (BLI_ghashutil_strcmp(A->msgid, B->msgid) == false) { - return BLI_ghashutil_strcmp(A->msgctxt, B->msgctxt); - } - return true; /* true means they are not equal! */ + const GHashKey *A = a; + const GHashKey *B = b; + + /* Note: comparing msgid first, most of the time it will be enough! */ + if (BLI_ghashutil_strcmp(A->msgid, B->msgid) == false) { + return BLI_ghashutil_strcmp(A->msgctxt, B->msgctxt); + } + return true; /* true means they are not equal! */ } static void _ghashutil_keyfree(void *ptr) { - const GHashKey *key = ptr; + const GHashKey *key = ptr; - /* We assume both msgctxt and msgid were BLI_strdup'ed! */ - MEM_freeN((void *)key->msgctxt); - MEM_freeN((void *)key->msgid); - MEM_freeN((void *)key); + /* We assume both msgctxt and msgid were BLI_strdup'ed! */ + MEM_freeN((void *)key->msgctxt); + MEM_freeN((void *)key->msgid); + MEM_freeN((void *)key); } -#define _ghashutil_valfree MEM_freeN +# define _ghashutil_valfree MEM_freeN /***** Python's messages cache *****/ @@ -118,255 +119,270 @@ static GHash *_translations_cache = NULL; static void _clear_translations_cache(void) { - if (_translations_cache) { - BLI_ghash_free(_translations_cache, _ghashutil_keyfree, _ghashutil_valfree); - } - _translations_cache = NULL; + if (_translations_cache) { + BLI_ghash_free(_translations_cache, _ghashutil_keyfree, _ghashutil_valfree); + } + _translations_cache = NULL; } static void _build_translations_cache(PyObject *py_messages, const char *locale) { - PyObject *uuid, *uuid_dict; - Py_ssize_t pos = 0; - char *language = NULL, *language_country = NULL, *language_variant = NULL; - - /* For each py dict, we'll search for full locale, then language+country, then language+variant, - * then only language keys... */ - BLT_lang_locale_explode(locale, &language, NULL, NULL, &language_country, &language_variant); - - /* Clear the cached ghash if needed, and create a new one. */ - _clear_translations_cache(); - _translations_cache = BLI_ghash_new(_ghashutil_keyhash, _ghashutil_keycmp, __func__); - - /* Iterate over all py dicts. */ - while (PyDict_Next(py_messages, &pos, &uuid, &uuid_dict)) { - PyObject *lang_dict; - -#if 0 - PyObject_Print(uuid_dict, stdout, 0); - printf("\n"); -#endif - - /* Try to get first complete locale, then language+country, then language+variant, then only language */ - lang_dict = PyDict_GetItemString(uuid_dict, locale); - if (!lang_dict && language_country) { - lang_dict = PyDict_GetItemString(uuid_dict, language_country); - locale = language_country; - } - if (!lang_dict && language_variant) { - lang_dict = PyDict_GetItemString(uuid_dict, language_variant); - locale = language_variant; - } - if (!lang_dict && language) { - lang_dict = PyDict_GetItemString(uuid_dict, language); - locale = language; - } - - if (lang_dict) { - PyObject *pykey, *trans; - Py_ssize_t ppos = 0; - - if (!PyDict_Check(lang_dict)) { - printf("WARNING! In translations' dict of \""); - PyObject_Print(uuid, stdout, Py_PRINT_RAW); - printf("\":\n"); - printf(" Each language key must have a dictionary as value, \"%s\" is not valid, skipping: ", - locale); - PyObject_Print(lang_dict, stdout, Py_PRINT_RAW); - printf("\n"); - continue; - } - - /* Iterate over all translations of the found language dict, and populate our ghash cache. */ - while (PyDict_Next(lang_dict, &ppos, &pykey, &trans)) { - const char *msgctxt = NULL, *msgid = NULL; - bool invalid_key = false; - - if ((PyTuple_CheckExact(pykey) == false) || (PyTuple_GET_SIZE(pykey) != 2)) { - invalid_key = true; - } - else { - PyObject *tmp = PyTuple_GET_ITEM(pykey, 0); - if (tmp == Py_None) { - msgctxt = BLT_I18NCONTEXT_DEFAULT_BPYRNA; - } - else if (PyUnicode_Check(tmp)) { - msgctxt = _PyUnicode_AsString(tmp); - } - else { - invalid_key = true; - } - - tmp = PyTuple_GET_ITEM(pykey, 1); - if (PyUnicode_Check(tmp)) { - msgid = _PyUnicode_AsString(tmp); - } - else { - invalid_key = true; - } - } - - if (invalid_key) { - printf("WARNING! In translations' dict of \""); - PyObject_Print(uuid, stdout, Py_PRINT_RAW); - printf("\", %s language:\n", locale); - printf(" Keys must be tuples of (msgctxt [string or None], msgid [string]), " - "this one is not valid, skipping: "); - PyObject_Print(pykey, stdout, Py_PRINT_RAW); - printf("\n"); - continue; - } - if (PyUnicode_Check(trans) == false) { - printf("WARNING! In translations' dict of \""); - PyObject_Print(uuid, stdout, Py_PRINT_RAW); - printf("\":\n"); - printf(" Values must be strings, this one is not valid, skipping: "); - PyObject_Print(trans, stdout, Py_PRINT_RAW); - printf("\n"); - continue; - } - - /* Do not overwrite existing keys! */ - if (BPY_app_translations_py_pgettext(msgctxt, msgid) == msgid) { - GHashKey *key = _ghashutil_keyalloc(msgctxt, msgid); - BLI_ghash_insert(_translations_cache, key, BLI_strdup(_PyUnicode_AsString(trans))); - } - } - } - } - - /* Clean up! */ - MEM_SAFE_FREE(language); - MEM_SAFE_FREE(language_country); - MEM_SAFE_FREE(language_variant); + PyObject *uuid, *uuid_dict; + Py_ssize_t pos = 0; + char *language = NULL, *language_country = NULL, *language_variant = NULL; + + /* For each py dict, we'll search for full locale, then language+country, then language+variant, + * then only language keys... */ + BLT_lang_locale_explode(locale, &language, NULL, NULL, &language_country, &language_variant); + + /* Clear the cached ghash if needed, and create a new one. */ + _clear_translations_cache(); + _translations_cache = BLI_ghash_new(_ghashutil_keyhash, _ghashutil_keycmp, __func__); + + /* Iterate over all py dicts. */ + while (PyDict_Next(py_messages, &pos, &uuid, &uuid_dict)) { + PyObject *lang_dict; + +# if 0 + PyObject_Print(uuid_dict, stdout, 0); + printf("\n"); +# endif + + /* Try to get first complete locale, then language+country, then language+variant, then only language */ + lang_dict = PyDict_GetItemString(uuid_dict, locale); + if (!lang_dict && language_country) { + lang_dict = PyDict_GetItemString(uuid_dict, language_country); + locale = language_country; + } + if (!lang_dict && language_variant) { + lang_dict = PyDict_GetItemString(uuid_dict, language_variant); + locale = language_variant; + } + if (!lang_dict && language) { + lang_dict = PyDict_GetItemString(uuid_dict, language); + locale = language; + } + + if (lang_dict) { + PyObject *pykey, *trans; + Py_ssize_t ppos = 0; + + if (!PyDict_Check(lang_dict)) { + printf("WARNING! In translations' dict of \""); + PyObject_Print(uuid, stdout, Py_PRINT_RAW); + printf("\":\n"); + printf( + " Each language key must have a dictionary as value, \"%s\" is not valid, " + "skipping: ", + locale); + PyObject_Print(lang_dict, stdout, Py_PRINT_RAW); + printf("\n"); + continue; + } + + /* Iterate over all translations of the found language dict, and populate our ghash cache. */ + while (PyDict_Next(lang_dict, &ppos, &pykey, &trans)) { + const char *msgctxt = NULL, *msgid = NULL; + bool invalid_key = false; + + if ((PyTuple_CheckExact(pykey) == false) || (PyTuple_GET_SIZE(pykey) != 2)) { + invalid_key = true; + } + else { + PyObject *tmp = PyTuple_GET_ITEM(pykey, 0); + if (tmp == Py_None) { + msgctxt = BLT_I18NCONTEXT_DEFAULT_BPYRNA; + } + else if (PyUnicode_Check(tmp)) { + msgctxt = _PyUnicode_AsString(tmp); + } + else { + invalid_key = true; + } + + tmp = PyTuple_GET_ITEM(pykey, 1); + if (PyUnicode_Check(tmp)) { + msgid = _PyUnicode_AsString(tmp); + } + else { + invalid_key = true; + } + } + + if (invalid_key) { + printf("WARNING! In translations' dict of \""); + PyObject_Print(uuid, stdout, Py_PRINT_RAW); + printf("\", %s language:\n", locale); + printf( + " Keys must be tuples of (msgctxt [string or None], msgid [string]), " + "this one is not valid, skipping: "); + PyObject_Print(pykey, stdout, Py_PRINT_RAW); + printf("\n"); + continue; + } + if (PyUnicode_Check(trans) == false) { + printf("WARNING! In translations' dict of \""); + PyObject_Print(uuid, stdout, Py_PRINT_RAW); + printf("\":\n"); + printf(" Values must be strings, this one is not valid, skipping: "); + PyObject_Print(trans, stdout, Py_PRINT_RAW); + printf("\n"); + continue; + } + + /* Do not overwrite existing keys! */ + if (BPY_app_translations_py_pgettext(msgctxt, msgid) == msgid) { + GHashKey *key = _ghashutil_keyalloc(msgctxt, msgid); + BLI_ghash_insert(_translations_cache, key, BLI_strdup(_PyUnicode_AsString(trans))); + } + } + } + } + + /* Clean up! */ + MEM_SAFE_FREE(language); + MEM_SAFE_FREE(language_country); + MEM_SAFE_FREE(language_variant); } const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) { -#define STATIC_LOCALE_SIZE 32 /* Should be more than enough! */ +# define STATIC_LOCALE_SIZE 32 /* Should be more than enough! */ - GHashKey key; - static char locale[STATIC_LOCALE_SIZE] = ""; - const char *tmp; + GHashKey key; + static char locale[STATIC_LOCALE_SIZE] = ""; + const char *tmp; - /* Just in case, should never happen! */ - if (!_translations) { - return msgid; - } + /* Just in case, should never happen! */ + if (!_translations) { + return msgid; + } - tmp = BLT_lang_get(); - if (!STREQ(tmp, locale) || !_translations_cache) { - PyGILState_STATE _py_state; + tmp = BLT_lang_get(); + if (!STREQ(tmp, locale) || !_translations_cache) { + PyGILState_STATE _py_state; - BLI_strncpy(locale, tmp, STATIC_LOCALE_SIZE); + BLI_strncpy(locale, tmp, STATIC_LOCALE_SIZE); - /* Locale changed or cache does not exist, refresh the whole cache! */ - /* This func may be called from C (i.e. outside of python interpreter 'context'). */ - _py_state = PyGILState_Ensure(); + /* Locale changed or cache does not exist, refresh the whole cache! */ + /* This func may be called from C (i.e. outside of python interpreter 'context'). */ + _py_state = PyGILState_Ensure(); - _build_translations_cache(_translations->py_messages, locale); + _build_translations_cache(_translations->py_messages, locale); - PyGILState_Release(_py_state); - } + PyGILState_Release(_py_state); + } - /* And now, simply create the key (context, messageid) and find it in the cached dict! */ - key.msgctxt = BLT_is_default_context(msgctxt) ? BLT_I18NCONTEXT_DEFAULT_BPYRNA : msgctxt; - key.msgid = msgid; + /* And now, simply create the key (context, messageid) and find it in the cached dict! */ + key.msgctxt = BLT_is_default_context(msgctxt) ? BLT_I18NCONTEXT_DEFAULT_BPYRNA : msgctxt; + key.msgid = msgid; - tmp = BLI_ghash_lookup(_translations_cache, &key); + tmp = BLI_ghash_lookup(_translations_cache, &key); - return tmp ? tmp : msgid; + return tmp ? tmp : msgid; -#undef STATIC_LOCALE_SIZE +# undef STATIC_LOCALE_SIZE } -#endif /* WITH_INTERNATIONAL */ +#endif /* WITH_INTERNATIONAL */ PyDoc_STRVAR(app_translations_py_messages_register_doc, -".. method:: register(module_name, translations_dict)\n" -"\n" -" Registers an addon's UI translations.\n" -"\n" -" .. note::\n" -" Does nothing when Blender is built without internationalization support.\n" -"\n" -" :arg module_name: The name identifying the addon.\n" -" :type module_name: string\n" -" :arg translations_dict: A dictionary built like that:\n" -" ``{locale: {msg_key: msg_translation, ...}, ...}``\n" -" :type translations_dict: dict\n" -"\n" -); -static PyObject *app_translations_py_messages_register(BlenderAppTranslations *self, PyObject *args, PyObject *kw) + ".. method:: register(module_name, translations_dict)\n" + "\n" + " Registers an addon's UI translations.\n" + "\n" + " .. note::\n" + " Does nothing when Blender is built without internationalization support.\n" + "\n" + " :arg module_name: The name identifying the addon.\n" + " :type module_name: string\n" + " :arg translations_dict: A dictionary built like that:\n" + " ``{locale: {msg_key: msg_translation, ...}, ...}``\n" + " :type translations_dict: dict\n" + "\n"); +static PyObject *app_translations_py_messages_register(BlenderAppTranslations *self, + PyObject *args, + PyObject *kw) { #ifdef WITH_INTERNATIONAL - static const char *kwlist[] = {"module_name", "translations_dict", NULL}; - PyObject *module_name, *uuid_dict; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!:bpy.app.translations.register", (char **)kwlist, &PyUnicode_Type, - &module_name, &PyDict_Type, &uuid_dict)) - { - return NULL; - } - - if (PyDict_Contains(self->py_messages, module_name)) { - PyErr_Format(PyExc_ValueError, - "bpy.app.translations.register: translations message cache already contains some data for " - "addon '%s'", (const char *)_PyUnicode_AsString(module_name)); - return NULL; - } - - PyDict_SetItem(self->py_messages, module_name, uuid_dict); - - /* Clear cached messages dict! */ - _clear_translations_cache(); + static const char *kwlist[] = {"module_name", "translations_dict", NULL}; + PyObject *module_name, *uuid_dict; + + if (!PyArg_ParseTupleAndKeywords(args, + kw, + "O!O!:bpy.app.translations.register", + (char **)kwlist, + &PyUnicode_Type, + &module_name, + &PyDict_Type, + &uuid_dict)) { + return NULL; + } + + if (PyDict_Contains(self->py_messages, module_name)) { + PyErr_Format( + PyExc_ValueError, + "bpy.app.translations.register: translations message cache already contains some data for " + "addon '%s'", + (const char *)_PyUnicode_AsString(module_name)); + return NULL; + } + + PyDict_SetItem(self->py_messages, module_name, uuid_dict); + + /* Clear cached messages dict! */ + _clear_translations_cache(); #else - (void)self; - (void)args; - (void)kw; + (void)self; + (void)args; + (void)kw; #endif - /* And we are done! */ - Py_RETURN_NONE; + /* And we are done! */ + Py_RETURN_NONE; } PyDoc_STRVAR(app_translations_py_messages_unregister_doc, -".. method:: unregister(module_name)\n" -"\n" -" Unregisters an addon's UI translations.\n" -"\n" -" .. note::\n" -" Does nothing when Blender is built without internationalization support.\n" -"\n" -" :arg module_name: The name identifying the addon.\n" -" :type module_name: string\n" -"\n" -); -static PyObject *app_translations_py_messages_unregister(BlenderAppTranslations *self, PyObject *args, PyObject *kw) + ".. method:: unregister(module_name)\n" + "\n" + " Unregisters an addon's UI translations.\n" + "\n" + " .. note::\n" + " Does nothing when Blender is built without internationalization support.\n" + "\n" + " :arg module_name: The name identifying the addon.\n" + " :type module_name: string\n" + "\n"); +static PyObject *app_translations_py_messages_unregister(BlenderAppTranslations *self, + PyObject *args, + PyObject *kw) { #ifdef WITH_INTERNATIONAL - static const char *kwlist[] = {"module_name", NULL}; - PyObject *module_name; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "O!:bpy.app.translations.unregister", (char **)kwlist, &PyUnicode_Type, - &module_name)) - { - return NULL; - } - - if (PyDict_Contains(self->py_messages, module_name)) { - PyDict_DelItem(self->py_messages, module_name); - /* Clear cached messages ghash! */ - _clear_translations_cache(); - } + static const char *kwlist[] = {"module_name", NULL}; + PyObject *module_name; + + if (!PyArg_ParseTupleAndKeywords(args, + kw, + "O!:bpy.app.translations.unregister", + (char **)kwlist, + &PyUnicode_Type, + &module_name)) { + return NULL; + } + + if (PyDict_Contains(self->py_messages, module_name)) { + PyDict_DelItem(self->py_messages, module_name); + /* Clear cached messages ghash! */ + _clear_translations_cache(); + } #else - (void)self; - (void)args; - (void)kw; + (void)self; + (void)args; + (void)kw; #endif - /* And we are done! */ - Py_RETURN_NONE; + /* And we are done! */ + Py_RETURN_NONE; } /***** C-defined contexts *****/ @@ -379,450 +395,499 @@ static BLT_i18n_contexts_descriptor _contexts[] = BLT_I18NCONTEXTS_DESC; /* These fields are just empty placeholders, actual values get set in app_translations_struct(). * This allows us to avoid many handwriting, and above all, to keep all context definition stuff in BLT_translation.h! */ -static PyStructSequence_Field -app_translations_contexts_fields[ARRAY_SIZE(_contexts)] = {{NULL}}; +static PyStructSequence_Field app_translations_contexts_fields[ARRAY_SIZE(_contexts)] = {{NULL}}; static PyStructSequence_Desc app_translations_contexts_desc = { - (char *)"bpy.app.translations.contexts", /* name */ - (char *)"This named tuple contains all pre-defined translation contexts", /* doc */ - app_translations_contexts_fields, /* fields */ - ARRAY_SIZE(app_translations_contexts_fields) - 1, + (char *)"bpy.app.translations.contexts", /* name */ + (char *)"This named tuple contains all pre-defined translation contexts", /* doc */ + app_translations_contexts_fields, /* fields */ + ARRAY_SIZE(app_translations_contexts_fields) - 1, }; static PyObject *app_translations_contexts_make(void) { - PyObject *translations_contexts; - BLT_i18n_contexts_descriptor *ctxt; - int pos = 0; - - translations_contexts = PyStructSequence_New(&BlenderAppTranslationsContextsType); - if (translations_contexts == NULL) { - return NULL; - } - -#define SetObjString(item) PyStructSequence_SET_ITEM(translations_contexts, pos++, PyUnicode_FromString((item))) -#define SetObjNone() PyStructSequence_SET_ITEM(translations_contexts, pos++, Py_INCREF_RET(Py_None)) - - for (ctxt = _contexts; ctxt->c_id; ctxt++) { - if (ctxt->value) { - SetObjString(ctxt->value); - } - else { - SetObjNone(); - } - } + PyObject *translations_contexts; + BLT_i18n_contexts_descriptor *ctxt; + int pos = 0; + + translations_contexts = PyStructSequence_New(&BlenderAppTranslationsContextsType); + if (translations_contexts == NULL) { + return NULL; + } + +#define SetObjString(item) \ + PyStructSequence_SET_ITEM(translations_contexts, pos++, PyUnicode_FromString((item))) +#define SetObjNone() \ + PyStructSequence_SET_ITEM(translations_contexts, pos++, Py_INCREF_RET(Py_None)) + + for (ctxt = _contexts; ctxt->c_id; ctxt++) { + if (ctxt->value) { + SetObjString(ctxt->value); + } + else { + SetObjNone(); + } + } #undef SetObjString #undef SetObjNone - return translations_contexts; + return translations_contexts; } /***** Main BlenderAppTranslations Py object definition *****/ PyDoc_STRVAR(app_translations_contexts_doc, -"A named tuple containing all pre-defined translation contexts.\n" -"\n" -".. warning::\n" -" Never use a (new) context starting with \"" BLT_I18NCONTEXT_DEFAULT_BPYRNA "\", it would be internally\n" -" assimilated as the default one!\n" -); + "A named tuple containing all pre-defined translation contexts.\n" + "\n" + ".. warning::\n" + " Never use a (new) context starting with \"" BLT_I18NCONTEXT_DEFAULT_BPYRNA + "\", it would be internally\n" + " assimilated as the default one!\n"); PyDoc_STRVAR(app_translations_contexts_C_to_py_doc, - "A readonly dict mapping contexts' C-identifiers to their py-identifiers." -); + "A readonly dict mapping contexts' C-identifiers to their py-identifiers."); static PyMemberDef app_translations_members[] = { - {(char *)"contexts", T_OBJECT_EX, offsetof(BlenderAppTranslations, contexts), READONLY, - app_translations_contexts_doc}, - {(char *)"contexts_C_to_py", T_OBJECT_EX, offsetof(BlenderAppTranslations, contexts_C_to_py), READONLY, - app_translations_contexts_C_to_py_doc}, - {NULL}, + {(char *)"contexts", + T_OBJECT_EX, + offsetof(BlenderAppTranslations, contexts), + READONLY, + app_translations_contexts_doc}, + {(char *)"contexts_C_to_py", + T_OBJECT_EX, + offsetof(BlenderAppTranslations, contexts_C_to_py), + READONLY, + app_translations_contexts_C_to_py_doc}, + {NULL}, }; PyDoc_STRVAR(app_translations_locale_doc, -"The actual locale currently in use (will always return a void string when Blender is built without " -"internationalization support)." -); + "The actual locale currently in use (will always return a void string when Blender " + "is built without " + "internationalization support)."); static PyObject *app_translations_locale_get(PyObject *UNUSED(self), void *UNUSED(userdata)) { - return PyUnicode_FromString(BLT_lang_get()); + return PyUnicode_FromString(BLT_lang_get()); } /* Note: defining as getter, as (even if quite unlikely), this *may* change during runtime... */ -PyDoc_STRVAR(app_translations_locales_doc, "All locales currently known by Blender (i.e. available as translations)."); +PyDoc_STRVAR(app_translations_locales_doc, + "All locales currently known by Blender (i.e. available as translations)."); static PyObject *app_translations_locales_get(PyObject *UNUSED(self), void *UNUSED(userdata)) { - PyObject *ret; - EnumPropertyItem *it, *items = BLT_lang_RNA_enum_properties(); - int num_locales = 0, pos = 0; - - if (items) { - /* This is not elegant, but simple! */ - for (it = items; it->identifier; it++) { - if (it->value) { - num_locales++; - } - } - } - - ret = PyTuple_New(num_locales); - - if (items) { - for (it = items; it->identifier; it++) { - if (it->value) { - PyTuple_SET_ITEM(ret, pos++, PyUnicode_FromString(it->description)); - } - } - } - - return ret; + PyObject *ret; + EnumPropertyItem *it, *items = BLT_lang_RNA_enum_properties(); + int num_locales = 0, pos = 0; + + if (items) { + /* This is not elegant, but simple! */ + for (it = items; it->identifier; it++) { + if (it->value) { + num_locales++; + } + } + } + + ret = PyTuple_New(num_locales); + + if (items) { + for (it = items; it->identifier; it++) { + if (it->value) { + PyTuple_SET_ITEM(ret, pos++, PyUnicode_FromString(it->description)); + } + } + } + + return ret; } static PyGetSetDef app_translations_getseters[] = { - /* {name, getter, setter, doc, userdata} */ - {(char *)"locale", (getter)app_translations_locale_get, NULL, app_translations_locale_doc, NULL}, - {(char *)"locales", (getter)app_translations_locales_get, NULL, app_translations_locales_doc, NULL}, - {NULL}, + /* {name, getter, setter, doc, userdata} */ + {(char *)"locale", + (getter)app_translations_locale_get, + NULL, + app_translations_locale_doc, + NULL}, + {(char *)"locales", + (getter)app_translations_locales_get, + NULL, + app_translations_locales_doc, + NULL}, + {NULL}, }; /* pgettext helper. */ -static PyObject *_py_pgettext(PyObject *args, PyObject *kw, const char *(*_pgettext)(const char *, const char *)) +static PyObject *_py_pgettext(PyObject *args, + PyObject *kw, + const char *(*_pgettext)(const char *, const char *)) { - static const char *kwlist[] = {"msgid", "msgctxt", NULL}; + static const char *kwlist[] = {"msgid", "msgctxt", NULL}; #ifdef WITH_INTERNATIONAL - char *msgid, *msgctxt = NULL; + char *msgid, *msgctxt = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kw, - "s|z:bpy.app.translations.pgettext", - (char **)kwlist, &msgid, &msgctxt)) - { - return NULL; - } + if (!PyArg_ParseTupleAndKeywords( + args, kw, "s|z:bpy.app.translations.pgettext", (char **)kwlist, &msgid, &msgctxt)) { + return NULL; + } - return PyUnicode_FromString((*_pgettext)(msgctxt ? msgctxt : BLT_I18NCONTEXT_DEFAULT, msgid)); + return PyUnicode_FromString((*_pgettext)(msgctxt ? msgctxt : BLT_I18NCONTEXT_DEFAULT, msgid)); #else - PyObject *msgid, *msgctxt; - (void)_pgettext; + PyObject *msgid, *msgctxt; + (void)_pgettext; - if (!PyArg_ParseTupleAndKeywords(args, kw, - "O|O:bpy.app.translations.pgettext", - (char **)kwlist, &msgid, &msgctxt)) - { - return NULL; - } + if (!PyArg_ParseTupleAndKeywords( + args, kw, "O|O:bpy.app.translations.pgettext", (char **)kwlist, &msgid, &msgctxt)) { + return NULL; + } - return Py_INCREF_RET(msgid); + return Py_INCREF_RET(msgid); #endif } -PyDoc_STRVAR(app_translations_pgettext_doc, -".. method:: pgettext(msgid, msgctxt)\n" -"\n" -" Try to translate the given msgid (with optional msgctxt).\n" -"\n" -" .. note::\n" -" The ``(msgid, msgctxt)`` parameters order has been switched compared to gettext function, to allow\n" -" single-parameter calls (context then defaults to BLT_I18NCONTEXT_DEFAULT).\n" -"\n" -" .. note::\n" -" You should really rarely need to use this function in regular addon code, as all translation should be\n" -" handled by Blender internal code. The only exception are string containing formatting (like \"File: %r\"),\n" -" but you should rather use :func:`pgettext_iface`/:func:`pgettext_tip` in those cases!\n" -"\n" -" .. note::\n" -" Does nothing when Blender is built without internationalization support (hence always returns ``msgid``).\n" -"\n" -" :arg msgid: The string to translate.\n" -" :type msgid: string\n" -" :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n" -" :type msgctxt: string or None\n" -" :return: The translated string (or msgid if no translation was found).\n" -"\n" -); -static PyObject *app_translations_pgettext(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) +PyDoc_STRVAR( + app_translations_pgettext_doc, + ".. method:: pgettext(msgid, msgctxt)\n" + "\n" + " Try to translate the given msgid (with optional msgctxt).\n" + "\n" + " .. note::\n" + " The ``(msgid, msgctxt)`` parameters order has been switched compared to gettext " + "function, to allow\n" + " single-parameter calls (context then defaults to BLT_I18NCONTEXT_DEFAULT).\n" + "\n" + " .. note::\n" + " You should really rarely need to use this function in regular addon code, as all " + "translation should be\n" + " handled by Blender internal code. The only exception are string containing formatting " + "(like \"File: %r\"),\n" + " but you should rather use :func:`pgettext_iface`/:func:`pgettext_tip` in those cases!\n" + "\n" + " .. note::\n" + " Does nothing when Blender is built without internationalization support (hence always " + "returns ``msgid``).\n" + "\n" + " :arg msgid: The string to translate.\n" + " :type msgid: string\n" + " :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n" + " :type msgctxt: string or None\n" + " :return: The translated string (or msgid if no translation was found).\n" + "\n"); +static PyObject *app_translations_pgettext(BlenderAppTranslations *UNUSED(self), + PyObject *args, + PyObject *kw) { - return _py_pgettext(args, kw, BLT_pgettext); + return _py_pgettext(args, kw, BLT_pgettext); } PyDoc_STRVAR(app_translations_pgettext_iface_doc, -".. method:: pgettext_iface(msgid, msgctxt)\n" -"\n" -" Try to translate the given msgid (with optional msgctxt), if labels' translation is enabled.\n" -"\n" -" .. note::\n" -" See :func:`pgettext` notes.\n" -"\n" -" :arg msgid: The string to translate.\n" -" :type msgid: string\n" -" :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n" -" :type msgctxt: string or None\n" -" :return: The translated string (or msgid if no translation was found).\n" -"\n" -); -static PyObject *app_translations_pgettext_iface(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) + ".. method:: pgettext_iface(msgid, msgctxt)\n" + "\n" + " Try to translate the given msgid (with optional msgctxt), if labels' translation " + "is enabled.\n" + "\n" + " .. note::\n" + " See :func:`pgettext` notes.\n" + "\n" + " :arg msgid: The string to translate.\n" + " :type msgid: string\n" + " :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n" + " :type msgctxt: string or None\n" + " :return: The translated string (or msgid if no translation was found).\n" + "\n"); +static PyObject *app_translations_pgettext_iface(BlenderAppTranslations *UNUSED(self), + PyObject *args, + PyObject *kw) { - return _py_pgettext(args, kw, BLT_translate_do_iface); + return _py_pgettext(args, kw, BLT_translate_do_iface); } PyDoc_STRVAR(app_translations_pgettext_tip_doc, -".. method:: pgettext_tip(msgid, msgctxt)\n" -"\n" -" Try to translate the given msgid (with optional msgctxt), if tooltips' translation is enabled.\n" -"\n" -" .. note::\n" -" See :func:`pgettext` notes.\n" -"\n" -" :arg msgid: The string to translate.\n" -" :type msgid: string\n" -" :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n" -" :type msgctxt: string or None\n" -" :return: The translated string (or msgid if no translation was found).\n" -"\n" -); -static PyObject *app_translations_pgettext_tip(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) + ".. method:: pgettext_tip(msgid, msgctxt)\n" + "\n" + " Try to translate the given msgid (with optional msgctxt), if tooltips' " + "translation is enabled.\n" + "\n" + " .. note::\n" + " See :func:`pgettext` notes.\n" + "\n" + " :arg msgid: The string to translate.\n" + " :type msgid: string\n" + " :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n" + " :type msgctxt: string or None\n" + " :return: The translated string (or msgid if no translation was found).\n" + "\n"); +static PyObject *app_translations_pgettext_tip(BlenderAppTranslations *UNUSED(self), + PyObject *args, + PyObject *kw) { - return _py_pgettext(args, kw, BLT_translate_do_tooltip); + return _py_pgettext(args, kw, BLT_translate_do_tooltip); } PyDoc_STRVAR(app_translations_pgettext_data_doc, -".. method:: pgettext_data(msgid, msgctxt)\n" -"\n" -" Try to translate the given msgid (with optional msgctxt), if new data name's translation is enabled.\n" -"\n" -" .. note::\n" -" See :func:`pgettext` notes.\n" -"\n" -" :arg msgid: The string to translate.\n" -" :type msgid: string\n" -" :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n" -" :type msgctxt: string or None\n" -" :return: The translated string (or ``msgid`` if no translation was found).\n" -"\n" -); -static PyObject *app_translations_pgettext_data(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) + ".. method:: pgettext_data(msgid, msgctxt)\n" + "\n" + " Try to translate the given msgid (with optional msgctxt), if new data name's " + "translation is enabled.\n" + "\n" + " .. note::\n" + " See :func:`pgettext` notes.\n" + "\n" + " :arg msgid: The string to translate.\n" + " :type msgid: string\n" + " :arg msgctxt: The translation context (defaults to BLT_I18NCONTEXT_DEFAULT).\n" + " :type msgctxt: string or None\n" + " :return: The translated string (or ``msgid`` if no translation was found).\n" + "\n"); +static PyObject *app_translations_pgettext_data(BlenderAppTranslations *UNUSED(self), + PyObject *args, + PyObject *kw) { - return _py_pgettext(args, kw, BLT_translate_do_new_dataname); + return _py_pgettext(args, kw, BLT_translate_do_new_dataname); } -PyDoc_STRVAR(app_translations_locale_explode_doc, -".. method:: locale_explode(locale)\n" -"\n" -" Return all components and their combinations of the given ISO locale string.\n" -"\n" -" >>> bpy.app.translations.locale_explode(\"sr_RS@latin\")\n" -" (\"sr\", \"RS\", \"latin\", \"sr_RS\", \"sr@latin\")\n" -"\n" -" For non-complete locales, missing elements will be None.\n" -"\n" -" :arg locale: The ISO locale string to explode.\n" -" :type msgid: string\n" -" :return: A tuple ``(language, country, variant, language_country, language@variant)``.\n" -"\n" -); -static PyObject *app_translations_locale_explode(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) +PyDoc_STRVAR( + app_translations_locale_explode_doc, + ".. method:: locale_explode(locale)\n" + "\n" + " Return all components and their combinations of the given ISO locale string.\n" + "\n" + " >>> bpy.app.translations.locale_explode(\"sr_RS@latin\")\n" + " (\"sr\", \"RS\", \"latin\", \"sr_RS\", \"sr@latin\")\n" + "\n" + " For non-complete locales, missing elements will be None.\n" + "\n" + " :arg locale: The ISO locale string to explode.\n" + " :type msgid: string\n" + " :return: A tuple ``(language, country, variant, language_country, language@variant)``.\n" + "\n"); +static PyObject *app_translations_locale_explode(BlenderAppTranslations *UNUSED(self), + PyObject *args, + PyObject *kw) { - PyObject *ret_tuple; - static const char *kwlist[] = {"locale", NULL}; - const char *locale; - char *language, *country, *variant, *language_country, *language_variant; + PyObject *ret_tuple; + static const char *kwlist[] = {"locale", NULL}; + const char *locale; + char *language, *country, *variant, *language_country, *language_variant; - if (!PyArg_ParseTupleAndKeywords(args, kw, "s:bpy.app.translations.locale_explode", (char **)kwlist, &locale)) { - return NULL; - } + if (!PyArg_ParseTupleAndKeywords( + args, kw, "s:bpy.app.translations.locale_explode", (char **)kwlist, &locale)) { + return NULL; + } - BLT_lang_locale_explode(locale, &language, &country, &variant, &language_country, &language_variant); + BLT_lang_locale_explode( + locale, &language, &country, &variant, &language_country, &language_variant); - ret_tuple = Py_BuildValue("sssss", language, country, variant, language_country, language_variant); + ret_tuple = Py_BuildValue( + "sssss", language, country, variant, language_country, language_variant); - MEM_SAFE_FREE(language); - MEM_SAFE_FREE(country); - MEM_SAFE_FREE(variant); - MEM_SAFE_FREE(language_country); - MEM_SAFE_FREE(language_variant); + MEM_SAFE_FREE(language); + MEM_SAFE_FREE(country); + MEM_SAFE_FREE(variant); + MEM_SAFE_FREE(language_country); + MEM_SAFE_FREE(language_variant); - return ret_tuple; + return ret_tuple; } static PyMethodDef app_translations_methods[] = { - /* Can't use METH_KEYWORDS alone, see http://bugs.python.org/issue11587 */ - {"register", (PyCFunction)app_translations_py_messages_register, METH_VARARGS | METH_KEYWORDS, - app_translations_py_messages_register_doc}, - {"unregister", (PyCFunction)app_translations_py_messages_unregister, METH_VARARGS | METH_KEYWORDS, - app_translations_py_messages_unregister_doc}, - {"pgettext", (PyCFunction)app_translations_pgettext, METH_VARARGS | METH_KEYWORDS | METH_STATIC, - app_translations_pgettext_doc}, - {"pgettext_iface", (PyCFunction)app_translations_pgettext_iface, METH_VARARGS | METH_KEYWORDS | METH_STATIC, - app_translations_pgettext_iface_doc}, - {"pgettext_tip", (PyCFunction)app_translations_pgettext_tip, METH_VARARGS | METH_KEYWORDS | METH_STATIC, - app_translations_pgettext_tip_doc}, - {"pgettext_data", (PyCFunction)app_translations_pgettext_data, METH_VARARGS | METH_KEYWORDS | METH_STATIC, - app_translations_pgettext_data_doc}, - {"locale_explode", (PyCFunction)app_translations_locale_explode, METH_VARARGS | METH_KEYWORDS | METH_STATIC, - app_translations_locale_explode_doc}, - {NULL}, + /* Can't use METH_KEYWORDS alone, see http://bugs.python.org/issue11587 */ + {"register", + (PyCFunction)app_translations_py_messages_register, + METH_VARARGS | METH_KEYWORDS, + app_translations_py_messages_register_doc}, + {"unregister", + (PyCFunction)app_translations_py_messages_unregister, + METH_VARARGS | METH_KEYWORDS, + app_translations_py_messages_unregister_doc}, + {"pgettext", + (PyCFunction)app_translations_pgettext, + METH_VARARGS | METH_KEYWORDS | METH_STATIC, + app_translations_pgettext_doc}, + {"pgettext_iface", + (PyCFunction)app_translations_pgettext_iface, + METH_VARARGS | METH_KEYWORDS | METH_STATIC, + app_translations_pgettext_iface_doc}, + {"pgettext_tip", + (PyCFunction)app_translations_pgettext_tip, + METH_VARARGS | METH_KEYWORDS | METH_STATIC, + app_translations_pgettext_tip_doc}, + {"pgettext_data", + (PyCFunction)app_translations_pgettext_data, + METH_VARARGS | METH_KEYWORDS | METH_STATIC, + app_translations_pgettext_data_doc}, + {"locale_explode", + (PyCFunction)app_translations_locale_explode, + METH_VARARGS | METH_KEYWORDS | METH_STATIC, + app_translations_locale_explode_doc}, + {NULL}, }; -static PyObject *app_translations_new(PyTypeObject *type, PyObject *UNUSED(args), PyObject *UNUSED(kw)) +static PyObject *app_translations_new(PyTypeObject *type, + PyObject *UNUSED(args), + PyObject *UNUSED(kw)) { -/* printf("%s (%p)\n", __func__, _translations); */ - - if (!_translations) { - _translations = (BlenderAppTranslations *)type->tp_alloc(type, 0); - if (_translations) { - PyObject *py_ctxts; - BLT_i18n_contexts_descriptor *ctxt; - - _translations->contexts = app_translations_contexts_make(); - - py_ctxts = _PyDict_NewPresized(ARRAY_SIZE(_contexts)); - for (ctxt = _contexts; ctxt->c_id; ctxt++) { - PyObject *val = PyUnicode_FromString(ctxt->py_id); - PyDict_SetItemString(py_ctxts, ctxt->c_id, val); - Py_DECREF(val); - } - _translations->contexts_C_to_py = PyDictProxy_New(py_ctxts); - Py_DECREF(py_ctxts); /* The actual dict is only owned by its proxy */ - - _translations->py_messages = PyDict_New(); - } - } - - return (PyObject *)_translations; + /* printf("%s (%p)\n", __func__, _translations); */ + + if (!_translations) { + _translations = (BlenderAppTranslations *)type->tp_alloc(type, 0); + if (_translations) { + PyObject *py_ctxts; + BLT_i18n_contexts_descriptor *ctxt; + + _translations->contexts = app_translations_contexts_make(); + + py_ctxts = _PyDict_NewPresized(ARRAY_SIZE(_contexts)); + for (ctxt = _contexts; ctxt->c_id; ctxt++) { + PyObject *val = PyUnicode_FromString(ctxt->py_id); + PyDict_SetItemString(py_ctxts, ctxt->c_id, val); + Py_DECREF(val); + } + _translations->contexts_C_to_py = PyDictProxy_New(py_ctxts); + Py_DECREF(py_ctxts); /* The actual dict is only owned by its proxy */ + + _translations->py_messages = PyDict_New(); + } + } + + return (PyObject *)_translations; } static void app_translations_free(void *obj) { - PyObject_Del(obj); + PyObject_Del(obj); #ifdef WITH_INTERNATIONAL - _clear_translations_cache(); + _clear_translations_cache(); #endif } PyDoc_STRVAR(app_translations_doc, -"This object contains some data/methods regarding internationalization in Blender, and allows every py script\n" -"to feature translations for its own UI messages.\n" -"\n" -); + "This object contains some data/methods regarding internationalization in Blender, " + "and allows every py script\n" + "to feature translations for its own UI messages.\n" + "\n"); static PyTypeObject BlenderAppTranslationsType = { - PyVarObject_HEAD_INIT(NULL, 0) - /* tp_name */ - "bpy.app._translations_type", - /* tp_basicsize */ - sizeof(BlenderAppTranslations), - 0, /* tp_itemsize */ - /* methods */ - /* No destructor, this is a singleton! */ - NULL, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* tp_repr */ - - /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - - app_translations_doc, /* char *tp_doc; Documentation string */ - - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ - 0, /* long tp_weaklistoffset */ - - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - app_translations_methods, /* struct PyMethodDef *tp_methods; */ - app_translations_members, /* struct PyMemberDef *tp_members; */ - app_translations_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - /* newfunc tp_new; */ - (newfunc)app_translations_new, - /* Low-level free-memory routine */ - app_translations_free, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + PyVarObject_HEAD_INIT(NULL, 0) + /* tp_name */ + "bpy.app._translations_type", + /* tp_basicsize */ + sizeof(BlenderAppTranslations), + 0, /* tp_itemsize */ + /* methods */ + /* No destructor, this is a singleton! */ + NULL, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + NULL, /* tp_repr */ + + /* Method suites for standard classes */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + + app_translations_doc, /* char *tp_doc; Documentation string */ + + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + app_translations_methods, /* struct PyMethodDef *tp_methods; */ + app_translations_members, /* struct PyMemberDef *tp_members; */ + app_translations_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + /* newfunc tp_new; */ + (newfunc)app_translations_new, + /* Low-level free-memory routine */ + app_translations_free, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; PyObject *BPY_app_translations_struct(void) { - PyObject *ret; + PyObject *ret; - /* Let's finalize our contexts structseq definition! */ - { - BLT_i18n_contexts_descriptor *ctxt; - PyStructSequence_Field *desc; + /* Let's finalize our contexts structseq definition! */ + { + BLT_i18n_contexts_descriptor *ctxt; + PyStructSequence_Field *desc; - /* We really populate the contexts' fields here! */ - for (ctxt = _contexts, desc = app_translations_contexts_desc.fields; ctxt->c_id; ctxt++, desc++) { - desc->name = (char *)ctxt->py_id; - desc->doc = NULL; - } - desc->name = desc->doc = NULL; /* End sentinel! */ + /* We really populate the contexts' fields here! */ + for (ctxt = _contexts, desc = app_translations_contexts_desc.fields; ctxt->c_id; + ctxt++, desc++) { + desc->name = (char *)ctxt->py_id; + desc->doc = NULL; + } + desc->name = desc->doc = NULL; /* End sentinel! */ - PyStructSequence_InitType(&BlenderAppTranslationsContextsType, &app_translations_contexts_desc); - } + PyStructSequence_InitType(&BlenderAppTranslationsContextsType, + &app_translations_contexts_desc); + } - if (PyType_Ready(&BlenderAppTranslationsType) < 0) { - return NULL; - } + if (PyType_Ready(&BlenderAppTranslationsType) < 0) { + return NULL; + } - ret = PyObject_CallObject((PyObject *)&BlenderAppTranslationsType, NULL); + ret = PyObject_CallObject((PyObject *)&BlenderAppTranslationsType, NULL); - /* prevent user from creating new instances */ - BlenderAppTranslationsType.tp_new = NULL; - /* without this we can't do set(sys.modules) [#29635] */ - BlenderAppTranslationsType.tp_hash = (hashfunc)_Py_HashPointer; + /* prevent user from creating new instances */ + BlenderAppTranslationsType.tp_new = NULL; + /* without this we can't do set(sys.modules) [#29635] */ + BlenderAppTranslationsType.tp_hash = (hashfunc)_Py_HashPointer; - return ret; + return ret; } void BPY_app_translations_end(void) { - /* Incase the object remains in a module's namespace, see T44127. */ + /* Incase the object remains in a module's namespace, see T44127. */ #ifdef WITH_INTERNATIONAL - _clear_translations_cache(); + _clear_translations_cache(); #endif } diff --git a/source/blender/python/intern/bpy_app_translations.h b/source/blender/python/intern/bpy_app_translations.h index a8eca079f37..e1e82480b49 100644 --- a/source/blender/python/intern/bpy_app_translations.h +++ b/source/blender/python/intern/bpy_app_translations.h @@ -22,6 +22,6 @@ #define __BPY_APP_TRANSLATIONS_H__ PyObject *BPY_app_translations_struct(void); -void BPY_app_translations_end(void); +void BPY_app_translations_end(void); #endif /* __BPY_APP_TRANSLATIONS_H__ */ diff --git a/source/blender/python/intern/bpy_capi_utils.c b/source/blender/python/intern/bpy_capi_utils.c index 549a06f5b28..db1684a7bca 100644 --- a/source/blender/python/intern/bpy_capi_utils.c +++ b/source/blender/python/intern/bpy_capi_utils.c @@ -38,42 +38,48 @@ #include "../generic/py_capi_utils.h" static bContext *__py_context = NULL; -bContext *BPy_GetContext(void) { return __py_context; } -void BPy_SetContext(bContext *C) { __py_context = C; } +bContext *BPy_GetContext(void) +{ + return __py_context; +} +void BPy_SetContext(bContext *C) +{ + __py_context = C; +} char *BPy_enum_as_string(const EnumPropertyItem *item) { - DynStr *dynstr = BLI_dynstr_new(); - const EnumPropertyItem *e; - char *cstring; - - for (e = item; item->identifier; item++) { - if (item->identifier[0]) { - BLI_dynstr_appendf(dynstr, (e == item) ? "'%s'" : ", '%s'", item->identifier); - } - } - - cstring = BLI_dynstr_get_cstring(dynstr); - BLI_dynstr_free(dynstr); - return cstring; + DynStr *dynstr = BLI_dynstr_new(); + const EnumPropertyItem *e; + char *cstring; + + for (e = item; item->identifier; item++) { + if (item->identifier[0]) { + BLI_dynstr_appendf(dynstr, (e == item) ? "'%s'" : ", '%s'", item->identifier); + } + } + + cstring = BLI_dynstr_get_cstring(dynstr); + BLI_dynstr_free(dynstr); + return cstring; } short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear) { - char *report_str; + char *report_str; - report_str = BKE_reports_string(reports, RPT_ERROR); + report_str = BKE_reports_string(reports, RPT_ERROR); - if (clear == true) { - BKE_reports_clear(reports); - } + if (clear == true) { + BKE_reports_clear(reports); + } - if (report_str) { - PyErr_SetString(exception, report_str); - MEM_freeN(report_str); - } + if (report_str) { + PyErr_SetString(exception, report_str); + MEM_freeN(report_str); + } - return (report_str == NULL) ? 0 : -1; + return (report_str == NULL) ? 0 : -1; } /** @@ -81,80 +87,78 @@ short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool */ void BPy_reports_write_stdout(const ReportList *reports, const char *header) { - if (header) { - PySys_WriteStdout("%s\n", header); - } + if (header) { + PySys_WriteStdout("%s\n", header); + } - for (const Report *report = reports->list.first; report; report = report->next) { - PySys_WriteStdout("%s: %s\n", report->typestr, report->message); - } + for (const Report *report = reports->list.first; report; report = report->next) { + PySys_WriteStdout("%s: %s\n", report->typestr, report->message); + } } bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const bool use_location) { - PyObject *pystring; - - if (!PyErr_Occurred()) { - return 1; - } - - /* less hassle if we allow NULL */ - if (reports == NULL) { - PyErr_Print(); - PyErr_Clear(); - return 1; - } - - if (use_full) { - pystring = PyC_ExceptionBuffer(); - } - else { - pystring = PyC_ExceptionBuffer_Simple(); - } - - if (pystring == NULL) { - BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert"); - return 0; - } - - if (use_location) { - const char *filename; - int lineno; - - PyObject *pystring_format; /* workaround, see below */ - const char *cstring; - - PyC_FileAndNum(&filename, &lineno); - if (filename == NULL) { - filename = "<unknown location>"; - } + PyObject *pystring; + + if (!PyErr_Occurred()) { + return 1; + } + + /* less hassle if we allow NULL */ + if (reports == NULL) { + PyErr_Print(); + PyErr_Clear(); + return 1; + } + + if (use_full) { + pystring = PyC_ExceptionBuffer(); + } + else { + pystring = PyC_ExceptionBuffer_Simple(); + } + + if (pystring == NULL) { + BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert"); + return 0; + } + + if (use_location) { + const char *filename; + int lineno; + + PyObject *pystring_format; /* workaround, see below */ + const char *cstring; + + PyC_FileAndNum(&filename, &lineno); + if (filename == NULL) { + filename = "<unknown location>"; + } #if 0 /* ARG!. workaround for a bug in blenders use of vsnprintf */ - BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", _PyUnicode_AsString(pystring), filename, lineno); + BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", _PyUnicode_AsString(pystring), filename, lineno); #else - pystring_format = PyUnicode_FromFormat( - TIP_("%s\nlocation: %s:%d\n"), - _PyUnicode_AsString(pystring), filename, lineno); + pystring_format = PyUnicode_FromFormat( + TIP_("%s\nlocation: %s:%d\n"), _PyUnicode_AsString(pystring), filename, lineno); - cstring = _PyUnicode_AsString(pystring_format); - BKE_report(reports, RPT_ERROR, cstring); + cstring = _PyUnicode_AsString(pystring_format); + BKE_report(reports, RPT_ERROR, cstring); - /* not exactly needed. just for testing */ - fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); + /* not exactly needed. just for testing */ + fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); - Py_DECREF(pystring_format); /* workaround */ + Py_DECREF(pystring_format); /* workaround */ #endif - } - else { - BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(pystring)); - } - + } + else { + BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(pystring)); + } - Py_DECREF(pystring); - return 1; + Py_DECREF(pystring); + return 1; } bool BPy_errors_to_report(ReportList *reports) { - return BPy_errors_to_report_ex(reports, true, true); + return BPy_errors_to_report_ex(reports, true, true); } diff --git a/source/blender/python/intern/bpy_capi_utils.h b/source/blender/python/intern/bpy_capi_utils.h index f8d42b463ac..fe086b61097 100644 --- a/source/blender/python/intern/bpy_capi_utils.h +++ b/source/blender/python/intern/bpy_capi_utils.h @@ -30,12 +30,17 @@ struct ReportList; char *BPy_enum_as_string(const struct EnumPropertyItem *item); -#define BLANK_PYTHON_TYPE {PyVarObject_HEAD_INIT(NULL, 0) NULL} +#define BLANK_PYTHON_TYPE \ + { \ + PyVarObject_HEAD_INIT(NULL, 0) NULL \ + } /* error reporting */ short BPy_reports_to_error(struct ReportList *reports, PyObject *exception, const bool clear); void BPy_reports_write_stdout(const struct ReportList *reports, const char *header); -bool BPy_errors_to_report_ex(struct ReportList *reports, const bool use_full, const bool use_location); +bool BPy_errors_to_report_ex(struct ReportList *reports, + const bool use_full, + const bool use_location); bool BPy_errors_to_report(struct ReportList *reports); /* TODO - find a better solution! */ @@ -45,4 +50,4 @@ void BPy_SetContext(struct bContext *C); extern void bpy_context_set(struct bContext *C, PyGILState_STATE *gilstate); extern void bpy_context_clear(struct bContext *C, PyGILState_STATE *gilstate); -#endif /* __BPY_CAPI_UTILS_H__ */ +#endif /* __BPY_CAPI_UTILS_H__ */ diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index cb23739ca33..3457e614708 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -36,7 +36,7 @@ #include "BKE_fcurve.h" #include "BKE_global.h" -#include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */ +#include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */ #include "bpy_intern_string.h" @@ -66,137 +66,136 @@ static PyObject *bpy_pydriver_Dict__whitelist = NULL; */ int bpy_pydriver_create_dict(void) { - PyObject *d, *mod; - - /* validate namespace for driver evaluation */ - if (bpy_pydriver_Dict) { - return -1; - } - - d = PyDict_New(); - if (d == NULL) { - return -1; - } - else { - bpy_pydriver_Dict = d; - } - - /* import some modules: builtins, bpy, math, (Blender.noise)*/ - PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins()); - - mod = PyImport_ImportModule("math"); - if (mod) { - PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - don't overwrite existing values */ - Py_DECREF(mod); - } + PyObject *d, *mod; + + /* validate namespace for driver evaluation */ + if (bpy_pydriver_Dict) { + return -1; + } + + d = PyDict_New(); + if (d == NULL) { + return -1; + } + else { + bpy_pydriver_Dict = d; + } + + /* import some modules: builtins, bpy, math, (Blender.noise)*/ + PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins()); + + mod = PyImport_ImportModule("math"); + if (mod) { + PyDict_Merge(d, PyModule_GetDict(mod), 0); /* 0 - don't overwrite existing values */ + Py_DECREF(mod); + } #ifdef USE_BYTECODE_WHITELIST - PyObject *mod_math = mod; + PyObject *mod_math = mod; #endif - /* add bpy to global namespace */ - mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0); - if (mod) { - PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod); - Py_DECREF(mod); - } - - /* add noise to global namespace */ - mod = PyImport_ImportModuleLevel("mathutils", NULL, NULL, NULL, 0); - if (mod) { - PyObject *modsub = PyDict_GetItemString(PyModule_GetDict(mod), "noise"); - PyDict_SetItemString(bpy_pydriver_Dict, "noise", modsub); - Py_DECREF(mod); - } + /* add bpy to global namespace */ + mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0); + if (mod) { + PyDict_SetItemString(bpy_pydriver_Dict, "bpy", mod); + Py_DECREF(mod); + } + + /* add noise to global namespace */ + mod = PyImport_ImportModuleLevel("mathutils", NULL, NULL, NULL, 0); + if (mod) { + PyObject *modsub = PyDict_GetItemString(PyModule_GetDict(mod), "noise"); + PyDict_SetItemString(bpy_pydriver_Dict, "noise", modsub); + Py_DECREF(mod); + } #ifdef USE_BYTECODE_WHITELIST - /* setup the whitelist */ - { - bpy_pydriver_Dict__whitelist = PyDict_New(); - const char *whitelist[] = { - /* builtins (basic) */ - "all", - "any", - "len", - /* builtins (numeric) */ - "max", - "min", - "pow", - "round", - "sum", - /* types */ - "bool", - "float", - "int", - - NULL, - }; - - for (int i = 0; whitelist[i]; i++) { - PyDict_SetItemString(bpy_pydriver_Dict__whitelist, whitelist[i], Py_None); - } - - /* Add all of 'math' functions. */ - if (mod_math != NULL) { - PyObject *mod_math_dict = PyModule_GetDict(mod_math); - PyObject *arg_key, *arg_value; - Py_ssize_t arg_pos = 0; - while (PyDict_Next(mod_math_dict, &arg_pos, &arg_key, &arg_value)) { - const char *arg_str = _PyUnicode_AsString(arg_key); - if (arg_str[0] && arg_str[1] != '_') { - PyDict_SetItem(bpy_pydriver_Dict__whitelist, arg_key, Py_None); - } - } - } - } -#endif /* USE_BYTECODE_WHITELIST */ - - return 0; + /* setup the whitelist */ + { + bpy_pydriver_Dict__whitelist = PyDict_New(); + const char *whitelist[] = { + /* builtins (basic) */ + "all", + "any", + "len", + /* builtins (numeric) */ + "max", + "min", + "pow", + "round", + "sum", + /* types */ + "bool", + "float", + "int", + + NULL, + }; + + for (int i = 0; whitelist[i]; i++) { + PyDict_SetItemString(bpy_pydriver_Dict__whitelist, whitelist[i], Py_None); + } + + /* Add all of 'math' functions. */ + if (mod_math != NULL) { + PyObject *mod_math_dict = PyModule_GetDict(mod_math); + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(mod_math_dict, &arg_pos, &arg_key, &arg_value)) { + const char *arg_str = _PyUnicode_AsString(arg_key); + if (arg_str[0] && arg_str[1] != '_') { + PyDict_SetItem(bpy_pydriver_Dict__whitelist, arg_key, Py_None); + } + } + } + } +#endif /* USE_BYTECODE_WHITELIST */ + + return 0; } /* note, this function should do nothing most runs, only when changing frame */ /* not thread safe but neither is python */ static struct { - float evaltime; + float evaltime; - /* borrowed reference to the 'self' in 'bpy_pydriver_Dict' - * keep for as long as the same self is used. */ - PyObject *self; + /* borrowed reference to the 'self' in 'bpy_pydriver_Dict' + * keep for as long as the same self is used. */ + PyObject *self; } g_pydriver_state_prev = { - .evaltime = FLT_MAX, - .self = NULL, + .evaltime = FLT_MAX, + .self = NULL, }; static void bpy_pydriver_namespace_update_frame(const float evaltime) { - if (g_pydriver_state_prev.evaltime != evaltime) { - PyObject *item = PyFloat_FromDouble(evaltime); - PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_frame, item); - Py_DECREF(item); + if (g_pydriver_state_prev.evaltime != evaltime) { + PyObject *item = PyFloat_FromDouble(evaltime); + PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_frame, item); + Py_DECREF(item); - g_pydriver_state_prev.evaltime = evaltime; - } + g_pydriver_state_prev.evaltime = evaltime; + } } static void bpy_pydriver_namespace_update_self(struct PathResolvedRNA *anim_rna) { - if ((g_pydriver_state_prev.self == NULL) || - (pyrna_driver_is_equal_anim_rna(anim_rna, g_pydriver_state_prev.self) == false)) - { - PyObject *item = pyrna_driver_self_from_anim_rna(anim_rna); - PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_self, item); - Py_DECREF(item); - - g_pydriver_state_prev.self = item; - } + if ((g_pydriver_state_prev.self == NULL) || + (pyrna_driver_is_equal_anim_rna(anim_rna, g_pydriver_state_prev.self) == false)) { + PyObject *item = pyrna_driver_self_from_anim_rna(anim_rna); + PyDict_SetItem(bpy_pydriver_Dict, bpy_intern_str_self, item); + Py_DECREF(item); + + g_pydriver_state_prev.self = item; + } } static void bpy_pydriver_namespace_clear_self(void) { - if (g_pydriver_state_prev.self) { - PyDict_DelItem(bpy_pydriver_Dict, bpy_intern_str_self); + if (g_pydriver_state_prev.self) { + PyDict_DelItem(bpy_pydriver_Dict, bpy_intern_str_self); - g_pydriver_state_prev.self = NULL; - } + g_pydriver_state_prev.self = NULL; + } } /* Update function, it gets rid of pydrivers global dictionary, forcing @@ -206,171 +205,176 @@ static void bpy_pydriver_namespace_clear_self(void) */ void BPY_driver_reset(void) { - PyGILState_STATE gilstate; - bool use_gil = true; /* !PyC_IsInterpreterActive(); */ + PyGILState_STATE gilstate; + bool use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */ - PyDict_Clear(bpy_pydriver_Dict); - Py_DECREF(bpy_pydriver_Dict); - bpy_pydriver_Dict = NULL; - } + if (bpy_pydriver_Dict) { /* free the global dict used by pydrivers */ + PyDict_Clear(bpy_pydriver_Dict); + Py_DECREF(bpy_pydriver_Dict); + bpy_pydriver_Dict = NULL; + } #ifdef USE_BYTECODE_WHITELIST - if (bpy_pydriver_Dict__whitelist) { - PyDict_Clear(bpy_pydriver_Dict__whitelist); - Py_DECREF(bpy_pydriver_Dict__whitelist); - bpy_pydriver_Dict__whitelist = NULL; - } + if (bpy_pydriver_Dict__whitelist) { + PyDict_Clear(bpy_pydriver_Dict__whitelist); + Py_DECREF(bpy_pydriver_Dict__whitelist); + bpy_pydriver_Dict__whitelist = NULL; + } #endif - g_pydriver_state_prev.evaltime = FLT_MAX; + g_pydriver_state_prev.evaltime = FLT_MAX; - /* freed when clearing driver dict */ - g_pydriver_state_prev.self = NULL; + /* freed when clearing driver dict */ + g_pydriver_state_prev.self = NULL; - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - return; + return; } /* error return function for BPY_eval_pydriver */ static void pydriver_error(ChannelDriver *driver) { - driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */ - fprintf(stderr, "\nError in Driver: The following Python expression failed:\n\t'%s'\n\n", driver->expression); - - // BPy_errors_to_report(NULL); // TODO - reports - PyErr_Print(); - PyErr_Clear(); + driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */ + fprintf(stderr, + "\nError in Driver: The following Python expression failed:\n\t'%s'\n\n", + driver->expression); + + // BPy_errors_to_report(NULL); // TODO - reports + PyErr_Print(); + PyErr_Clear(); } #ifdef USE_BYTECODE_WHITELIST -#define OK_OP(op) [op] = 1 +# define OK_OP(op) [op] = 1 static const char secure_opcodes[255] = { - OK_OP(POP_TOP), - OK_OP(ROT_TWO), - OK_OP(ROT_THREE), - OK_OP(DUP_TOP), - OK_OP(DUP_TOP_TWO), - OK_OP(NOP), - OK_OP(UNARY_POSITIVE), - OK_OP(UNARY_NEGATIVE), - OK_OP(UNARY_NOT), - OK_OP(UNARY_INVERT), - OK_OP(BINARY_MATRIX_MULTIPLY), - OK_OP(INPLACE_MATRIX_MULTIPLY), - OK_OP(BINARY_POWER), - OK_OP(BINARY_MULTIPLY), - OK_OP(BINARY_MODULO), - OK_OP(BINARY_ADD), - OK_OP(BINARY_SUBTRACT), - OK_OP(BINARY_SUBSCR), - OK_OP(BINARY_FLOOR_DIVIDE), - OK_OP(BINARY_TRUE_DIVIDE), - OK_OP(INPLACE_FLOOR_DIVIDE), - OK_OP(INPLACE_TRUE_DIVIDE), - OK_OP(INPLACE_ADD), - OK_OP(INPLACE_SUBTRACT), - OK_OP(INPLACE_MULTIPLY), - OK_OP(INPLACE_MODULO), - OK_OP(BINARY_LSHIFT), - OK_OP(BINARY_RSHIFT), - OK_OP(BINARY_AND), - OK_OP(BINARY_XOR), - OK_OP(BINARY_OR), - OK_OP(INPLACE_POWER), - OK_OP(INPLACE_LSHIFT), - OK_OP(INPLACE_RSHIFT), - OK_OP(INPLACE_AND), - OK_OP(INPLACE_XOR), - OK_OP(INPLACE_OR), - OK_OP(RETURN_VALUE), - OK_OP(BUILD_TUPLE), - OK_OP(BUILD_LIST), - OK_OP(BUILD_SET), - OK_OP(BUILD_MAP), - OK_OP(COMPARE_OP), - OK_OP(JUMP_FORWARD), - OK_OP(JUMP_IF_FALSE_OR_POP), - OK_OP(JUMP_IF_TRUE_OR_POP), - OK_OP(JUMP_ABSOLUTE), - OK_OP(POP_JUMP_IF_FALSE), - OK_OP(POP_JUMP_IF_TRUE), - OK_OP(LOAD_GLOBAL), - OK_OP(LOAD_FAST), - OK_OP(STORE_FAST), - OK_OP(DELETE_FAST), - OK_OP(LOAD_DEREF), - OK_OP(STORE_DEREF), - - /* special cases */ - OK_OP(LOAD_CONST), /* ok because constants are accepted */ - OK_OP(LOAD_NAME), /* ok, because PyCodeObject.names is checked */ - OK_OP(CALL_FUNCTION), /* ok, because we check its 'name' before calling */ - OK_OP(CALL_FUNCTION_KW), - OK_OP(CALL_FUNCTION_EX), + OK_OP(POP_TOP), + OK_OP(ROT_TWO), + OK_OP(ROT_THREE), + OK_OP(DUP_TOP), + OK_OP(DUP_TOP_TWO), + OK_OP(NOP), + OK_OP(UNARY_POSITIVE), + OK_OP(UNARY_NEGATIVE), + OK_OP(UNARY_NOT), + OK_OP(UNARY_INVERT), + OK_OP(BINARY_MATRIX_MULTIPLY), + OK_OP(INPLACE_MATRIX_MULTIPLY), + OK_OP(BINARY_POWER), + OK_OP(BINARY_MULTIPLY), + OK_OP(BINARY_MODULO), + OK_OP(BINARY_ADD), + OK_OP(BINARY_SUBTRACT), + OK_OP(BINARY_SUBSCR), + OK_OP(BINARY_FLOOR_DIVIDE), + OK_OP(BINARY_TRUE_DIVIDE), + OK_OP(INPLACE_FLOOR_DIVIDE), + OK_OP(INPLACE_TRUE_DIVIDE), + OK_OP(INPLACE_ADD), + OK_OP(INPLACE_SUBTRACT), + OK_OP(INPLACE_MULTIPLY), + OK_OP(INPLACE_MODULO), + OK_OP(BINARY_LSHIFT), + OK_OP(BINARY_RSHIFT), + OK_OP(BINARY_AND), + OK_OP(BINARY_XOR), + OK_OP(BINARY_OR), + OK_OP(INPLACE_POWER), + OK_OP(INPLACE_LSHIFT), + OK_OP(INPLACE_RSHIFT), + OK_OP(INPLACE_AND), + OK_OP(INPLACE_XOR), + OK_OP(INPLACE_OR), + OK_OP(RETURN_VALUE), + OK_OP(BUILD_TUPLE), + OK_OP(BUILD_LIST), + OK_OP(BUILD_SET), + OK_OP(BUILD_MAP), + OK_OP(COMPARE_OP), + OK_OP(JUMP_FORWARD), + OK_OP(JUMP_IF_FALSE_OR_POP), + OK_OP(JUMP_IF_TRUE_OR_POP), + OK_OP(JUMP_ABSOLUTE), + OK_OP(POP_JUMP_IF_FALSE), + OK_OP(POP_JUMP_IF_TRUE), + OK_OP(LOAD_GLOBAL), + OK_OP(LOAD_FAST), + OK_OP(STORE_FAST), + OK_OP(DELETE_FAST), + OK_OP(LOAD_DEREF), + OK_OP(STORE_DEREF), + + /* special cases */ + OK_OP(LOAD_CONST), /* ok because constants are accepted */ + OK_OP(LOAD_NAME), /* ok, because PyCodeObject.names is checked */ + OK_OP(CALL_FUNCTION), /* ok, because we check its 'name' before calling */ + OK_OP(CALL_FUNCTION_KW), + OK_OP(CALL_FUNCTION_EX), }; -#undef OK_OP +# undef OK_OP static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *dict_arr[]) { - PyCodeObject *py_code = (PyCodeObject *)expr_code; - - /* Check names. */ - { - for (int i = 0; i < PyTuple_GET_SIZE(py_code->co_names); i++) { - PyObject *name = PyTuple_GET_ITEM(py_code->co_names, i); - - bool contains_name = false; - for (int j = 0; dict_arr[j]; j++) { - if (PyDict_Contains(dict_arr[j], name)) { - contains_name = true; - break; - } - } - - if (contains_name == false) { - fprintf(stderr, "\tBPY_driver_eval() - restricted access disallows name '%s', " - "enable auto-execution to support\n", _PyUnicode_AsString(name)); - return false; - } - } - } - - /* Check opcodes. */ - { - const _Py_CODEUNIT *codestr; - Py_ssize_t code_len; - - PyBytes_AsStringAndSize(py_code->co_code, (char **)&codestr, &code_len); - code_len /= sizeof(*codestr); - - for (Py_ssize_t i = 0; i < code_len; i++) { - const int opcode = _Py_OPCODE(codestr[i]); - if (secure_opcodes[opcode] == 0) { - fprintf(stderr, "\tBPY_driver_eval() - restricted access disallows opcode '%d', " - "enable auto-execution to support\n", opcode); - return false; - } - } - -#undef CODESIZE - } - - return true; + PyCodeObject *py_code = (PyCodeObject *)expr_code; + + /* Check names. */ + { + for (int i = 0; i < PyTuple_GET_SIZE(py_code->co_names); i++) { + PyObject *name = PyTuple_GET_ITEM(py_code->co_names, i); + + bool contains_name = false; + for (int j = 0; dict_arr[j]; j++) { + if (PyDict_Contains(dict_arr[j], name)) { + contains_name = true; + break; + } + } + + if (contains_name == false) { + fprintf(stderr, + "\tBPY_driver_eval() - restricted access disallows name '%s', " + "enable auto-execution to support\n", + _PyUnicode_AsString(name)); + return false; + } + } + } + + /* Check opcodes. */ + { + const _Py_CODEUNIT *codestr; + Py_ssize_t code_len; + + PyBytes_AsStringAndSize(py_code->co_code, (char **)&codestr, &code_len); + code_len /= sizeof(*codestr); + + for (Py_ssize_t i = 0; i < code_len; i++) { + const int opcode = _Py_OPCODE(codestr[i]); + if (secure_opcodes[opcode] == 0) { + fprintf(stderr, + "\tBPY_driver_eval() - restricted access disallows opcode '%d', " + "enable auto-execution to support\n", + opcode); + return false; + } + } + +# undef CODESIZE + } + + return true; } -#endif /* USE_BYTECODE_WHITELIST */ - +#endif /* USE_BYTECODE_WHITELIST */ /* This evals py driver expressions, 'expr' is a Python expression that * should evaluate to a float number, which is returned. @@ -388,231 +392,239 @@ static bool bpy_driver_secure_bytecode_validate(PyObject *expr_code, PyObject *d * original driver, otherwise these would get freed while editing. Due to * the GIL this is thread-safe. */ -float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, const float evaltime) +float BPY_driver_exec(struct PathResolvedRNA *anim_rna, + ChannelDriver *driver, + ChannelDriver *driver_orig, + const float evaltime) { - PyObject *driver_vars = NULL; - PyObject *retval = NULL; - PyObject *expr_vars; /* speed up by pre-hashing string & avoids re-converting unicode strings for every execution */ - PyObject *expr_code; - PyGILState_STATE gilstate; - bool use_gil; - - DriverVar *dvar; - double result = 0.0; /* default return */ - const char *expr; - short targets_ok = 1; - int i; - - /* get the py expression to be evaluated */ - expr = driver_orig->expression; - if (expr[0] == '\0') { - return 0.0f; - } + PyObject *driver_vars = NULL; + PyObject *retval = NULL; + PyObject * + expr_vars; /* speed up by pre-hashing string & avoids re-converting unicode strings for every execution */ + PyObject *expr_code; + PyGILState_STATE gilstate; + bool use_gil; + + DriverVar *dvar; + double result = 0.0; /* default return */ + const char *expr; + short targets_ok = 1; + int i; + + /* get the py expression to be evaluated */ + expr = driver_orig->expression; + if (expr[0] == '\0') { + return 0.0f; + } #ifndef USE_BYTECODE_WHITELIST - if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) { - if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) { - G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL; - BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", expr); - - printf("skipping driver '%s', automatic scripts are disabled\n", expr); - } - return 0.0f; - } + if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) { + if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) { + G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL; + BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", expr); + + printf("skipping driver '%s', automatic scripts are disabled\n", expr); + } + return 0.0f; + } #else - bool is_recompile = false; + bool is_recompile = false; #endif - use_gil = true; /* !PyC_IsInterpreterActive(); */ - - if (use_gil) { - gilstate = PyGILState_Ensure(); - } - - /* needed since drivers are updated directly after undo where 'main' is - * re-allocated [#28807] */ - BPY_update_rna_module(); - - /* init global dictionary for py-driver evaluation settings */ - if (!bpy_pydriver_Dict) { - if (bpy_pydriver_create_dict() != 0) { - fprintf(stderr, "PyDriver error: couldn't create Python dictionary\n"); - if (use_gil) { - PyGILState_Release(gilstate); - } - return 0.0f; - } - } - - /* update global namespace */ - bpy_pydriver_namespace_update_frame(evaltime); - - if (driver_orig->flag & DRIVER_FLAG_USE_SELF) { - bpy_pydriver_namespace_update_self(anim_rna); - } - else { - bpy_pydriver_namespace_clear_self(); - } - - if (driver_orig->expr_comp == NULL) { - driver_orig->flag |= DRIVER_FLAG_RECOMPILE; - } - - /* compile the expression first if it hasn't been compiled or needs to be rebuilt */ - if (driver_orig->flag & DRIVER_FLAG_RECOMPILE) { - Py_XDECREF(driver_orig->expr_comp); - driver_orig->expr_comp = PyTuple_New(2); - - expr_code = Py_CompileString(expr, "<bpy driver>", Py_eval_input); - PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, expr_code); - - driver_orig->flag &= ~DRIVER_FLAG_RECOMPILE; - driver_orig->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ + + if (use_gil) { + gilstate = PyGILState_Ensure(); + } + + /* needed since drivers are updated directly after undo where 'main' is + * re-allocated [#28807] */ + BPY_update_rna_module(); + + /* init global dictionary for py-driver evaluation settings */ + if (!bpy_pydriver_Dict) { + if (bpy_pydriver_create_dict() != 0) { + fprintf(stderr, "PyDriver error: couldn't create Python dictionary\n"); + if (use_gil) { + PyGILState_Release(gilstate); + } + return 0.0f; + } + } + + /* update global namespace */ + bpy_pydriver_namespace_update_frame(evaltime); + + if (driver_orig->flag & DRIVER_FLAG_USE_SELF) { + bpy_pydriver_namespace_update_self(anim_rna); + } + else { + bpy_pydriver_namespace_clear_self(); + } + + if (driver_orig->expr_comp == NULL) { + driver_orig->flag |= DRIVER_FLAG_RECOMPILE; + } + + /* compile the expression first if it hasn't been compiled or needs to be rebuilt */ + if (driver_orig->flag & DRIVER_FLAG_RECOMPILE) { + Py_XDECREF(driver_orig->expr_comp); + driver_orig->expr_comp = PyTuple_New(2); + + expr_code = Py_CompileString(expr, "<bpy driver>", Py_eval_input); + PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, expr_code); + + driver_orig->flag &= ~DRIVER_FLAG_RECOMPILE; + driver_orig->flag |= + DRIVER_FLAG_RENAMEVAR; /* maybe this can be removed but for now best keep until were sure */ #ifdef USE_BYTECODE_WHITELIST - is_recompile = true; + is_recompile = true; #endif - } - else { - expr_code = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 0); - } - - if (driver_orig->flag & DRIVER_FLAG_RENAMEVAR) { - /* may not be set */ - expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1); - Py_XDECREF(expr_vars); - - expr_vars = PyTuple_New(BLI_listbase_count(&driver_orig->variables)); - PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 1, expr_vars); - - for (dvar = driver_orig->variables.first, i = 0; dvar; dvar = dvar->next) { - PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_FromString(dvar->name)); - } - - driver_orig->flag &= ~DRIVER_FLAG_RENAMEVAR; - } - else { - expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1); - } - - /* add target values to a dict that will be used as '__locals__' dict */ - driver_vars = _PyDict_NewPresized(PyTuple_GET_SIZE(expr_vars)); - for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) { - PyObject *driver_arg = NULL; - - /* support for any RNA data */ + } + else { + expr_code = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 0); + } + + if (driver_orig->flag & DRIVER_FLAG_RENAMEVAR) { + /* may not be set */ + expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1); + Py_XDECREF(expr_vars); + + expr_vars = PyTuple_New(BLI_listbase_count(&driver_orig->variables)); + PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 1, expr_vars); + + for (dvar = driver_orig->variables.first, i = 0; dvar; dvar = dvar->next) { + PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_FromString(dvar->name)); + } + + driver_orig->flag &= ~DRIVER_FLAG_RENAMEVAR; + } + else { + expr_vars = PyTuple_GET_ITEM(((PyObject *)driver_orig->expr_comp), 1); + } + + /* add target values to a dict that will be used as '__locals__' dict */ + driver_vars = _PyDict_NewPresized(PyTuple_GET_SIZE(expr_vars)); + for (dvar = driver->variables.first, i = 0; dvar; dvar = dvar->next) { + PyObject *driver_arg = NULL; + + /* support for any RNA data */ #ifdef USE_RNA_AS_PYOBJECT - if (dvar->type == DVAR_TYPE_SINGLE_PROP) { - driver_arg = pyrna_driver_get_variable_value(driver, &dvar->targets[0]); - - if (driver_arg == NULL) { - driver_arg = PyFloat_FromDouble(0.0); - dvar->curval = 0.0f; - } - else { - /* no need to worry about overflow here, values from RNA are within limits. */ - if (PyFloat_CheckExact(driver_arg)) { - dvar->curval = (float)PyFloat_AsDouble(driver_arg); - } - else if (PyLong_CheckExact(driver_arg)) { - dvar->curval = (float)PyLong_AsLong(driver_arg); - } - else if (PyBool_Check(driver_arg)) { - dvar->curval = (driver_arg == Py_True); - } - else { - dvar->curval = 0.0f; - } - } - } - else + if (dvar->type == DVAR_TYPE_SINGLE_PROP) { + driver_arg = pyrna_driver_get_variable_value(driver, &dvar->targets[0]); + + if (driver_arg == NULL) { + driver_arg = PyFloat_FromDouble(0.0); + dvar->curval = 0.0f; + } + else { + /* no need to worry about overflow here, values from RNA are within limits. */ + if (PyFloat_CheckExact(driver_arg)) { + dvar->curval = (float)PyFloat_AsDouble(driver_arg); + } + else if (PyLong_CheckExact(driver_arg)) { + dvar->curval = (float)PyLong_AsLong(driver_arg); + } + else if (PyBool_Check(driver_arg)) { + dvar->curval = (driver_arg == Py_True); + } + else { + dvar->curval = 0.0f; + } + } + } + else #endif - { - /* try to get variable value */ - float tval = driver_get_variable_value(driver, dvar); - driver_arg = PyFloat_FromDouble((double)tval); - } - - /* try to add to dictionary */ - /* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */ - if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) != -1) { - Py_DECREF(driver_arg); - } - else { - /* this target failed - bad name */ - if (targets_ok) { - /* first one - print some extra info for easier identification */ - fprintf(stderr, "\nBPY_driver_eval() - Error while evaluating PyDriver:\n"); - targets_ok = 0; - } - - fprintf(stderr, "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", dvar->name); - // BPy_errors_to_report(NULL); // TODO - reports - PyErr_Print(); - PyErr_Clear(); - } - } + { + /* try to get variable value */ + float tval = driver_get_variable_value(driver, dvar); + driver_arg = PyFloat_FromDouble((double)tval); + } + + /* try to add to dictionary */ + /* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */ + if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) != -1) { + Py_DECREF(driver_arg); + } + else { + /* this target failed - bad name */ + if (targets_ok) { + /* first one - print some extra info for easier identification */ + fprintf(stderr, "\nBPY_driver_eval() - Error while evaluating PyDriver:\n"); + targets_ok = 0; + } + + fprintf( + stderr, "\tBPY_driver_eval() - couldn't add variable '%s' to namespace\n", dvar->name); + // BPy_errors_to_report(NULL); // TODO - reports + PyErr_Print(); + PyErr_Clear(); + } + } #ifdef USE_BYTECODE_WHITELIST - if (is_recompile && expr_code) { - if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) { - if (!bpy_driver_secure_bytecode_validate( - expr_code, (PyObject *[]){ - bpy_pydriver_Dict, - bpy_pydriver_Dict__whitelist, - driver_vars, - NULL,} - )) - { - if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) { - G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL; - BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", expr); - } - - Py_DECREF(expr_code); - expr_code = NULL; - PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, NULL); - } - } - } -#endif /* USE_BYTECODE_WHITELIST */ - -#if 0 /* slow, with this can avoid all Py_CompileString above. */ - /* execute expression to get a value */ - retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars); + if (is_recompile && expr_code) { + if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) { + if (!bpy_driver_secure_bytecode_validate(expr_code, + (PyObject *[]){ + bpy_pydriver_Dict, + bpy_pydriver_Dict__whitelist, + driver_vars, + NULL, + })) { + if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) { + G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL; + BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Driver '%s'", expr); + } + + Py_DECREF(expr_code); + expr_code = NULL; + PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, NULL); + } + } + } +#endif /* USE_BYTECODE_WHITELIST */ + +#if 0 /* slow, with this can avoid all Py_CompileString above. */ + /* execute expression to get a value */ + retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars); #else - /* evaluate the compiled expression */ - if (expr_code) { - retval = PyEval_EvalCode((void *)expr_code, bpy_pydriver_Dict, driver_vars); - } + /* evaluate the compiled expression */ + if (expr_code) { + retval = PyEval_EvalCode((void *)expr_code, bpy_pydriver_Dict, driver_vars); + } #endif - /* decref the driver vars first... */ - Py_DECREF(driver_vars); - - /* process the result */ - if (retval == NULL) { - pydriver_error(driver); - } - else if ((result = PyFloat_AsDouble(retval)) == -1.0 && PyErr_Occurred()) { - pydriver_error(driver); - Py_DECREF(retval); - result = 0.0; - } - else { - /* all fine, make sure the "invalid expression" flag is cleared */ - driver->flag &= ~DRIVER_FLAG_INVALID; - Py_DECREF(retval); - } - - if (use_gil) { - PyGILState_Release(gilstate); - } - - if (isfinite(result)) { - return (float)result; - } - else { - fprintf(stderr, "\tBPY_driver_eval() - driver '%s' evaluates to '%f'\n", driver->expression, result); - return 0.0f; - } + /* decref the driver vars first... */ + Py_DECREF(driver_vars); + + /* process the result */ + if (retval == NULL) { + pydriver_error(driver); + } + else if ((result = PyFloat_AsDouble(retval)) == -1.0 && PyErr_Occurred()) { + pydriver_error(driver); + Py_DECREF(retval); + result = 0.0; + } + else { + /* all fine, make sure the "invalid expression" flag is cleared */ + driver->flag &= ~DRIVER_FLAG_INVALID; + Py_DECREF(retval); + } + + if (use_gil) { + PyGILState_Release(gilstate); + } + + if (isfinite(result)) { + return (float)result; + } + else { + fprintf(stderr, + "\tBPY_driver_eval() - driver '%s' evaluates to '%f'\n", + driver->expression, + result); + return 0.0f; + } } diff --git a/source/blender/python/intern/bpy_driver.h b/source/blender/python/intern/bpy_driver.h index 4026a9f2abf..c77815c7e0e 100644 --- a/source/blender/python/intern/bpy_driver.h +++ b/source/blender/python/intern/bpy_driver.h @@ -24,4 +24,4 @@ int bpy_pydriver_create_dict(void); extern PyObject *bpy_pydriver_Dict; -#endif /* __BPY_DRIVER_H__ */ +#endif /* __BPY_DRIVER_H__ */ diff --git a/source/blender/python/intern/bpy_gizmo_wrap.c b/source/blender/python/intern/bpy_gizmo_wrap.c index f1281344bcf..41ff630753f 100644 --- a/source/blender/python/intern/bpy_gizmo_wrap.c +++ b/source/blender/python/intern/bpy_gizmo_wrap.c @@ -39,7 +39,7 @@ #include "bpy_rna.h" #include "bpy_intern_string.h" -#include "bpy_gizmo_wrap.h" /* own include */ +#include "bpy_gizmo_wrap.h" /* own include */ /* we may want to add, but not now */ @@ -47,176 +47,168 @@ /** \name Gizmo * \{ */ - -static bool bpy_gizmotype_target_property_def( - wmGizmoType *gzt, PyObject *item) +static bool bpy_gizmotype_target_property_def(wmGizmoType *gzt, PyObject *item) { - /* Note: names based on 'rna_rna.c' */ - PyObject *empty_tuple = PyTuple_New(0); - - struct { - char *id; - char *type_id; int type; - int array_length; - } params = { - .id = NULL, /* not optional */ - .type = PROP_FLOAT, - .type_id = NULL, - .array_length = 1, - }; - - static const char * const _keywords[] = {"id", "type", "array_length", NULL}; - static _PyArg_Parser _parser = {"|$ssi:register_class", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - empty_tuple, item, - &_parser, - ¶ms.id, - ¶ms.type_id, - ¶ms.array_length)) - { - goto fail; - } - - if (params.id == NULL) { - PyErr_SetString(PyExc_ValueError, "'id' argument not given"); - goto fail; - } - - if ((params.type_id != NULL) && - pyrna_enum_value_from_id( - rna_enum_property_type_items, params.type_id, ¶ms.type, "'type' enum value") == -1) - { - goto fail; - } - else { - params.type = rna_enum_property_type_items[params.type].value; - } - - if ((params.array_length < 1 || params.array_length > RNA_MAX_ARRAY_LENGTH)) { - PyErr_SetString(PyExc_ValueError, "'array_length' out of range"); - goto fail; - } - - WM_gizmotype_target_property_def(gzt, params.id, params.type, params.array_length); - Py_DECREF(empty_tuple); - return true; + /* Note: names based on 'rna_rna.c' */ + PyObject *empty_tuple = PyTuple_New(0); + + struct { + char *id; + char *type_id; + int type; + int array_length; + } params = { + .id = NULL, /* not optional */ + .type = PROP_FLOAT, + .type_id = NULL, + .array_length = 1, + }; + + static const char *const _keywords[] = {"id", "type", "array_length", NULL}; + static _PyArg_Parser _parser = {"|$ssi:register_class", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast( + empty_tuple, item, &_parser, ¶ms.id, ¶ms.type_id, ¶ms.array_length)) { + goto fail; + } + + if (params.id == NULL) { + PyErr_SetString(PyExc_ValueError, "'id' argument not given"); + goto fail; + } + + if ((params.type_id != NULL) && + pyrna_enum_value_from_id( + rna_enum_property_type_items, params.type_id, ¶ms.type, "'type' enum value") == -1) { + goto fail; + } + else { + params.type = rna_enum_property_type_items[params.type].value; + } + + if ((params.array_length < 1 || params.array_length > RNA_MAX_ARRAY_LENGTH)) { + PyErr_SetString(PyExc_ValueError, "'array_length' out of range"); + goto fail; + } + + WM_gizmotype_target_property_def(gzt, params.id, params.type, params.array_length); + Py_DECREF(empty_tuple); + return true; fail: - Py_DECREF(empty_tuple); - return false; + Py_DECREF(empty_tuple); + return false; } static void gizmo_properties_init(wmGizmoType *gzt) { - PyTypeObject *py_class = gzt->ext.data; - RNA_struct_blender_type_set(gzt->ext.srna, gzt); - - /* only call this so pyrna_deferred_register_class gives a useful error - * WM_operatortype_append_ptr will call RNA_def_struct_identifier - * later */ - RNA_def_struct_identifier_no_struct_map(gzt->srna, gzt->idname); - - if (pyrna_deferred_register_class(gzt->srna, py_class) != 0) { - PyErr_Print(); /* failed to register operator props */ - PyErr_Clear(); - } - - /* Extract target property definitions from 'bl_target_properties' */ - { - /* picky developers will notice that 'bl_targets' won't work with inheritance - * get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */ - PyObject *py_class_dict = py_class->tp_dict; - PyObject *bl_target_properties = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_target_properties); - - /* Some widgets may only exist to activate operators. */ - if (bl_target_properties != NULL) { - PyObject *bl_target_properties_fast; - if (!(bl_target_properties_fast = PySequence_Fast( - bl_target_properties, "bl_target_properties sequence"))) - { - /* PySequence_Fast sets the error */ - PyErr_Print(); - PyErr_Clear(); - return; - } - - const uint items_len = PySequence_Fast_GET_SIZE(bl_target_properties_fast); - PyObject **items = PySequence_Fast_ITEMS(bl_target_properties_fast); - - for (uint i = 0; i < items_len; i++) { - if (!bpy_gizmotype_target_property_def(gzt, items[i])) { - PyErr_Print(); - PyErr_Clear(); - break; - } - } - - Py_DECREF(bl_target_properties_fast); - } - } + PyTypeObject *py_class = gzt->ext.data; + RNA_struct_blender_type_set(gzt->ext.srna, gzt); + + /* only call this so pyrna_deferred_register_class gives a useful error + * WM_operatortype_append_ptr will call RNA_def_struct_identifier + * later */ + RNA_def_struct_identifier_no_struct_map(gzt->srna, gzt->idname); + + if (pyrna_deferred_register_class(gzt->srna, py_class) != 0) { + PyErr_Print(); /* failed to register operator props */ + PyErr_Clear(); + } + + /* Extract target property definitions from 'bl_target_properties' */ + { + /* picky developers will notice that 'bl_targets' won't work with inheritance + * get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */ + PyObject *py_class_dict = py_class->tp_dict; + PyObject *bl_target_properties = PyDict_GetItem(py_class_dict, + bpy_intern_str_bl_target_properties); + + /* Some widgets may only exist to activate operators. */ + if (bl_target_properties != NULL) { + PyObject *bl_target_properties_fast; + if (!(bl_target_properties_fast = PySequence_Fast(bl_target_properties, + "bl_target_properties sequence"))) { + /* PySequence_Fast sets the error */ + PyErr_Print(); + PyErr_Clear(); + return; + } + + const uint items_len = PySequence_Fast_GET_SIZE(bl_target_properties_fast); + PyObject **items = PySequence_Fast_ITEMS(bl_target_properties_fast); + + for (uint i = 0; i < items_len; i++) { + if (!bpy_gizmotype_target_property_def(gzt, items[i])) { + PyErr_Print(); + PyErr_Clear(); + break; + } + } + + Py_DECREF(bl_target_properties_fast); + } + } } void BPY_RNA_gizmo_wrapper(wmGizmoType *gzt, void *userdata) { - /* take care not to overwrite anything set in - * WM_gizmomaptype_group_link_ptr before opfunc() is called */ - StructRNA *srna = gzt->srna; - *gzt = *((wmGizmoType *)userdata); - gzt->srna = srna; /* restore */ + /* take care not to overwrite anything set in + * WM_gizmomaptype_group_link_ptr before opfunc() is called */ + StructRNA *srna = gzt->srna; + *gzt = *((wmGizmoType *)userdata); + gzt->srna = srna; /* restore */ - /* don't do translations here yet */ + /* don't do translations here yet */ #if 0 - /* Use i18n context from ext.srna if possible (py gizmogroups). */ - if (gt->ext.srna) { - RNA_def_struct_translation_context(gt->srna, RNA_struct_translation_context(gt->ext.srna)); - } + /* Use i18n context from ext.srna if possible (py gizmogroups). */ + if (gt->ext.srna) { + RNA_def_struct_translation_context(gt->srna, RNA_struct_translation_context(gt->ext.srna)); + } #endif - gzt->struct_size = sizeof(wmGizmo); + gzt->struct_size = sizeof(wmGizmo); - gizmo_properties_init(gzt); + gizmo_properties_init(gzt); } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Gizmo Group * \{ */ static void gizmogroup_properties_init(wmGizmoGroupType *gzgt) { - PyTypeObject *py_class = gzgt->ext.data; - RNA_struct_blender_type_set(gzgt->ext.srna, gzgt); - - /* only call this so pyrna_deferred_register_class gives a useful error - * WM_operatortype_append_ptr will call RNA_def_struct_identifier - * later */ - RNA_def_struct_identifier_no_struct_map(gzgt->srna, gzgt->idname); - - if (pyrna_deferred_register_class(gzgt->srna, py_class) != 0) { - PyErr_Print(); /* failed to register operator props */ - PyErr_Clear(); - } + PyTypeObject *py_class = gzgt->ext.data; + RNA_struct_blender_type_set(gzgt->ext.srna, gzgt); + + /* only call this so pyrna_deferred_register_class gives a useful error + * WM_operatortype_append_ptr will call RNA_def_struct_identifier + * later */ + RNA_def_struct_identifier_no_struct_map(gzgt->srna, gzgt->idname); + + if (pyrna_deferred_register_class(gzgt->srna, py_class) != 0) { + PyErr_Print(); /* failed to register operator props */ + PyErr_Clear(); + } } void BPY_RNA_gizmogroup_wrapper(wmGizmoGroupType *gzgt, void *userdata) { - /* take care not to overwrite anything set in - * WM_gizmomaptype_group_link_ptr before opfunc() is called */ - StructRNA *srna = gzgt->srna; - *gzgt = *((wmGizmoGroupType *)userdata); - gzgt->srna = srna; /* restore */ + /* take care not to overwrite anything set in + * WM_gizmomaptype_group_link_ptr before opfunc() is called */ + StructRNA *srna = gzgt->srna; + *gzgt = *((wmGizmoGroupType *)userdata); + gzgt->srna = srna; /* restore */ - /* don't do translations here yet */ + /* don't do translations here yet */ #if 0 - /* Use i18n context from ext.srna if possible (py gizmogroups). */ - if (gzgt->ext.srna) { - RNA_def_struct_translation_context(gzgt->srna, RNA_struct_translation_context(gzgt->ext.srna)); - } + /* Use i18n context from ext.srna if possible (py gizmogroups). */ + if (gzgt->ext.srna) { + RNA_def_struct_translation_context(gzgt->srna, RNA_struct_translation_context(gzgt->ext.srna)); + } #endif - gizmogroup_properties_init(gzgt); + gizmogroup_properties_init(gzgt); } /** \} */ diff --git a/source/blender/python/intern/bpy_gizmo_wrap.h b/source/blender/python/intern/bpy_gizmo_wrap.h index f1e9773e866..d9031282c40 100644 --- a/source/blender/python/intern/bpy_gizmo_wrap.h +++ b/source/blender/python/intern/bpy_gizmo_wrap.h @@ -28,4 +28,4 @@ struct wmGizmoType; void BPY_RNA_gizmo_wrapper(struct wmGizmoType *gzt, void *userdata); void BPY_RNA_gizmogroup_wrapper(struct wmGizmoGroupType *gzgt, void *userdata); -#endif /* __BPY_GIZMO_WRAP_H__ */ +#endif /* __BPY_GIZMO_WRAP_H__ */ diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 61ddf46d896..1b36ded884d 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -63,7 +63,7 @@ #include "BPY_extern.h" -#include "../generic/bpy_internal_import.h" /* our own imports */ +#include "../generic/bpy_internal_import.h" /* our own imports */ #include "../generic/py_capi_utils.h" /* inittab initialization functions */ @@ -87,118 +87,116 @@ static int py_call_level = 0; // #define TIME_PY_RUN // simple python tests. prints on exit. #ifdef TIME_PY_RUN -#include "PIL_time.h" -static int bpy_timer_count = 0; -static double bpy_timer; /* time since python starts */ -static double bpy_timer_run; /* time for each python script run */ -static double bpy_timer_run_tot; /* accumulate python runs */ +# include "PIL_time.h" +static int bpy_timer_count = 0; +static double bpy_timer; /* time since python starts */ +static double bpy_timer_run; /* time for each python script run */ +static double bpy_timer_run_tot; /* accumulate python runs */ #endif /* use for updating while a python script runs - in case of file load */ void BPY_context_update(bContext *C) { - /* don't do this from a non-main (e.g. render) thread, it can cause a race - * condition on C->data.recursion. ideal solution would be to disable - * context entirely from non-main threads, but that's more complicated */ - if (!BLI_thread_is_main()) { - return; - } - - BPy_SetContext(C); - bpy_import_main_set(CTX_data_main(C)); - BPY_modules_update(C); /* can give really bad results if this isn't here */ + /* don't do this from a non-main (e.g. render) thread, it can cause a race + * condition on C->data.recursion. ideal solution would be to disable + * context entirely from non-main threads, but that's more complicated */ + if (!BLI_thread_is_main()) { + return; + } + + BPy_SetContext(C); + bpy_import_main_set(CTX_data_main(C)); + BPY_modules_update(C); /* can give really bad results if this isn't here */ } void bpy_context_set(bContext *C, PyGILState_STATE *gilstate) { - py_call_level++; + py_call_level++; - if (gilstate) { - *gilstate = PyGILState_Ensure(); - } + if (gilstate) { + *gilstate = PyGILState_Ensure(); + } - if (py_call_level == 1) { - BPY_context_update(C); + if (py_call_level == 1) { + BPY_context_update(C); #ifdef TIME_PY_RUN - if (bpy_timer_count == 0) { - /* record time from the beginning */ - bpy_timer = PIL_check_seconds_timer(); - bpy_timer_run = bpy_timer_run_tot = 0.0; - } - bpy_timer_run = PIL_check_seconds_timer(); - - - bpy_timer_count++; + if (bpy_timer_count == 0) { + /* record time from the beginning */ + bpy_timer = PIL_check_seconds_timer(); + bpy_timer_run = bpy_timer_run_tot = 0.0; + } + bpy_timer_run = PIL_check_seconds_timer(); + + bpy_timer_count++; #endif - } + } } /* context should be used but not now because it causes some bugs */ void bpy_context_clear(bContext *UNUSED(C), PyGILState_STATE *gilstate) { - py_call_level--; - - if (gilstate) { - PyGILState_Release(*gilstate); - } - - if (py_call_level < 0) { - fprintf(stderr, "ERROR: Python context internal state bug. this should not happen!\n"); - } - else if (py_call_level == 0) { - /* XXX - Calling classes currently wont store the context :\, - * cant set NULL because of this. but this is very flakey still. */ + py_call_level--; + + if (gilstate) { + PyGILState_Release(*gilstate); + } + + if (py_call_level < 0) { + fprintf(stderr, "ERROR: Python context internal state bug. this should not happen!\n"); + } + else if (py_call_level == 0) { + /* XXX - Calling classes currently wont store the context :\, + * cant set NULL because of this. but this is very flakey still. */ #if 0 - BPy_SetContext(NULL); - bpy_import_main_set(NULL); + BPy_SetContext(NULL); + bpy_import_main_set(NULL); #endif #ifdef TIME_PY_RUN - bpy_timer_run_tot += PIL_check_seconds_timer() - bpy_timer_run; - bpy_timer_count++; + bpy_timer_run_tot += PIL_check_seconds_timer() - bpy_timer_run; + bpy_timer_count++; #endif - - } + } } void BPY_text_free_code(Text *text) { - if (text->compiled) { - PyGILState_STATE gilstate; - bool use_gil = !PyC_IsInterpreterActive(); + if (text->compiled) { + PyGILState_STATE gilstate; + bool use_gil = !PyC_IsInterpreterActive(); - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - Py_DECREF((PyObject *)text->compiled); - text->compiled = NULL; + Py_DECREF((PyObject *)text->compiled); + text->compiled = NULL; - if (use_gil) { - PyGILState_Release(gilstate); - } - } + if (use_gil) { + PyGILState_Release(gilstate); + } + } } void BPY_modules_update(bContext *C) { -#if 0 /* slow, this runs all the time poll, draw etc 100's of time a sec. */ - PyObject *mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0); - PyModule_AddObject(mod, "data", BPY_rna_module()); - PyModule_AddObject(mod, "types", BPY_rna_types()); /* atm this does not need updating */ +#if 0 /* slow, this runs all the time poll, draw etc 100's of time a sec. */ + PyObject *mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0); + PyModule_AddObject(mod, "data", BPY_rna_module()); + PyModule_AddObject(mod, "types", BPY_rna_types()); /* atm this does not need updating */ #endif - /* refreshes the main struct */ - BPY_update_rna_module(); - if (bpy_context_module) { - bpy_context_module->ptr.data = (void *)C; - } + /* refreshes the main struct */ + BPY_update_rna_module(); + if (bpy_context_module) { + bpy_context_module->ptr.data = (void *)C; + } } void BPY_context_set(bContext *C) { - BPy_SetContext(C); + BPy_SetContext(C); } /* defined in AUD_C-API.cpp */ @@ -208,214 +206,213 @@ extern PyObject *AUD_initPython(void); /* defined in cycles module */ static PyObject *CCL_initPython(void) { - return (PyObject *)CCL_python_module_init(); + return (PyObject *)CCL_python_module_init(); } #endif static struct _inittab bpy_internal_modules[] = { - {"mathutils", PyInit_mathutils}, + {"mathutils", PyInit_mathutils}, #if 0 - {"mathutils.geometry", PyInit_mathutils_geometry}, - {"mathutils.noise", PyInit_mathutils_noise}, - {"mathutils.kdtree", PyInit_mathutils_kdtree}, + {"mathutils.geometry", PyInit_mathutils_geometry}, + {"mathutils.noise", PyInit_mathutils_noise}, + {"mathutils.kdtree", PyInit_mathutils_kdtree}, #endif - {"_bpy_path", BPyInit__bpy_path}, - {"bgl", BPyInit_bgl}, - {"blf", BPyInit_blf}, - {"imbuf", BPyInit_imbuf}, - {"bmesh", BPyInit_bmesh}, + {"_bpy_path", BPyInit__bpy_path}, + {"bgl", BPyInit_bgl}, + {"blf", BPyInit_blf}, + {"imbuf", BPyInit_imbuf}, + {"bmesh", BPyInit_bmesh}, #if 0 - {"bmesh.types", BPyInit_bmesh_types}, - {"bmesh.utils", BPyInit_bmesh_utils}, - {"bmesh.utils", BPyInit_bmesh_geometry}, + {"bmesh.types", BPyInit_bmesh_types}, + {"bmesh.utils", BPyInit_bmesh_utils}, + {"bmesh.utils", BPyInit_bmesh_geometry}, #endif #ifdef WITH_AUDASPACE - {"aud", AUD_initPython}, + {"aud", AUD_initPython}, #endif #ifdef WITH_CYCLES - {"_cycles", CCL_initPython}, + {"_cycles", CCL_initPython}, #endif - {"gpu", BPyInit_gpu}, - {"idprop", BPyInit_idprop}, - {NULL, NULL}, + {"gpu", BPyInit_gpu}, + {"idprop", BPyInit_idprop}, + {NULL, NULL}, }; /* call BPY_context_set first */ void BPY_python_start(int argc, const char **argv) { #ifndef WITH_PYTHON_MODULE - PyThreadState *py_tstate = NULL; - const char *py_path_bundle = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, NULL); - - /* not essential but nice to set our name */ - static wchar_t program_path_wchar[FILE_MAX]; /* python holds a reference */ - BLI_strncpy_wchar_from_utf8(program_path_wchar, BKE_appdir_program_path(), ARRAY_SIZE(program_path_wchar)); - Py_SetProgramName(program_path_wchar); - - /* must run before python initializes */ - PyImport_ExtendInittab(bpy_internal_modules); - - /* allow to use our own included python */ - PyC_SetHomePath(py_path_bundle); - - /* without this the sys.stdout may be set to 'ascii' - * (it is on my system at least), where printing unicode values will raise - * an error, this is highly annoying, another stumbling block for devs, - * so use a more relaxed error handler and enforce utf-8 since the rest of - * blender is utf-8 too - campbell */ - Py_SetStandardStreamEncoding("utf-8", "surrogateescape"); - - /* Update, Py3.3 resolves attempting to parse non-existing header */ -#if 0 - /* Python 3.2 now looks for '2.xx/python/include/python3.2d/pyconfig.h' to - * parse from the 'sysconfig' module which is used by 'site', - * so for now disable site. alternatively we could copy the file. */ - if (py_path_bundle) { - Py_NoSiteFlag = 1; - } -#endif - - Py_FrozenFlag = 1; - - Py_Initialize(); - - // PySys_SetArgv(argc, argv); /* broken in py3, not a huge deal */ - /* sigh, why do python guys not have a (char **) version anymore? */ - { - int i; - PyObject *py_argv = PyList_New(argc); - for (i = 0; i < argc; i++) { - /* should fix bug #20021 - utf path name problems, by replacing - * PyUnicode_FromString, with this one */ - PyList_SET_ITEM(py_argv, i, PyC_UnicodeFromByte(argv[i])); - } - - PySys_SetObject("argv", py_argv); - Py_DECREF(py_argv); - } - - /* Initialize thread support (also acquires lock) */ - PyEval_InitThreads(); + PyThreadState *py_tstate = NULL; + const char *py_path_bundle = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, NULL); + + /* not essential but nice to set our name */ + static wchar_t program_path_wchar[FILE_MAX]; /* python holds a reference */ + BLI_strncpy_wchar_from_utf8( + program_path_wchar, BKE_appdir_program_path(), ARRAY_SIZE(program_path_wchar)); + Py_SetProgramName(program_path_wchar); + + /* must run before python initializes */ + PyImport_ExtendInittab(bpy_internal_modules); + + /* allow to use our own included python */ + PyC_SetHomePath(py_path_bundle); + + /* without this the sys.stdout may be set to 'ascii' + * (it is on my system at least), where printing unicode values will raise + * an error, this is highly annoying, another stumbling block for devs, + * so use a more relaxed error handler and enforce utf-8 since the rest of + * blender is utf-8 too - campbell */ + Py_SetStandardStreamEncoding("utf-8", "surrogateescape"); + + /* Update, Py3.3 resolves attempting to parse non-existing header */ +# if 0 + /* Python 3.2 now looks for '2.xx/python/include/python3.2d/pyconfig.h' to + * parse from the 'sysconfig' module which is used by 'site', + * so for now disable site. alternatively we could copy the file. */ + if (py_path_bundle) { + Py_NoSiteFlag = 1; + } +# endif + + Py_FrozenFlag = 1; + + Py_Initialize(); + + // PySys_SetArgv(argc, argv); /* broken in py3, not a huge deal */ + /* sigh, why do python guys not have a (char **) version anymore? */ + { + int i; + PyObject *py_argv = PyList_New(argc); + for (i = 0; i < argc; i++) { + /* should fix bug #20021 - utf path name problems, by replacing + * PyUnicode_FromString, with this one */ + PyList_SET_ITEM(py_argv, i, PyC_UnicodeFromByte(argv[i])); + } + + PySys_SetObject("argv", py_argv); + Py_DECREF(py_argv); + } + + /* Initialize thread support (also acquires lock) */ + PyEval_InitThreads(); #else - (void)argc; - (void)argv; + (void)argc; + (void)argv; - /* must run before python initializes */ - /* broken in py3.3, load explicitly below */ - // PyImport_ExtendInittab(bpy_internal_modules); + /* must run before python initializes */ + /* broken in py3.3, load explicitly below */ + // PyImport_ExtendInittab(bpy_internal_modules); #endif - bpy_intern_string_init(); - + bpy_intern_string_init(); #ifdef WITH_PYTHON_MODULE - { - /* Manually load all modules */ - struct _inittab *inittab_item; - PyObject *sys_modules = PyImport_GetModuleDict(); - - for (inittab_item = bpy_internal_modules; inittab_item->name; inittab_item++) { - PyObject *mod = inittab_item->initfunc(); - if (mod) { - PyDict_SetItemString(sys_modules, inittab_item->name, mod); - } - else { - PyErr_Print(); - PyErr_Clear(); - } - // Py_DECREF(mod); /* ideally would decref, but in this case we never want to free */ - } - } + { + /* Manually load all modules */ + struct _inittab *inittab_item; + PyObject *sys_modules = PyImport_GetModuleDict(); + + for (inittab_item = bpy_internal_modules; inittab_item->name; inittab_item++) { + PyObject *mod = inittab_item->initfunc(); + if (mod) { + PyDict_SetItemString(sys_modules, inittab_item->name, mod); + } + else { + PyErr_Print(); + PyErr_Clear(); + } + // Py_DECREF(mod); /* ideally would decref, but in this case we never want to free */ + } + } #endif - /* bpy.* and lets us import it */ - BPy_init_modules(); + /* bpy.* and lets us import it */ + BPy_init_modules(); - bpy_import_init(PyEval_GetBuiltins()); + bpy_import_init(PyEval_GetBuiltins()); - pyrna_alloc_types(); + pyrna_alloc_types(); #ifndef WITH_PYTHON_MODULE - /* py module runs atexit when bpy is freed */ - BPY_atexit_register(); /* this can init any time */ + /* py module runs atexit when bpy is freed */ + BPY_atexit_register(); /* this can init any time */ - py_tstate = PyGILState_GetThisThreadState(); - PyEval_ReleaseThread(py_tstate); + py_tstate = PyGILState_GetThisThreadState(); + PyEval_ReleaseThread(py_tstate); #endif } void BPY_python_end(void) { - // fprintf(stderr, "Ending Python!\n"); - PyGILState_STATE gilstate; + // fprintf(stderr, "Ending Python!\n"); + PyGILState_STATE gilstate; - /* finalizing, no need to grab the state, except when we are a module */ - gilstate = PyGILState_Ensure(); + /* finalizing, no need to grab the state, except when we are a module */ + gilstate = PyGILState_Ensure(); - /* free other python data. */ - pyrna_free_types(); + /* free other python data. */ + pyrna_free_types(); - /* clear all python data from structs */ + /* clear all python data from structs */ - bpy_intern_string_exit(); + bpy_intern_string_exit(); - /* bpy.app modules that need cleanup */ - BPY_app_translations_end(); + /* bpy.app modules that need cleanup */ + BPY_app_translations_end(); #ifndef WITH_PYTHON_MODULE - BPY_atexit_unregister(); /* without this we get recursive calls to WM_exit */ + BPY_atexit_unregister(); /* without this we get recursive calls to WM_exit */ - Py_Finalize(); + Py_Finalize(); - (void)gilstate; + (void)gilstate; #else - PyGILState_Release(gilstate); + PyGILState_Release(gilstate); #endif #ifdef TIME_PY_RUN - /* measure time since py started */ - bpy_timer = PIL_check_seconds_timer() - bpy_timer; + /* measure time since py started */ + bpy_timer = PIL_check_seconds_timer() - bpy_timer; - printf("*bpy stats* - "); - printf("tot exec: %d, ", bpy_timer_count); - printf("tot run: %.4fsec, ", bpy_timer_run_tot); - if (bpy_timer_count > 0) { - printf("average run: %.6fsec, ", (bpy_timer_run_tot / bpy_timer_count)); - } + printf("*bpy stats* - "); + printf("tot exec: %d, ", bpy_timer_count); + printf("tot run: %.4fsec, ", bpy_timer_run_tot); + if (bpy_timer_count > 0) { + printf("average run: %.6fsec, ", (bpy_timer_run_tot / bpy_timer_count)); + } - if (bpy_timer > 0.0) { - printf("tot usage %.4f%%", (bpy_timer_run_tot / bpy_timer) * 100.0); - } + if (bpy_timer > 0.0) { + printf("tot usage %.4f%%", (bpy_timer_run_tot / bpy_timer) * 100.0); + } - printf("\n"); + printf("\n"); - // fprintf(stderr, "Ending Python Done!\n"); + // fprintf(stderr, "Ending Python Done!\n"); #endif - } void BPY_python_reset(bContext *C) { - /* unrelated security stuff */ - G.f &= ~(G_FLAG_SCRIPT_AUTOEXEC_FAIL | G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET); - G.autoexec_fail[0] = '\0'; + /* unrelated security stuff */ + G.f &= ~(G_FLAG_SCRIPT_AUTOEXEC_FAIL | G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET); + G.autoexec_fail[0] = '\0'; - BPY_driver_reset(); - BPY_app_handlers_reset(false); - BPY_modules_load_user(C); + BPY_driver_reset(); + BPY_app_handlers_reset(false); + BPY_modules_load_user(C); } static void python_script_error_jump_text(struct Text *text) { - int lineno; - int offset; - python_script_error_jump(text->id.name + 2, &lineno, &offset); - if (lineno != -1) { - /* select the line with the error */ - txt_move_to(text, lineno - 1, INT_MAX, false); - txt_move_to(text, lineno - 1, offset, true); - } + int lineno; + int offset; + python_script_error_jump(text->id.name + 2, &lineno, &offset); + if (lineno != -1) { + /* select the line with the error */ + txt_move_to(text, lineno - 1, INT_MAX, false); + txt_move_to(text, lineno - 1, offset, true); + } } /* super annoying, undo _PyModule_Clear(), bug [#23871] */ @@ -425,240 +422,236 @@ static void python_script_error_jump_text(struct Text *text) /* bad!, we should never do this, but currently only safe way I could find to keep namespace. * from being cleared. - campbell */ typedef struct { - PyObject_HEAD - PyObject *md_dict; - /* omit other values, we only want the dict. */ + PyObject_HEAD PyObject *md_dict; + /* omit other values, we only want the dict. */ } PyModuleObject; #endif static bool python_script_exec( - bContext *C, const char *fn, struct Text *text, - struct ReportList *reports, const bool do_jump) + bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const bool do_jump) { - Main *bmain_old = CTX_data_main(C); - PyObject *main_mod = NULL; - PyObject *py_dict = NULL, *py_result = NULL; - PyGILState_STATE gilstate; - - BLI_assert(fn || text); + Main *bmain_old = CTX_data_main(C); + PyObject *main_mod = NULL; + PyObject *py_dict = NULL, *py_result = NULL; + PyGILState_STATE gilstate; - if (fn == NULL && text == NULL) { - return 0; - } + BLI_assert(fn || text); - bpy_context_set(C, &gilstate); + if (fn == NULL && text == NULL) { + return 0; + } - PyC_MainModule_Backup(&main_mod); + bpy_context_set(C, &gilstate); - if (text) { - char fn_dummy[FILE_MAXDIR]; - bpy_text_filename_get(fn_dummy, sizeof(fn_dummy), text); + PyC_MainModule_Backup(&main_mod); - if (text->compiled == NULL) { /* if it wasn't already compiled, do it now */ - char *buf; - PyObject *fn_dummy_py; + if (text) { + char fn_dummy[FILE_MAXDIR]; + bpy_text_filename_get(fn_dummy, sizeof(fn_dummy), text); - fn_dummy_py = PyC_UnicodeFromByte(fn_dummy); + if (text->compiled == NULL) { /* if it wasn't already compiled, do it now */ + char *buf; + PyObject *fn_dummy_py; - buf = txt_to_buf(text); - text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1); - MEM_freeN(buf); + fn_dummy_py = PyC_UnicodeFromByte(fn_dummy); - Py_DECREF(fn_dummy_py); + buf = txt_to_buf(text); + text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1); + MEM_freeN(buf); - if (PyErr_Occurred()) { - if (do_jump) { - python_script_error_jump_text(text); - } - BPY_text_free_code(text); - } - } + Py_DECREF(fn_dummy_py); - if (text->compiled) { - py_dict = PyC_DefaultNameSpace(fn_dummy); - py_result = PyEval_EvalCode(text->compiled, py_dict, py_dict); - } + if (PyErr_Occurred()) { + if (do_jump) { + python_script_error_jump_text(text); + } + BPY_text_free_code(text); + } + } - } - else { - FILE *fp = BLI_fopen(fn, "r"); + if (text->compiled) { + py_dict = PyC_DefaultNameSpace(fn_dummy); + py_result = PyEval_EvalCode(text->compiled, py_dict, py_dict); + } + } + else { + FILE *fp = BLI_fopen(fn, "r"); - if (fp) { - py_dict = PyC_DefaultNameSpace(fn); + if (fp) { + py_dict = PyC_DefaultNameSpace(fn); #ifdef _WIN32 - /* Previously we used PyRun_File to run directly the code on a FILE - * object, but as written in the Python/C API Ref Manual, chapter 2, - * 'FILE structs for different C libraries can be different and - * incompatible'. - * So now we load the script file data to a buffer. - * - * Note on use of 'globals()', it's important not copy the dictionary because - * tools may inspect 'sys.modules["__main__"]' for variables defined in the code - * where using a copy of 'globals()' causes code execution - * to leave the main namespace untouched. see: T51444 - * - * This leaves us with the problem of variables being included, - * currently this is worked around using 'dict.__del__' it's ugly but works. - */ - { - const char *pystring = - "with open(__file__, 'rb') as f:" - "exec(compile(f.read(), __file__, 'exec'), globals().__delitem__('f') or globals())"; - - fclose(fp); - - py_result = PyRun_String(pystring, Py_file_input, py_dict, py_dict); - } + /* Previously we used PyRun_File to run directly the code on a FILE + * object, but as written in the Python/C API Ref Manual, chapter 2, + * 'FILE structs for different C libraries can be different and + * incompatible'. + * So now we load the script file data to a buffer. + * + * Note on use of 'globals()', it's important not copy the dictionary because + * tools may inspect 'sys.modules["__main__"]' for variables defined in the code + * where using a copy of 'globals()' causes code execution + * to leave the main namespace untouched. see: T51444 + * + * This leaves us with the problem of variables being included, + * currently this is worked around using 'dict.__del__' it's ugly but works. + */ + { + const char *pystring = + "with open(__file__, 'rb') as f:" + "exec(compile(f.read(), __file__, 'exec'), globals().__delitem__('f') or globals())"; + + fclose(fp); + + py_result = PyRun_String(pystring, Py_file_input, py_dict, py_dict); + } #else - py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict); - fclose(fp); + py_result = PyRun_File(fp, fn, Py_file_input, py_dict, py_dict); + fclose(fp); #endif - } - else { - PyErr_Format(PyExc_IOError, - "Python file \"%s\" could not be opened: %s", - fn, strerror(errno)); - py_result = NULL; - } - } - - if (!py_result) { - if (text) { - if (do_jump) { - /* ensure text is valid before use, the script may have freed its self */ - Main *bmain_new = CTX_data_main(C); - if ((bmain_old == bmain_new) && (BLI_findindex(&bmain_new->texts, text) != -1)) { - python_script_error_jump_text(text); - } - } - } - BPy_errors_to_report(reports); - } - else { - Py_DECREF(py_result); - } - - if (py_dict) { + } + else { + PyErr_Format( + PyExc_IOError, "Python file \"%s\" could not be opened: %s", fn, strerror(errno)); + py_result = NULL; + } + } + + if (!py_result) { + if (text) { + if (do_jump) { + /* ensure text is valid before use, the script may have freed its self */ + Main *bmain_new = CTX_data_main(C); + if ((bmain_old == bmain_new) && (BLI_findindex(&bmain_new->texts, text) != -1)) { + python_script_error_jump_text(text); + } + } + } + BPy_errors_to_report(reports); + } + else { + Py_DECREF(py_result); + } + + if (py_dict) { #ifdef PYMODULE_CLEAR_WORKAROUND - PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItem( - PyImport_GetModuleDict(), bpy_intern_str___main__); - PyObject *dict_back = mmod->md_dict; - /* freeing the module will clear the namespace, - * gives problems running classes defined in this namespace being used later. */ - mmod->md_dict = NULL; - Py_DECREF(dict_back); + PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItem(PyImport_GetModuleDict(), + bpy_intern_str___main__); + PyObject *dict_back = mmod->md_dict; + /* freeing the module will clear the namespace, + * gives problems running classes defined in this namespace being used later. */ + mmod->md_dict = NULL; + Py_DECREF(dict_back); #endif #undef PYMODULE_CLEAR_WORKAROUND - } + } - PyC_MainModule_Restore(main_mod); + PyC_MainModule_Restore(main_mod); - bpy_context_clear(C, &gilstate); + bpy_context_clear(C, &gilstate); - return (py_result != NULL); + return (py_result != NULL); } /* Can run a file or text block */ bool BPY_execute_filepath(bContext *C, const char *filepath, struct ReportList *reports) { - return python_script_exec(C, filepath, NULL, reports, false); + return python_script_exec(C, filepath, NULL, reports, false); } - -bool BPY_execute_text(bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump) +bool BPY_execute_text(bContext *C, + struct Text *text, + struct ReportList *reports, + const bool do_jump) { - return python_script_exec(C, NULL, text, reports, do_jump); + return python_script_exec(C, NULL, text, reports, do_jump); } void BPY_DECREF(void *pyob_ptr) { - PyGILState_STATE gilstate = PyGILState_Ensure(); - Py_DECREF((PyObject *)pyob_ptr); - PyGILState_Release(gilstate); + PyGILState_STATE gilstate = PyGILState_Ensure(); + Py_DECREF((PyObject *)pyob_ptr); + PyGILState_Release(gilstate); } void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr) { - PyGILState_STATE gilstate = PyGILState_Ensure(); - const int do_invalidate = (Py_REFCNT((PyObject *)pyob_ptr) > 1); - Py_DECREF((PyObject *)pyob_ptr); - if (do_invalidate) { - pyrna_invalidate(pyob_ptr); - } - PyGILState_Release(gilstate); + PyGILState_STATE gilstate = PyGILState_Ensure(); + const int do_invalidate = (Py_REFCNT((PyObject *)pyob_ptr) > 1); + Py_DECREF((PyObject *)pyob_ptr); + if (do_invalidate) { + pyrna_invalidate(pyob_ptr); + } + PyGILState_Release(gilstate); } /** * \return success */ bool BPY_execute_string_as_number( - bContext *C, const char *imports[], - const char *expr, const bool verbose, double *r_value) + bContext *C, const char *imports[], const char *expr, const bool verbose, double *r_value) { - PyGILState_STATE gilstate; - bool ok = true; + PyGILState_STATE gilstate; + bool ok = true; - if (!r_value || !expr) { - return -1; - } + if (!r_value || !expr) { + return -1; + } - if (expr[0] == '\0') { - *r_value = 0.0; - return ok; - } + if (expr[0] == '\0') { + *r_value = 0.0; + return ok; + } - bpy_context_set(C, &gilstate); + bpy_context_set(C, &gilstate); - ok = PyC_RunString_AsNumber(imports, expr, "<expr as number>", r_value); + ok = PyC_RunString_AsNumber(imports, expr, "<expr as number>", r_value); - if (ok == false) { - if (verbose) { - BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); - } - else { - PyErr_Clear(); - } - } + if (ok == false) { + if (verbose) { + BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); + } + else { + PyErr_Clear(); + } + } - bpy_context_clear(C, &gilstate); + bpy_context_clear(C, &gilstate); - return ok; + return ok; } /** * \return success */ bool BPY_execute_string_as_string( - bContext *C, const char *imports[], - const char *expr, const bool verbose, char **r_value) + bContext *C, const char *imports[], const char *expr, const bool verbose, char **r_value) { - BLI_assert(r_value && expr); - PyGILState_STATE gilstate; - bool ok = true; + BLI_assert(r_value && expr); + PyGILState_STATE gilstate; + bool ok = true; - if (expr[0] == '\0') { - *r_value = NULL; - return ok; - } + if (expr[0] == '\0') { + *r_value = NULL; + return ok; + } - bpy_context_set(C, &gilstate); + bpy_context_set(C, &gilstate); - ok = PyC_RunString_AsString(imports, expr, "<expr as str>", r_value); + ok = PyC_RunString_AsString(imports, expr, "<expr as str>", r_value); - if (ok == false) { - if (verbose) { - BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); - } - else { - PyErr_Clear(); - } - } + if (ok == false) { + if (verbose) { + BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); + } + else { + PyErr_Clear(); + } + } - bpy_context_clear(C, &gilstate); + bpy_context_clear(C, &gilstate); - return ok; + return ok; } /** @@ -667,226 +660,225 @@ bool BPY_execute_string_as_string( * \return success */ bool BPY_execute_string_as_intptr( - bContext *C, const char *imports[], - const char *expr, const bool verbose, intptr_t *r_value) + bContext *C, const char *imports[], const char *expr, const bool verbose, intptr_t *r_value) { - BLI_assert(r_value && expr); - PyGILState_STATE gilstate; - bool ok = true; + BLI_assert(r_value && expr); + PyGILState_STATE gilstate; + bool ok = true; - if (expr[0] == '\0') { - *r_value = 0; - return ok; - } + if (expr[0] == '\0') { + *r_value = 0; + return ok; + } - bpy_context_set(C, &gilstate); + bpy_context_set(C, &gilstate); - ok = PyC_RunString_AsIntPtr(imports, expr, "<expr as intptr>", r_value); + ok = PyC_RunString_AsIntPtr(imports, expr, "<expr as intptr>", r_value); - if (ok == false) { - if (verbose) { - BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); - } - else { - PyErr_Clear(); - } - } + if (ok == false) { + if (verbose) { + BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); + } + else { + PyErr_Clear(); + } + } - bpy_context_clear(C, &gilstate); + bpy_context_clear(C, &gilstate); - return ok; + return ok; } -bool BPY_execute_string_ex( - bContext *C, const char *imports[], - const char *expr, bool use_eval) +bool BPY_execute_string_ex(bContext *C, const char *imports[], const char *expr, bool use_eval) { - BLI_assert(expr); - PyGILState_STATE gilstate; - PyObject *main_mod = NULL; - PyObject *py_dict, *retval; - bool ok = true; - Main *bmain_back; /* XXX, quick fix for release (Copy Settings crash), needs further investigation */ + BLI_assert(expr); + PyGILState_STATE gilstate; + PyObject *main_mod = NULL; + PyObject *py_dict, *retval; + bool ok = true; + Main * + bmain_back; /* XXX, quick fix for release (Copy Settings crash), needs further investigation */ - if (expr[0] == '\0') { - return ok; - } + if (expr[0] == '\0') { + return ok; + } - bpy_context_set(C, &gilstate); + bpy_context_set(C, &gilstate); - PyC_MainModule_Backup(&main_mod); + PyC_MainModule_Backup(&main_mod); - py_dict = PyC_DefaultNameSpace("<blender string>"); + py_dict = PyC_DefaultNameSpace("<blender string>"); - bmain_back = bpy_import_main_get(); - bpy_import_main_set(CTX_data_main(C)); + bmain_back = bpy_import_main_get(); + bpy_import_main_set(CTX_data_main(C)); - if (imports && (!PyC_NameSpace_ImportArray(py_dict, imports))) { - Py_DECREF(py_dict); - retval = NULL; - } - else { - retval = PyRun_String(expr, use_eval ? Py_eval_input : Py_file_input, py_dict, py_dict); - } + if (imports && (!PyC_NameSpace_ImportArray(py_dict, imports))) { + Py_DECREF(py_dict); + retval = NULL; + } + else { + retval = PyRun_String(expr, use_eval ? Py_eval_input : Py_file_input, py_dict, py_dict); + } - bpy_import_main_set(bmain_back); + bpy_import_main_set(bmain_back); - if (retval == NULL) { - ok = false; - BPy_errors_to_report(CTX_wm_reports(C)); - } - else { - Py_DECREF(retval); - } + if (retval == NULL) { + ok = false; + BPy_errors_to_report(CTX_wm_reports(C)); + } + else { + Py_DECREF(retval); + } - PyC_MainModule_Restore(main_mod); + PyC_MainModule_Restore(main_mod); - bpy_context_clear(C, &gilstate); + bpy_context_clear(C, &gilstate); - return ok; + return ok; } -bool BPY_execute_string( - bContext *C, const char *imports[], - const char *expr) +bool BPY_execute_string(bContext *C, const char *imports[], const char *expr) { - return BPY_execute_string_ex(C, imports, expr, true); + return BPY_execute_string_ex(C, imports, expr, true); } void BPY_modules_load_user(bContext *C) { - PyGILState_STATE gilstate; - Main *bmain = CTX_data_main(C); - Text *text; - - /* can happen on file load */ - if (bmain == NULL) { - return; - } - - /* update pointers since this can run from a nested script - * on file load */ - if (py_call_level) { - BPY_context_update(C); - } - - bpy_context_set(C, &gilstate); - - for (text = bmain->texts.first; text; text = text->id.next) { - if (text->flags & TXT_ISSCRIPT && BLI_path_extension_check(text->id.name + 2, ".py")) { - if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) { - if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) { - G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL; - BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Text '%s'", text->id.name + 2); - - printf("scripts disabled for \"%s\", skipping '%s'\n", BKE_main_blendfile_path(bmain), text->id.name + 2); - } - } - else { - PyObject *module = bpy_text_import(text); - - if (module == NULL) { - PyErr_Print(); - PyErr_Clear(); - } - else { - Py_DECREF(module); - } - - /* check if the script loaded a new file */ - if (bmain != CTX_data_main(C)) { - break; - } - } - } - } - bpy_context_clear(C, &gilstate); + PyGILState_STATE gilstate; + Main *bmain = CTX_data_main(C); + Text *text; + + /* can happen on file load */ + if (bmain == NULL) { + return; + } + + /* update pointers since this can run from a nested script + * on file load */ + if (py_call_level) { + BPY_context_update(C); + } + + bpy_context_set(C, &gilstate); + + for (text = bmain->texts.first; text; text = text->id.next) { + if (text->flags & TXT_ISSCRIPT && BLI_path_extension_check(text->id.name + 2, ".py")) { + if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC)) { + if (!(G.f & G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET)) { + G.f |= G_FLAG_SCRIPT_AUTOEXEC_FAIL; + BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Text '%s'", text->id.name + 2); + + printf("scripts disabled for \"%s\", skipping '%s'\n", + BKE_main_blendfile_path(bmain), + text->id.name + 2); + } + } + else { + PyObject *module = bpy_text_import(text); + + if (module == NULL) { + PyErr_Print(); + PyErr_Clear(); + } + else { + Py_DECREF(module); + } + + /* check if the script loaded a new file */ + if (bmain != CTX_data_main(C)) { + break; + } + } + } + } + bpy_context_clear(C, &gilstate); } int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *result) { - PyGILState_STATE gilstate; - bool use_gil = !PyC_IsInterpreterActive(); - - PyObject *pyctx; - PyObject *item; - PointerRNA *ptr = NULL; - bool done = false; - - if (use_gil) { - gilstate = PyGILState_Ensure(); - } - - pyctx = (PyObject *)CTX_py_dict_get(C); - item = PyDict_GetItemString(pyctx, member); - - if (item == NULL) { - /* pass */ - } - else if (item == Py_None) { - done = true; - } - else if (BPy_StructRNA_Check(item)) { - ptr = &(((BPy_StructRNA *)item)->ptr); - - //result->ptr = ((BPy_StructRNA *)item)->ptr; - CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data); - CTX_data_type_set(result, CTX_DATA_TYPE_POINTER); - done = true; - } - else if (PySequence_Check(item)) { - PyObject *seq_fast = PySequence_Fast(item, "bpy_context_get sequence conversion"); - if (seq_fast == NULL) { - PyErr_Print(); - PyErr_Clear(); - } - else { - int len = PySequence_Fast_GET_SIZE(seq_fast); - PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast); - int i; - - for (i = 0; i < len; i++) { - PyObject *list_item = seq_fast_items[i]; - - if (BPy_StructRNA_Check(list_item)) { + PyGILState_STATE gilstate; + bool use_gil = !PyC_IsInterpreterActive(); + + PyObject *pyctx; + PyObject *item; + PointerRNA *ptr = NULL; + bool done = false; + + if (use_gil) { + gilstate = PyGILState_Ensure(); + } + + pyctx = (PyObject *)CTX_py_dict_get(C); + item = PyDict_GetItemString(pyctx, member); + + if (item == NULL) { + /* pass */ + } + else if (item == Py_None) { + done = true; + } + else if (BPy_StructRNA_Check(item)) { + ptr = &(((BPy_StructRNA *)item)->ptr); + + //result->ptr = ((BPy_StructRNA *)item)->ptr; + CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data); + CTX_data_type_set(result, CTX_DATA_TYPE_POINTER); + done = true; + } + else if (PySequence_Check(item)) { + PyObject *seq_fast = PySequence_Fast(item, "bpy_context_get sequence conversion"); + if (seq_fast == NULL) { + PyErr_Print(); + PyErr_Clear(); + } + else { + int len = PySequence_Fast_GET_SIZE(seq_fast); + PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast); + int i; + + for (i = 0; i < len; i++) { + PyObject *list_item = seq_fast_items[i]; + + if (BPy_StructRNA_Check(list_item)) { #if 0 - CollectionPointerLink *link = MEM_callocN(sizeof(CollectionPointerLink), "bpy_context_get"); - link->ptr = ((BPy_StructRNA *)item)->ptr; - BLI_addtail(&result->list, link); + CollectionPointerLink *link = MEM_callocN(sizeof(CollectionPointerLink), "bpy_context_get"); + link->ptr = ((BPy_StructRNA *)item)->ptr; + BLI_addtail(&result->list, link); #endif - ptr = &(((BPy_StructRNA *)list_item)->ptr); - CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data); - } - else { - CLOG_INFO(BPY_LOG_CONTEXT, 1, - "'%s' list item not a valid type in sequence type '%s'", - member, Py_TYPE(item)->tp_name); - } - - } - Py_DECREF(seq_fast); - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - done = true; - } - } - - if (done == false) { - if (item) { - CLOG_INFO(BPY_LOG_CONTEXT, 1, "'%s' not a valid type", member); - } - else { - CLOG_INFO(BPY_LOG_CONTEXT, 1, "'%s' not found\n", member); - } - } - else { - CLOG_INFO(BPY_LOG_CONTEXT, 2, "'%s' found", member); - } - - if (use_gil) { - PyGILState_Release(gilstate); - } - - return done; + ptr = &(((BPy_StructRNA *)list_item)->ptr); + CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data); + } + else { + CLOG_INFO(BPY_LOG_CONTEXT, + 1, + "'%s' list item not a valid type in sequence type '%s'", + member, + Py_TYPE(item)->tp_name); + } + } + Py_DECREF(seq_fast); + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + done = true; + } + } + + if (done == false) { + if (item) { + CLOG_INFO(BPY_LOG_CONTEXT, 1, "'%s' not a valid type", member); + } + else { + CLOG_INFO(BPY_LOG_CONTEXT, 1, "'%s' not found\n", member); + } + } + else { + CLOG_INFO(BPY_LOG_CONTEXT, 2, "'%s' found", member); + } + + if (use_gil) { + PyGILState_Release(gilstate); + } + + return done; } #ifdef WITH_PYTHON_MODULE @@ -896,48 +888,48 @@ static void bpy_module_free(void *mod); extern int main_python_enter(int argc, const char **argv); extern void main_python_exit(void); static struct PyModuleDef bpy_proxy_def = { - PyModuleDef_HEAD_INIT, - "bpy", /* m_name */ - NULL, /* m_doc */ - 0, /* m_size */ - NULL, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - bpy_module_free, /* m_free */ + PyModuleDef_HEAD_INIT, + "bpy", /* m_name */ + NULL, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + bpy_module_free, /* m_free */ }; typedef struct { - PyObject_HEAD - /* Type-specific fields go here. */ - PyObject *mod; + PyObject_HEAD + /* Type-specific fields go here. */ + PyObject *mod; } dealloc_obj; /* call once __file__ is set */ static void bpy_module_delay_init(PyObject *bpy_proxy) { - const int argc = 1; - const char *argv[2]; + const int argc = 1; + const char *argv[2]; - /* updating the module dict below will loose the reference to __file__ */ - PyObject *filename_obj = PyModule_GetFilenameObject(bpy_proxy); + /* updating the module dict below will loose the reference to __file__ */ + PyObject *filename_obj = PyModule_GetFilenameObject(bpy_proxy); - const char *filename_rel = _PyUnicode_AsString(filename_obj); /* can be relative */ - char filename_abs[1024]; + const char *filename_rel = _PyUnicode_AsString(filename_obj); /* can be relative */ + char filename_abs[1024]; - BLI_strncpy(filename_abs, filename_rel, sizeof(filename_abs)); - BLI_path_cwd(filename_abs, sizeof(filename_abs)); - Py_DECREF(filename_obj); + BLI_strncpy(filename_abs, filename_rel, sizeof(filename_abs)); + BLI_path_cwd(filename_abs, sizeof(filename_abs)); + Py_DECREF(filename_obj); - argv[0] = filename_abs; - argv[1] = NULL; + argv[0] = filename_abs; + argv[1] = NULL; - // printf("module found %s\n", argv[0]); + // printf("module found %s\n", argv[0]); - main_python_enter(argc, argv); + main_python_enter(argc, argv); - /* initialized in BPy_init_modules() */ - PyDict_Update(PyModule_GetDict(bpy_proxy), PyModule_GetDict(bpy_package_py)); + /* initialized in BPy_init_modules() */ + PyDict_Update(PyModule_GetDict(bpy_proxy), PyModule_GetDict(bpy_package_py)); } static void dealloc_obj_dealloc(PyObject *self); @@ -947,57 +939,55 @@ static PyTypeObject dealloc_obj_Type; /* use our own dealloc so we can free a property if we use one */ static void dealloc_obj_dealloc(PyObject *self) { - bpy_module_delay_init(((dealloc_obj *)self)->mod); + bpy_module_delay_init(((dealloc_obj *)self)->mod); - /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ - dealloc_obj_Type.tp_free(self); + /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ + dealloc_obj_Type.tp_free(self); } -PyMODINIT_FUNC -PyInit_bpy(void); +PyMODINIT_FUNC PyInit_bpy(void); -PyMODINIT_FUNC -PyInit_bpy(void) +PyMODINIT_FUNC PyInit_bpy(void) { - PyObject *bpy_proxy = PyModule_Create(&bpy_proxy_def); - - /* Problem: - * 1) this init function is expected to have a private member defined - 'md_def' - * but this is only set for C defined modules (not py packages) - * so we cant return 'bpy_package_py' as is. - * - * 2) there is a 'bpy' C module for python to load which is basically all of blender, - * and there is scripts/bpy/__init__.py, - * we may end up having to rename this module so there is no naming conflict here eg: - * 'from blender import bpy' - * - * 3) we don't know the filename at this point, workaround by assigning a dummy value - * which calls back when its freed so the real loading can take place. - */ - - /* assign an object which is freed after __file__ is assigned */ - dealloc_obj *dob; - - /* assign dummy type */ - dealloc_obj_Type.tp_name = "dealloc_obj"; - dealloc_obj_Type.tp_basicsize = sizeof(dealloc_obj); - dealloc_obj_Type.tp_dealloc = dealloc_obj_dealloc; - dealloc_obj_Type.tp_flags = Py_TPFLAGS_DEFAULT; - - if (PyType_Ready(&dealloc_obj_Type) < 0) { - return NULL; - } - - dob = (dealloc_obj *) dealloc_obj_Type.tp_alloc(&dealloc_obj_Type, 0); - dob->mod = bpy_proxy; /* borrow */ - PyModule_AddObject(bpy_proxy, "__file__", (PyObject *)dob); /* borrow */ - - return bpy_proxy; + PyObject *bpy_proxy = PyModule_Create(&bpy_proxy_def); + + /* Problem: + * 1) this init function is expected to have a private member defined - 'md_def' + * but this is only set for C defined modules (not py packages) + * so we cant return 'bpy_package_py' as is. + * + * 2) there is a 'bpy' C module for python to load which is basically all of blender, + * and there is scripts/bpy/__init__.py, + * we may end up having to rename this module so there is no naming conflict here eg: + * 'from blender import bpy' + * + * 3) we don't know the filename at this point, workaround by assigning a dummy value + * which calls back when its freed so the real loading can take place. + */ + + /* assign an object which is freed after __file__ is assigned */ + dealloc_obj *dob; + + /* assign dummy type */ + dealloc_obj_Type.tp_name = "dealloc_obj"; + dealloc_obj_Type.tp_basicsize = sizeof(dealloc_obj); + dealloc_obj_Type.tp_dealloc = dealloc_obj_dealloc; + dealloc_obj_Type.tp_flags = Py_TPFLAGS_DEFAULT; + + if (PyType_Ready(&dealloc_obj_Type) < 0) { + return NULL; + } + + dob = (dealloc_obj *)dealloc_obj_Type.tp_alloc(&dealloc_obj_Type, 0); + dob->mod = bpy_proxy; /* borrow */ + PyModule_AddObject(bpy_proxy, "__file__", (PyObject *)dob); /* borrow */ + + return bpy_proxy; } static void bpy_module_free(void *UNUSED(mod)) { - main_python_exit(); + main_python_exit(); } #endif @@ -1007,36 +997,33 @@ static void bpy_module_free(void *UNUSED(mod)) */ bool BPY_string_is_keyword(const char *str) { - /* list is from... - * ", ".join(['"%s"' % kw for kw in __import__("keyword").kwlist]) - */ - const char *kwlist[] = { - "False", "None", "True", - "and", "as", "assert", "async", "await", "break", - "class", "continue", "def", "del", "elif", "else", "except", - "finally", "for", "from", "global", "if", "import", "in", - "is", "lambda", "nonlocal", "not", "or", "pass", "raise", - "return", "try", "while", "with", "yield", NULL, - }; - - for (int i = 0; kwlist[i]; i++) { - if (STREQ(str, kwlist[i])) { - return true; - } - } - - return false; + /* list is from... + * ", ".join(['"%s"' % kw for kw in __import__("keyword").kwlist]) + */ + const char *kwlist[] = { + "False", "None", "True", "and", "as", "assert", "async", "await", "break", + "class", "continue", "def", "del", "elif", "else", "except", "finally", "for", + "from", "global", "if", "import", "in", "is", "lambda", "nonlocal", "not", + "or", "pass", "raise", "return", "try", "while", "with", "yield", NULL, + }; + + for (int i = 0; kwlist[i]; i++) { + if (STREQ(str, kwlist[i])) { + return true; + } + } + + return false; } - /* EVIL, define text.c functions here... */ /* BKE_text.h */ int text_check_identifier_unicode(const unsigned int ch) { - return (ch < 255 && text_check_identifier((char)ch)) || Py_UNICODE_ISALNUM(ch); + return (ch < 255 && text_check_identifier((char)ch)) || Py_UNICODE_ISALNUM(ch); } int text_check_identifier_nodigit_unicode(const unsigned int ch) { - return (ch < 255 && text_check_identifier_nodigit((char)ch)) || Py_UNICODE_ISALPHA(ch); + return (ch < 255 && text_check_identifier_nodigit((char)ch)) || Py_UNICODE_ISALPHA(ch); } diff --git a/source/blender/python/intern/bpy_interface_atexit.c b/source/blender/python/intern/bpy_interface_atexit.c index a7aab0e72f4..cb79a1f7f93 100644 --- a/source/blender/python/intern/bpy_interface_atexit.c +++ b/source/blender/python/intern/bpy_interface_atexit.c @@ -22,24 +22,23 @@ * resources. */ - #include <Python.h> #include "BLI_utildefines.h" #include "bpy_capi_utils.h" -#include "bpy.h" /* own include */ +#include "bpy.h" /* own include */ #include "WM_api.h" static PyObject *bpy_atexit(PyObject *UNUSED(self), PyObject *UNUSED(args), PyObject *UNUSED(kw)) { - /* close down enough of blender at least not to crash */ - struct bContext *C = BPy_GetContext(); + /* close down enough of blender at least not to crash */ + struct bContext *C = BPy_GetContext(); - WM_exit_ext(C, 0); + WM_exit_ext(C, 0); - Py_RETURN_NONE; + Py_RETURN_NONE; } static PyMethodDef meth_bpy_atexit = {"bpy_atexit", (PyCFunction)bpy_atexit, METH_NOARGS, NULL}; @@ -47,45 +46,45 @@ static PyObject *func_bpy_atregister = NULL; /* borrowed referebce, atexit holds static void atexit_func_call(const char *func_name, PyObject *atexit_func_arg) { - /* note - no error checking, if any of these fail we'll get a crash - * this is intended, but if its problematic it could be changed - * - campbell */ - - PyObject *atexit_mod = PyImport_ImportModuleLevel("atexit", NULL, NULL, NULL, 0); - PyObject *atexit_func = PyObject_GetAttrString(atexit_mod, func_name); - PyObject *args = PyTuple_New(1); - PyObject *ret; - - PyTuple_SET_ITEM(args, 0, atexit_func_arg); - Py_INCREF(atexit_func_arg); /* only incref so we don't dec'ref along with 'args' */ - - ret = PyObject_CallObject(atexit_func, args); - - Py_DECREF(atexit_mod); - Py_DECREF(atexit_func); - Py_DECREF(args); - - if (ret) { - Py_DECREF(ret); - } - else { /* should never happen */ - PyErr_Print(); - } + /* note - no error checking, if any of these fail we'll get a crash + * this is intended, but if its problematic it could be changed + * - campbell */ + + PyObject *atexit_mod = PyImport_ImportModuleLevel("atexit", NULL, NULL, NULL, 0); + PyObject *atexit_func = PyObject_GetAttrString(atexit_mod, func_name); + PyObject *args = PyTuple_New(1); + PyObject *ret; + + PyTuple_SET_ITEM(args, 0, atexit_func_arg); + Py_INCREF(atexit_func_arg); /* only incref so we don't dec'ref along with 'args' */ + + ret = PyObject_CallObject(atexit_func, args); + + Py_DECREF(atexit_mod); + Py_DECREF(atexit_func); + Py_DECREF(args); + + if (ret) { + Py_DECREF(ret); + } + else { /* should never happen */ + PyErr_Print(); + } } void BPY_atexit_register(void) { - /* atexit module owns this new function reference */ - BLI_assert(func_bpy_atregister == NULL); + /* atexit module owns this new function reference */ + BLI_assert(func_bpy_atregister == NULL); - func_bpy_atregister = (PyObject *)PyCFunction_New(&meth_bpy_atexit, NULL); - atexit_func_call("register", func_bpy_atregister); + func_bpy_atregister = (PyObject *)PyCFunction_New(&meth_bpy_atexit, NULL); + atexit_func_call("register", func_bpy_atregister); } void BPY_atexit_unregister(void) { - BLI_assert(func_bpy_atregister != NULL); + BLI_assert(func_bpy_atregister != NULL); - atexit_func_call("unregister", func_bpy_atregister); - func_bpy_atregister = NULL; /* don't really need to set but just in case */ + atexit_func_call("unregister", func_bpy_atregister); + func_bpy_atregister = NULL; /* don't really need to set but just in case */ } diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c index 334aa49c0bf..141f03c22aa 100644 --- a/source/blender/python/intern/bpy_intern_string.c +++ b/source/blender/python/intern/bpy_intern_string.c @@ -49,37 +49,40 @@ PyObject *bpy_intern_str_unregister; void bpy_intern_string_init(void) { - unsigned int i = 0; + unsigned int i = 0; #define BPY_INTERN_STR(var, str) \ - { var = bpy_intern_str_arr[i++] = PyUnicode_FromString(str); } (void)0 + { \ + var = bpy_intern_str_arr[i++] = PyUnicode_FromString(str); \ + } \ + (void)0 - BPY_INTERN_STR(bpy_intern_str___annotations__, "__annotations__"); - BPY_INTERN_STR(bpy_intern_str___doc__, "__doc__"); - BPY_INTERN_STR(bpy_intern_str___main__, "__main__"); - BPY_INTERN_STR(bpy_intern_str___module__, "__module__"); - BPY_INTERN_STR(bpy_intern_str___name__, "__name__"); - BPY_INTERN_STR(bpy_intern_str___slots__, "__slots__"); - BPY_INTERN_STR(bpy_intern_str_attr, "attr"); - BPY_INTERN_STR(bpy_intern_str_bl_property, "bl_property"); - BPY_INTERN_STR(bpy_intern_str_bl_rna, "bl_rna"); - BPY_INTERN_STR(bpy_intern_str_bl_target_properties, "bl_target_properties"); - BPY_INTERN_STR(bpy_intern_str_bpy_types, "bpy.types"); - BPY_INTERN_STR(bpy_intern_str_frame, "frame"); - BPY_INTERN_STR(bpy_intern_str_properties, "properties"); - BPY_INTERN_STR(bpy_intern_str_register, "register"); - BPY_INTERN_STR(bpy_intern_str_self, "self"); - BPY_INTERN_STR(bpy_intern_str_unregister, "unregister"); + BPY_INTERN_STR(bpy_intern_str___annotations__, "__annotations__"); + BPY_INTERN_STR(bpy_intern_str___doc__, "__doc__"); + BPY_INTERN_STR(bpy_intern_str___main__, "__main__"); + BPY_INTERN_STR(bpy_intern_str___module__, "__module__"); + BPY_INTERN_STR(bpy_intern_str___name__, "__name__"); + BPY_INTERN_STR(bpy_intern_str___slots__, "__slots__"); + BPY_INTERN_STR(bpy_intern_str_attr, "attr"); + BPY_INTERN_STR(bpy_intern_str_bl_property, "bl_property"); + BPY_INTERN_STR(bpy_intern_str_bl_rna, "bl_rna"); + BPY_INTERN_STR(bpy_intern_str_bl_target_properties, "bl_target_properties"); + BPY_INTERN_STR(bpy_intern_str_bpy_types, "bpy.types"); + BPY_INTERN_STR(bpy_intern_str_frame, "frame"); + BPY_INTERN_STR(bpy_intern_str_properties, "properties"); + BPY_INTERN_STR(bpy_intern_str_register, "register"); + BPY_INTERN_STR(bpy_intern_str_self, "self"); + BPY_INTERN_STR(bpy_intern_str_unregister, "unregister"); #undef BPY_INTERN_STR - BLI_assert(i == ARRAY_SIZE(bpy_intern_str_arr)); + BLI_assert(i == ARRAY_SIZE(bpy_intern_str_arr)); } void bpy_intern_string_exit(void) { - unsigned int i = ARRAY_SIZE(bpy_intern_str_arr); - while (i--) { - Py_DECREF(bpy_intern_str_arr[i]); - } + unsigned int i = ARRAY_SIZE(bpy_intern_str_arr); + while (i--) { + Py_DECREF(bpy_intern_str_arr[i]); + } } diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h index 362a07904e0..14f9607f3b4 100644 --- a/source/blender/python/intern/bpy_intern_string.h +++ b/source/blender/python/intern/bpy_intern_string.h @@ -41,4 +41,4 @@ extern PyObject *bpy_intern_str_register; extern PyObject *bpy_intern_str_self; extern PyObject *bpy_intern_str_unregister; -#endif /* __BPY_INTERN_STRING_H__ */ +#endif /* __BPY_INTERN_STRING_H__ */ diff --git a/source/blender/python/intern/bpy_library.h b/source/blender/python/intern/bpy_library.h index 7537eb40d19..3fd116d7028 100644 --- a/source/blender/python/intern/bpy_library.h +++ b/source/blender/python/intern/bpy_library.h @@ -24,4 +24,4 @@ int BPY_library_load_module(PyObject *mod_par); int BPY_library_write_module(PyObject *mod_par); -#endif /* __BPY_LIBRARY_H__ */ +#endif /* __BPY_LIBRARY_H__ */ diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index 3a4c70c1873..3de8e49dffd 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -59,13 +59,13 @@ #endif typedef struct { - PyObject_HEAD /* required python macro */ - /* collection iterator specific parts */ - char relpath[FILE_MAX]; - char abspath[FILE_MAX]; /* absolute path */ - BlendHandle *blo_handle; - int flag; - PyObject *dict; + PyObject_HEAD /* required python macro */ + /* collection iterator specific parts */ + char relpath[FILE_MAX]; + char abspath[FILE_MAX]; /* absolute path */ + BlendHandle *blo_handle; + int flag; + PyObject *dict; } BPy_Library; static PyObject *bpy_lib_load(PyObject *self, PyObject *args, PyObject *kwds); @@ -74,411 +74,407 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *args); static PyObject *bpy_lib_dir(BPy_Library *self); static PyMethodDef bpy_lib_methods[] = { - {"__enter__", (PyCFunction)bpy_lib_enter, METH_NOARGS}, - {"__exit__", (PyCFunction)bpy_lib_exit, METH_VARARGS}, - {"__dir__", (PyCFunction)bpy_lib_dir, METH_NOARGS}, - {NULL} /* sentinel */ + {"__enter__", (PyCFunction)bpy_lib_enter, METH_NOARGS}, + {"__exit__", (PyCFunction)bpy_lib_exit, METH_VARARGS}, + {"__dir__", (PyCFunction)bpy_lib_dir, METH_NOARGS}, + {NULL} /* sentinel */ }; static void bpy_lib_dealloc(BPy_Library *self) { - Py_XDECREF(self->dict); - Py_TYPE(self)->tp_free(self); + Py_XDECREF(self->dict); + Py_TYPE(self)->tp_free(self); } - static PyTypeObject bpy_lib_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_lib", /* tp_name */ - sizeof(BPy_Library), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)bpy_lib_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* tp_repr */ - - /* Method suites for standard classes */ - - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - - /* will only use these if this is a subtype of a py class */ - NULL /*PyObject_GenericGetAttr is assigned later */, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons (subclassed) ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ - 0, - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - bpy_lib_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - offsetof(BPy_Library, dict), /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + PyVarObject_HEAD_INIT(NULL, 0) "bpy_lib", /* tp_name */ + sizeof(BPy_Library), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)bpy_lib_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + NULL, /* tp_repr */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + + /* will only use these if this is a subtype of a py class */ + NULL /*PyObject_GenericGetAttr is assigned later */, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons (subclassed) ***/ + NULL, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + bpy_lib_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + offsetof(BPy_Library, dict), /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; -PyDoc_STRVAR(bpy_lib_load_doc, -".. method:: load(filepath, link=False, relative=False)\n" -"\n" -" Returns a context manager which exposes 2 library objects on entering.\n" -" Each object has attributes matching bpy.data which are lists of strings to be linked.\n" -"\n" -" :arg filepath: The path to a blend file.\n" -" :type filepath: string\n" -" :arg link: When False reference to the original file is lost.\n" -" :type link: bool\n" -" :arg relative: When True the path is stored relative to the open blend file.\n" -" :type relative: bool\n" -); +PyDoc_STRVAR( + bpy_lib_load_doc, + ".. method:: load(filepath, link=False, relative=False)\n" + "\n" + " Returns a context manager which exposes 2 library objects on entering.\n" + " Each object has attributes matching bpy.data which are lists of strings to be linked.\n" + "\n" + " :arg filepath: The path to a blend file.\n" + " :type filepath: string\n" + " :arg link: When False reference to the original file is lost.\n" + " :type link: bool\n" + " :arg relative: When True the path is stored relative to the open blend file.\n" + " :type relative: bool\n"); static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - Main *bmain = CTX_data_main(BPy_GetContext()); - BPy_Library *ret; - const char *filename = NULL; - bool is_rel = false, is_link = false; - - static const char *_keywords[] = {"filepath", "link", "relative", NULL}; - static _PyArg_Parser _parser = {"s|O&O&:load", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &filename, - PyC_ParseBool, &is_link, - PyC_ParseBool, &is_rel)) - { - return NULL; - } - - ret = PyObject_New(BPy_Library, &bpy_lib_Type); - - BLI_strncpy(ret->relpath, filename, sizeof(ret->relpath)); - BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath)); - BLI_path_abs(ret->abspath, BKE_main_blendfile_path(bmain)); - - ret->blo_handle = NULL; - ret->flag = ((is_link ? FILE_LINK : 0) | - (is_rel ? FILE_RELPATH : 0)); - - ret->dict = _PyDict_NewPresized(MAX_LIBARRAY); - - return (PyObject *)ret; + Main *bmain = CTX_data_main(BPy_GetContext()); + BPy_Library *ret; + const char *filename = NULL; + bool is_rel = false, is_link = false; + + static const char *_keywords[] = {"filepath", "link", "relative", NULL}; + static _PyArg_Parser _parser = {"s|O&O&:load", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast( + args, kw, &_parser, &filename, PyC_ParseBool, &is_link, PyC_ParseBool, &is_rel)) { + return NULL; + } + + ret = PyObject_New(BPy_Library, &bpy_lib_Type); + + BLI_strncpy(ret->relpath, filename, sizeof(ret->relpath)); + BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath)); + BLI_path_abs(ret->abspath, BKE_main_blendfile_path(bmain)); + + ret->blo_handle = NULL; + ret->flag = ((is_link ? FILE_LINK : 0) | (is_rel ? FILE_RELPATH : 0)); + + ret->dict = _PyDict_NewPresized(MAX_LIBARRAY); + + return (PyObject *)ret; } static PyObject *_bpy_names(BPy_Library *self, int blocktype) { - PyObject *list; - LinkNode *l, *names; - int totnames; - - names = BLO_blendhandle_get_datablock_names(self->blo_handle, blocktype, &totnames); - list = PyList_New(totnames); - - if (names) { - int counter = 0; - for (l = names; l; l = l->next) { - PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link)); - counter++; - } - BLI_linklist_free(names, free); /* free linklist *and* each node's data */ - } - - return list; + PyObject *list; + LinkNode *l, *names; + int totnames; + + names = BLO_blendhandle_get_datablock_names(self->blo_handle, blocktype, &totnames); + list = PyList_New(totnames); + + if (names) { + int counter = 0; + for (l = names; l; l = l->next) { + PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link)); + counter++; + } + BLI_linklist_free(names, free); /* free linklist *and* each node's data */ + } + + return list; } static PyObject *bpy_lib_enter(BPy_Library *self) { - PyObject *ret; - BPy_Library *self_from; - PyObject *from_dict = _PyDict_NewPresized(MAX_LIBARRAY); - ReportList reports; - - BKE_reports_init(&reports, RPT_STORE); - - self->blo_handle = BLO_blendhandle_from_file(self->abspath, &reports); - - if (self->blo_handle == NULL) { - if (BPy_reports_to_error(&reports, PyExc_IOError, true) != -1) { - PyErr_Format(PyExc_IOError, - "load: %s failed to open blend file", - self->abspath); - } - return NULL; - } - else { - int i = 0, code; - while ((code = BKE_idcode_iter_step(&i))) { - if (BKE_idcode_is_linkable(code)) { - const char *name_plural = BKE_idcode_to_name_plural(code); - PyObject *str = PyUnicode_FromString(name_plural); - PyObject *item; - - PyDict_SetItem(self->dict, str, item = PyList_New(0)); - Py_DECREF(item); - PyDict_SetItem(from_dict, str, item = _bpy_names(self, code)); - Py_DECREF(item); - - Py_DECREF(str); - } - } - } - - /* create a dummy */ - self_from = PyObject_New(BPy_Library, &bpy_lib_Type); - BLI_strncpy(self_from->relpath, self->relpath, sizeof(self_from->relpath)); - BLI_strncpy(self_from->abspath, self->abspath, sizeof(self_from->abspath)); - - self_from->blo_handle = NULL; - self_from->flag = 0; - self_from->dict = from_dict; /* owns the dict */ - - /* return pair */ - ret = PyTuple_New(2); - PyTuple_SET_ITEMS(ret, - (PyObject *)self_from, - (PyObject *)self); - Py_INCREF(self); - - BKE_reports_clear(&reports); - - return ret; + PyObject *ret; + BPy_Library *self_from; + PyObject *from_dict = _PyDict_NewPresized(MAX_LIBARRAY); + ReportList reports; + + BKE_reports_init(&reports, RPT_STORE); + + self->blo_handle = BLO_blendhandle_from_file(self->abspath, &reports); + + if (self->blo_handle == NULL) { + if (BPy_reports_to_error(&reports, PyExc_IOError, true) != -1) { + PyErr_Format(PyExc_IOError, "load: %s failed to open blend file", self->abspath); + } + return NULL; + } + else { + int i = 0, code; + while ((code = BKE_idcode_iter_step(&i))) { + if (BKE_idcode_is_linkable(code)) { + const char *name_plural = BKE_idcode_to_name_plural(code); + PyObject *str = PyUnicode_FromString(name_plural); + PyObject *item; + + PyDict_SetItem(self->dict, str, item = PyList_New(0)); + Py_DECREF(item); + PyDict_SetItem(from_dict, str, item = _bpy_names(self, code)); + Py_DECREF(item); + + Py_DECREF(str); + } + } + } + + /* create a dummy */ + self_from = PyObject_New(BPy_Library, &bpy_lib_Type); + BLI_strncpy(self_from->relpath, self->relpath, sizeof(self_from->relpath)); + BLI_strncpy(self_from->abspath, self->abspath, sizeof(self_from->abspath)); + + self_from->blo_handle = NULL; + self_from->flag = 0; + self_from->dict = from_dict; /* owns the dict */ + + /* return pair */ + ret = PyTuple_New(2); + PyTuple_SET_ITEMS(ret, (PyObject *)self_from, (PyObject *)self); + Py_INCREF(self); + + BKE_reports_clear(&reports); + + return ret; } -static void bpy_lib_exit_warn_idname(BPy_Library *self, const char *name_plural, const char *idname) +static void bpy_lib_exit_warn_idname(BPy_Library *self, + const char *name_plural, + const char *idname) { - PyObject *exc, *val, *tb; - PyErr_Fetch(&exc, &val, &tb); - if (PyErr_WarnFormat(PyExc_UserWarning, 1, - "load: '%s' does not contain %s[\"%s\"]", - self->abspath, name_plural, idname)) - { - /* Spurious errors can appear at shutdown */ - if (PyErr_ExceptionMatches(PyExc_Warning)) { - PyErr_WriteUnraisable((PyObject *)self); - } - } - PyErr_Restore(exc, val, tb); + PyObject *exc, *val, *tb; + PyErr_Fetch(&exc, &val, &tb); + if (PyErr_WarnFormat(PyExc_UserWarning, + 1, + "load: '%s' does not contain %s[\"%s\"]", + self->abspath, + name_plural, + idname)) { + /* Spurious errors can appear at shutdown */ + if (PyErr_ExceptionMatches(PyExc_Warning)) { + PyErr_WriteUnraisable((PyObject *)self); + } + } + PyErr_Restore(exc, val, tb); } static void bpy_lib_exit_warn_type(BPy_Library *self, PyObject *item) { - PyObject *exc, *val, *tb; - PyErr_Fetch(&exc, &val, &tb); - if (PyErr_WarnFormat(PyExc_UserWarning, 1, - "load: '%s' expected a string type, not a %.200s", - self->abspath, Py_TYPE(item)->tp_name)) - { - /* Spurious errors can appear at shutdown */ - if (PyErr_ExceptionMatches(PyExc_Warning)) { - PyErr_WriteUnraisable((PyObject *)self); - } - } - PyErr_Restore(exc, val, tb); + PyObject *exc, *val, *tb; + PyErr_Fetch(&exc, &val, &tb); + if (PyErr_WarnFormat(PyExc_UserWarning, + 1, + "load: '%s' expected a string type, not a %.200s", + self->abspath, + Py_TYPE(item)->tp_name)) { + /* Spurious errors can appear at shutdown */ + if (PyErr_ExceptionMatches(PyExc_Warning)) { + PyErr_WriteUnraisable((PyObject *)self); + } + } + PyErr_Restore(exc, val, tb); } static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) { - Main *bmain = CTX_data_main(BPy_GetContext()); - Main *mainl = NULL; - int err = 0; - const bool do_append = ((self->flag & FILE_LINK) == 0); - - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); - - /* here appending/linking starts */ - mainl = BLO_library_link_begin(bmain, &(self->blo_handle), self->relpath); - - { - int idcode_step = 0, idcode; - while ((idcode = BKE_idcode_iter_step(&idcode_step))) { - if (BKE_idcode_is_linkable(idcode) && (idcode != ID_WS || do_append)) { - const char *name_plural = BKE_idcode_to_name_plural(idcode); - PyObject *ls = PyDict_GetItemString(self->dict, name_plural); - // printf("lib: %s\n", name_plural); - if (ls && PyList_Check(ls)) { - /* loop */ - Py_ssize_t size = PyList_GET_SIZE(ls); - Py_ssize_t i; - - for (i = 0; i < size; i++) { - PyObject *item_src = PyList_GET_ITEM(ls, i); - PyObject *item_dst; /* must be set below */ - const char *item_idname = _PyUnicode_AsString(item_src); - - // printf(" %s\n", item_idname); - - if (item_idname) { - ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_idname); - if (id) { + Main *bmain = CTX_data_main(BPy_GetContext()); + Main *mainl = NULL; + int err = 0; + const bool do_append = ((self->flag & FILE_LINK) == 0); + + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); + + /* here appending/linking starts */ + mainl = BLO_library_link_begin(bmain, &(self->blo_handle), self->relpath); + + { + int idcode_step = 0, idcode; + while ((idcode = BKE_idcode_iter_step(&idcode_step))) { + if (BKE_idcode_is_linkable(idcode) && (idcode != ID_WS || do_append)) { + const char *name_plural = BKE_idcode_to_name_plural(idcode); + PyObject *ls = PyDict_GetItemString(self->dict, name_plural); + // printf("lib: %s\n", name_plural); + if (ls && PyList_Check(ls)) { + /* loop */ + Py_ssize_t size = PyList_GET_SIZE(ls); + Py_ssize_t i; + + for (i = 0; i < size; i++) { + PyObject *item_src = PyList_GET_ITEM(ls, i); + PyObject *item_dst; /* must be set below */ + const char *item_idname = _PyUnicode_AsString(item_src); + + // printf(" %s\n", item_idname); + + if (item_idname) { + ID *id = BLO_library_link_named_part( + mainl, &(self->blo_handle), idcode, item_idname); + if (id) { #ifdef USE_RNA_DATABLOCKS - /* swap name for pointer to the id */ - item_dst = PyCapsule_New((void *)id, NULL, NULL); + /* swap name for pointer to the id */ + item_dst = PyCapsule_New((void *)id, NULL, NULL); #else - /* leave as is */ - continue; + /* leave as is */ + continue; #endif - } - else { - bpy_lib_exit_warn_idname(self, name_plural, item_idname); - /* just warn for now */ - /* err = -1; */ - item_dst = Py_INCREF_RET(Py_None); - } - - /* ID or None */ - } - else { - /* XXX, could complain about this */ - bpy_lib_exit_warn_type(self, item_src); - PyErr_Clear(); - item_dst = Py_INCREF_RET(Py_None); - } - - /* item_dst must be new or already incref'd */ - Py_DECREF(item_src); - PyList_SET_ITEM(ls, i, item_dst); - } - } - } - } - } - - if (err == -1) { - /* exception raised above, XXX, this leaks some memory */ - BLO_blendhandle_close(self->blo_handle); - self->blo_handle = NULL; - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); - return NULL; - } - else { - Library *lib = mainl->curlib; /* newly added lib, assign before append end */ - BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL, NULL, NULL); - BLO_blendhandle_close(self->blo_handle); - self->blo_handle = NULL; - - GHash *old_to_new_ids = BLI_ghash_ptr_new(__func__); - - /* copied from wm_operator.c */ - { - /* mark all library linked objects to be updated */ - BKE_main_lib_objects_recalc_all(bmain); - - /* append, rather than linking */ - if (do_append) { - BKE_library_make_local(bmain, lib, old_to_new_ids, true, false); - } - } - - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); - - /* finally swap the capsules for real bpy objects - * important since BLO_library_append_end initializes NodeTree types used by srna->refine */ + } + else { + bpy_lib_exit_warn_idname(self, name_plural, item_idname); + /* just warn for now */ + /* err = -1; */ + item_dst = Py_INCREF_RET(Py_None); + } + + /* ID or None */ + } + else { + /* XXX, could complain about this */ + bpy_lib_exit_warn_type(self, item_src); + PyErr_Clear(); + item_dst = Py_INCREF_RET(Py_None); + } + + /* item_dst must be new or already incref'd */ + Py_DECREF(item_src); + PyList_SET_ITEM(ls, i, item_dst); + } + } + } + } + } + + if (err == -1) { + /* exception raised above, XXX, this leaks some memory */ + BLO_blendhandle_close(self->blo_handle); + self->blo_handle = NULL; + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); + return NULL; + } + else { + Library *lib = mainl->curlib; /* newly added lib, assign before append end */ + BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL, NULL, NULL); + BLO_blendhandle_close(self->blo_handle); + self->blo_handle = NULL; + + GHash *old_to_new_ids = BLI_ghash_ptr_new(__func__); + + /* copied from wm_operator.c */ + { + /* mark all library linked objects to be updated */ + BKE_main_lib_objects_recalc_all(bmain); + + /* append, rather than linking */ + if (do_append) { + BKE_library_make_local(bmain, lib, old_to_new_ids, true, false); + } + } + + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); + + /* finally swap the capsules for real bpy objects + * important since BLO_library_append_end initializes NodeTree types used by srna->refine */ #ifdef USE_RNA_DATABLOCKS - { - int idcode_step = 0, idcode; - while ((idcode = BKE_idcode_iter_step(&idcode_step))) { - if (BKE_idcode_is_linkable(idcode) && (idcode != ID_WS || do_append)) { - const char *name_plural = BKE_idcode_to_name_plural(idcode); - PyObject *ls = PyDict_GetItemString(self->dict, name_plural); - if (ls && PyList_Check(ls)) { - Py_ssize_t size = PyList_GET_SIZE(ls); - Py_ssize_t i; - PyObject *item; - - for (i = 0; i < size; i++) { - item = PyList_GET_ITEM(ls, i); - if (PyCapsule_CheckExact(item)) { - PointerRNA id_ptr; - ID *id; - - id = PyCapsule_GetPointer(item, NULL); - id = BLI_ghash_lookup_default(old_to_new_ids, id, id); - Py_DECREF(item); - - RNA_id_pointer_create(id, &id_ptr); - item = pyrna_struct_CreatePyObject(&id_ptr); - PyList_SET_ITEM(ls, i, item); - } - } - } - } - } - } -#endif /* USE_RNA_DATABLOCKS */ - - BLI_ghash_free(old_to_new_ids, NULL, NULL); - Py_RETURN_NONE; - } + { + int idcode_step = 0, idcode; + while ((idcode = BKE_idcode_iter_step(&idcode_step))) { + if (BKE_idcode_is_linkable(idcode) && (idcode != ID_WS || do_append)) { + const char *name_plural = BKE_idcode_to_name_plural(idcode); + PyObject *ls = PyDict_GetItemString(self->dict, name_plural); + if (ls && PyList_Check(ls)) { + Py_ssize_t size = PyList_GET_SIZE(ls); + Py_ssize_t i; + PyObject *item; + + for (i = 0; i < size; i++) { + item = PyList_GET_ITEM(ls, i); + if (PyCapsule_CheckExact(item)) { + PointerRNA id_ptr; + ID *id; + + id = PyCapsule_GetPointer(item, NULL); + id = BLI_ghash_lookup_default(old_to_new_ids, id, id); + Py_DECREF(item); + + RNA_id_pointer_create(id, &id_ptr); + item = pyrna_struct_CreatePyObject(&id_ptr); + PyList_SET_ITEM(ls, i, item); + } + } + } + } + } + } +#endif /* USE_RNA_DATABLOCKS */ + + BLI_ghash_free(old_to_new_ids, NULL, NULL); + Py_RETURN_NONE; + } } static PyObject *bpy_lib_dir(BPy_Library *self) { - return PyDict_Keys(self->dict); + return PyDict_Keys(self->dict); } - int BPY_library_load_module(PyObject *mod_par) { - static PyMethodDef load_meth = { - "load", (PyCFunction)bpy_lib_load, - METH_STATIC | METH_VARARGS | METH_KEYWORDS, - bpy_lib_load_doc, - }; - PyModule_AddObject(mod_par, "_library_load", PyCFunction_New(&load_meth, NULL)); - - /* some compilers don't like accessing this directly, delay assignment */ - bpy_lib_Type.tp_getattro = PyObject_GenericGetAttr; - - if (PyType_Ready(&bpy_lib_Type) < 0) { - return -1; - } - - return 0; + static PyMethodDef load_meth = { + "load", + (PyCFunction)bpy_lib_load, + METH_STATIC | METH_VARARGS | METH_KEYWORDS, + bpy_lib_load_doc, + }; + PyModule_AddObject(mod_par, "_library_load", PyCFunction_New(&load_meth, NULL)); + + /* some compilers don't like accessing this directly, delay assignment */ + bpy_lib_Type.tp_getattro = PyObject_GenericGetAttr; + + if (PyType_Ready(&bpy_lib_Type) < 0) { + return -1; + } + + return 0; } diff --git a/source/blender/python/intern/bpy_library_write.c b/source/blender/python/intern/bpy_library_write.c index 7b7457bc4b3..a1894b7f000 100644 --- a/source/blender/python/intern/bpy_library_write.c +++ b/source/blender/python/intern/bpy_library_write.c @@ -43,174 +43,177 @@ #include "../generic/py_capi_utils.h" - -PyDoc_STRVAR(bpy_lib_write_doc, -".. method:: write(filepath, datablocks, relative_remap=False, fake_user=False, compress=False)\n" -"\n" -" Write data-blocks into a blend file.\n" -"\n" -" .. note::\n" -"\n" -" Indirectly referenced data-blocks will be expanded and written too.\n" -"\n" -" :arg filepath: The path to write the blend-file.\n" -" :type filepath: string\n" -" :arg datablocks: set of data-blocks (:class:`bpy.types.ID` instances).\n" -" :type datablocks: set\n" -" :arg relative_remap: When True, make paths relative to the current blend-file.\n" -" :type relative_remap: bool\n" -" :arg fake_user: When True, data-blocks will be written with fake-user flag enabled.\n" -" :type fake_user: bool\n" -" :arg compress: When True, write a compressed blend file.\n" -" :type compress: bool\n" -); +PyDoc_STRVAR( + bpy_lib_write_doc, + ".. method:: write(filepath, datablocks, relative_remap=False, fake_user=False, " + "compress=False)\n" + "\n" + " Write data-blocks into a blend file.\n" + "\n" + " .. note::\n" + "\n" + " Indirectly referenced data-blocks will be expanded and written too.\n" + "\n" + " :arg filepath: The path to write the blend-file.\n" + " :type filepath: string\n" + " :arg datablocks: set of data-blocks (:class:`bpy.types.ID` instances).\n" + " :type datablocks: set\n" + " :arg relative_remap: When True, make paths relative to the current blend-file.\n" + " :type relative_remap: bool\n" + " :arg fake_user: When True, data-blocks will be written with fake-user flag enabled.\n" + " :type fake_user: bool\n" + " :arg compress: When True, write a compressed blend file.\n" + " :type compress: bool\n"); static PyObject *bpy_lib_write(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - /* args */ - const char *filepath; - char filepath_abs[FILE_MAX]; - PyObject *datablocks = NULL; - bool use_relative_remap = false, use_fake_user = false, use_compress = false; - - static const char *_keywords[] = { - "filepath", "datablocks", - /* optional */ - "relative_remap", "fake_user", "compress", - NULL, - }; - static _PyArg_Parser _parser = {"sO!|$O&O&O&:write", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &filepath, - &PySet_Type, &datablocks, - PyC_ParseBool, &use_relative_remap, - PyC_ParseBool, &use_fake_user, - PyC_ParseBool, &use_compress)) - { - return NULL; - } - - Main *bmain_src = G_MAIN; - int write_flags = 0; - - if (use_relative_remap) { - write_flags |= G_FILE_RELATIVE_REMAP; - } - - if (use_compress) { - write_flags |= G_FILE_COMPRESS; - } - - BLI_strncpy(filepath_abs, filepath, FILE_MAX); - BLI_path_abs(filepath_abs, BKE_main_blendfile_path_from_global()); - - BKE_blendfile_write_partial_begin(bmain_src); - - /* array of ID's and backup any data we modify */ - struct { - ID *id; - /* original values */ - short id_flag; - short id_us; - } *id_store_array, *id_store; - int id_store_len = 0; - - PyObject *ret; - - /* collect all id data from the set and store in 'id_store_array' */ - { - Py_ssize_t pos, hash; - PyObject *key; - - id_store_array = MEM_mallocN(sizeof(*id_store_array) * PySet_Size(datablocks), __func__); - id_store = id_store_array; - - pos = hash = 0; - while (_PySet_NextEntry(datablocks, &pos, &key, &hash)) { - - if (!pyrna_id_FromPyObject(key, &id_store->id)) { - PyErr_Format(PyExc_TypeError, - "Expected an ID type, not %.200s", - Py_TYPE(key)->tp_name); - ret = NULL; - goto finally; - } - else { - id_store->id_flag = id_store->id->flag; - id_store->id_us = id_store->id->us; - - if (use_fake_user) { - id_store->id->flag |= LIB_FAKEUSER; - } - id_store->id->us = 1; - - BKE_blendfile_write_partial_tag_ID(id_store->id, true); - - id_store_len += 1; - id_store++; - } - } - } - - /* write blend */ - int retval = 0; - ReportList reports; - - BKE_reports_init(&reports, RPT_STORE); - - retval = BKE_blendfile_write_partial(bmain_src, filepath_abs, write_flags, &reports); - - /* cleanup state */ - BKE_blendfile_write_partial_end(bmain_src); - - if (retval) { - BKE_reports_print(&reports, RPT_ERROR_ALL); - BKE_reports_clear(&reports); - ret = Py_None; - Py_INCREF(ret); - } - else { - if (BPy_reports_to_error(&reports, PyExc_IOError, true) == 0) { - PyErr_SetString(PyExc_IOError, "Unknown error writing library data"); - } - ret = NULL; - } - + /* args */ + const char *filepath; + char filepath_abs[FILE_MAX]; + PyObject *datablocks = NULL; + bool use_relative_remap = false, use_fake_user = false, use_compress = false; + + static const char *_keywords[] = { + "filepath", + "datablocks", + /* optional */ + "relative_remap", + "fake_user", + "compress", + NULL, + }; + static _PyArg_Parser _parser = {"sO!|$O&O&O&:write", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &filepath, + &PySet_Type, + &datablocks, + PyC_ParseBool, + &use_relative_remap, + PyC_ParseBool, + &use_fake_user, + PyC_ParseBool, + &use_compress)) { + return NULL; + } + + Main *bmain_src = G_MAIN; + int write_flags = 0; + + if (use_relative_remap) { + write_flags |= G_FILE_RELATIVE_REMAP; + } + + if (use_compress) { + write_flags |= G_FILE_COMPRESS; + } + + BLI_strncpy(filepath_abs, filepath, FILE_MAX); + BLI_path_abs(filepath_abs, BKE_main_blendfile_path_from_global()); + + BKE_blendfile_write_partial_begin(bmain_src); + + /* array of ID's and backup any data we modify */ + struct { + ID *id; + /* original values */ + short id_flag; + short id_us; + } * id_store_array, *id_store; + int id_store_len = 0; + + PyObject *ret; + + /* collect all id data from the set and store in 'id_store_array' */ + { + Py_ssize_t pos, hash; + PyObject *key; + + id_store_array = MEM_mallocN(sizeof(*id_store_array) * PySet_Size(datablocks), __func__); + id_store = id_store_array; + + pos = hash = 0; + while (_PySet_NextEntry(datablocks, &pos, &key, &hash)) { + + if (!pyrna_id_FromPyObject(key, &id_store->id)) { + PyErr_Format(PyExc_TypeError, "Expected an ID type, not %.200s", Py_TYPE(key)->tp_name); + ret = NULL; + goto finally; + } + else { + id_store->id_flag = id_store->id->flag; + id_store->id_us = id_store->id->us; + + if (use_fake_user) { + id_store->id->flag |= LIB_FAKEUSER; + } + id_store->id->us = 1; + + BKE_blendfile_write_partial_tag_ID(id_store->id, true); + + id_store_len += 1; + id_store++; + } + } + } + + /* write blend */ + int retval = 0; + ReportList reports; + + BKE_reports_init(&reports, RPT_STORE); + + retval = BKE_blendfile_write_partial(bmain_src, filepath_abs, write_flags, &reports); + + /* cleanup state */ + BKE_blendfile_write_partial_end(bmain_src); + + if (retval) { + BKE_reports_print(&reports, RPT_ERROR_ALL); + BKE_reports_clear(&reports); + ret = Py_None; + Py_INCREF(ret); + } + else { + if (BPy_reports_to_error(&reports, PyExc_IOError, true) == 0) { + PyErr_SetString(PyExc_IOError, "Unknown error writing library data"); + } + ret = NULL; + } finally: - /* clear all flags for ID's added to the store (may run on error too) */ - id_store = id_store_array; + /* clear all flags for ID's added to the store (may run on error too) */ + id_store = id_store_array; - for (int i = 0; i < id_store_len; id_store++, i++) { + for (int i = 0; i < id_store_len; id_store++, i++) { + if (use_fake_user) { + if ((id_store->id_flag & LIB_FAKEUSER) == 0) { + id_store->id->flag &= ~LIB_FAKEUSER; + } + } - if (use_fake_user) { - if ((id_store->id_flag & LIB_FAKEUSER) == 0) { - id_store->id->flag &= ~LIB_FAKEUSER; - } - } + id_store->id->us = id_store->id_us; - id_store->id->us = id_store->id_us; + BKE_blendfile_write_partial_tag_ID(id_store->id, false); + } - BKE_blendfile_write_partial_tag_ID(id_store->id, false); - } + MEM_freeN(id_store_array); - MEM_freeN(id_store_array); - - return ret; + return ret; } - int BPY_library_write_module(PyObject *mod_par) { - static PyMethodDef write_meth = { - "write", (PyCFunction)bpy_lib_write, - METH_STATIC | METH_VARARGS | METH_KEYWORDS, - bpy_lib_write_doc, - }; + static PyMethodDef write_meth = { + "write", + (PyCFunction)bpy_lib_write, + METH_STATIC | METH_VARARGS | METH_KEYWORDS, + bpy_lib_write_doc, + }; - PyModule_AddObject(mod_par, "_library_write", PyCFunction_New(&write_meth, NULL)); + PyModule_AddObject(mod_par, "_library_write", PyCFunction_New(&write_meth, NULL)); - return 0; + return 0; } diff --git a/source/blender/python/intern/bpy_msgbus.c b/source/blender/python/intern/bpy_msgbus.c index bfcf089fb60..9db4201c252 100644 --- a/source/blender/python/intern/bpy_msgbus.c +++ b/source/blender/python/intern/bpy_msgbus.c @@ -40,24 +40,22 @@ #include "bpy_capi_utils.h" #include "bpy_rna.h" #include "bpy_intern_string.h" -#include "bpy_gizmo_wrap.h" /* own include */ - - -#include "bpy_msgbus.h" /* own include */ +#include "bpy_gizmo_wrap.h" /* own include */ +#include "bpy_msgbus.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name Internal Utils * \{ */ #define BPY_MSGBUS_RNA_MSGKEY_DOC \ -" :arg key: Represents the type of data being subscribed to\n" \ -"\n" \ -" Arguments include\n" \ -" - :class:`bpy.types.Property` instance.\n" \ -" - :class:`bpy.types.Struct` type.\n" \ -" - (:class:`bpy.types.Struct`, str) type and property name.\n" \ -" :type key: Muliple\n" + " :arg key: Represents the type of data being subscribed to\n" \ + "\n" \ + " Arguments include\n" \ + " - :class:`bpy.types.Property` instance.\n" \ + " - :class:`bpy.types.Struct` type.\n" \ + " - (:class:`bpy.types.Struct`, str) type and property name.\n" \ + " :type key: Muliple\n" /** * There are multiple ways we can get RNA from Python, @@ -69,87 +67,78 @@ * \param msg_key_params: Message key with all members zeroed out. * \return -1 on failure, 0 on success. */ -static int py_msgbus_rna_key_from_py( - PyObject *py_sub, - wmMsgParams_RNA *msg_key_params, - const char *error_prefix) +static int py_msgbus_rna_key_from_py(PyObject *py_sub, + wmMsgParams_RNA *msg_key_params, + const char *error_prefix) { - /* Allow common case, object rotation, location - etc. */ - if (BaseMathObject_CheckExact(py_sub)) { - BaseMathObject *py_sub_math = (BaseMathObject *)py_sub; - if (py_sub_math->cb_user == NULL) { - PyErr_Format( - PyExc_TypeError, - "%s: math argument has no owner", - error_prefix); - return -1; - } - py_sub = py_sub_math->cb_user; - /* Common case will use BPy_PropertyRNA_Check below. */ - } - - if (BPy_PropertyRNA_Check(py_sub)) { - BPy_PropertyRNA *data_prop = (BPy_PropertyRNA *)py_sub; - PYRNA_PROP_CHECK_INT(data_prop); - msg_key_params->ptr = data_prop->ptr; - msg_key_params->prop = data_prop->prop; - } - else if (BPy_StructRNA_Check(py_sub)) { - /* note, this isn't typically used since we don't edit structs directly. */ - BPy_StructRNA *data_srna = (BPy_StructRNA *)py_sub; - PYRNA_STRUCT_CHECK_INT(data_srna); - msg_key_params->ptr = data_srna->ptr; - } - /* TODO - property / type, not instance. */ - else if (PyType_Check(py_sub)) { - StructRNA *data_type = pyrna_struct_as_srna(py_sub, false, error_prefix); - if (data_type == NULL) { - return -1; - } - msg_key_params->ptr.type = data_type; - } - else if (PyTuple_CheckExact(py_sub)) { - if (PyTuple_GET_SIZE(py_sub) == 2) { - PyObject *data_type_py = PyTuple_GET_ITEM(py_sub, 0); - PyObject *data_prop_py = PyTuple_GET_ITEM(py_sub, 1); - StructRNA *data_type = pyrna_struct_as_srna(data_type_py, false, error_prefix); - if (data_type == NULL) { - return -1; - } - if (!PyUnicode_CheckExact(data_prop_py)) { - PyErr_Format( - PyExc_TypeError, - "%s: expected property to be a string", - error_prefix); - return -1; - } - PointerRNA data_type_ptr = { .type = data_type, }; - const char *data_prop_str = _PyUnicode_AsString(data_prop_py); - PropertyRNA *data_prop = RNA_struct_find_property(&data_type_ptr, data_prop_str); - - if (data_prop == NULL) { - PyErr_Format( - PyExc_TypeError, - "%s: struct %.200s does not contain property %.200s", - error_prefix, - RNA_struct_identifier(data_type), - data_prop_str); - return -1; - } - - msg_key_params->ptr.type = data_type; - msg_key_params->prop = data_prop; - } - else { - PyErr_Format( - PyExc_ValueError, - "%s: Expected a pair (type, property_id)", - error_prefix); - return -1; - } - } - return 0; + /* Allow common case, object rotation, location - etc. */ + if (BaseMathObject_CheckExact(py_sub)) { + BaseMathObject *py_sub_math = (BaseMathObject *)py_sub; + if (py_sub_math->cb_user == NULL) { + PyErr_Format(PyExc_TypeError, "%s: math argument has no owner", error_prefix); + return -1; + } + py_sub = py_sub_math->cb_user; + /* Common case will use BPy_PropertyRNA_Check below. */ + } + + if (BPy_PropertyRNA_Check(py_sub)) { + BPy_PropertyRNA *data_prop = (BPy_PropertyRNA *)py_sub; + PYRNA_PROP_CHECK_INT(data_prop); + msg_key_params->ptr = data_prop->ptr; + msg_key_params->prop = data_prop->prop; + } + else if (BPy_StructRNA_Check(py_sub)) { + /* note, this isn't typically used since we don't edit structs directly. */ + BPy_StructRNA *data_srna = (BPy_StructRNA *)py_sub; + PYRNA_STRUCT_CHECK_INT(data_srna); + msg_key_params->ptr = data_srna->ptr; + } + /* TODO - property / type, not instance. */ + else if (PyType_Check(py_sub)) { + StructRNA *data_type = pyrna_struct_as_srna(py_sub, false, error_prefix); + if (data_type == NULL) { + return -1; + } + msg_key_params->ptr.type = data_type; + } + else if (PyTuple_CheckExact(py_sub)) { + if (PyTuple_GET_SIZE(py_sub) == 2) { + PyObject *data_type_py = PyTuple_GET_ITEM(py_sub, 0); + PyObject *data_prop_py = PyTuple_GET_ITEM(py_sub, 1); + StructRNA *data_type = pyrna_struct_as_srna(data_type_py, false, error_prefix); + if (data_type == NULL) { + return -1; + } + if (!PyUnicode_CheckExact(data_prop_py)) { + PyErr_Format(PyExc_TypeError, "%s: expected property to be a string", error_prefix); + return -1; + } + PointerRNA data_type_ptr = { + .type = data_type, + }; + const char *data_prop_str = _PyUnicode_AsString(data_prop_py); + PropertyRNA *data_prop = RNA_struct_find_property(&data_type_ptr, data_prop_str); + + if (data_prop == NULL) { + PyErr_Format(PyExc_TypeError, + "%s: struct %.200s does not contain property %.200s", + error_prefix, + RNA_struct_identifier(data_type), + data_prop_str); + return -1; + } + + msg_key_params->ptr.type = data_type; + msg_key_params->prop = data_prop; + } + else { + PyErr_Format(PyExc_ValueError, "%s: Expected a pair (type, property_id)", error_prefix); + return -1; + } + } + return 0; } /** \} */ @@ -161,51 +150,52 @@ static int py_msgbus_rna_key_from_py( #define BPY_MSGBUS_USER_DATA_LEN 2 /* Follow wmMsgNotifyFn spec */ -static void bpy_msgbus_notify( - bContext *C, wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val) +static void bpy_msgbus_notify(bContext *C, + wmMsgSubscribeKey *UNUSED(msg_key), + wmMsgSubscribeValue *msg_val) { - PyGILState_STATE gilstate; - bpy_context_set(C, &gilstate); - - PyObject *user_data = msg_val->user_data; - BLI_assert(PyTuple_GET_SIZE(user_data) == BPY_MSGBUS_USER_DATA_LEN); - - PyObject *callback_args = PyTuple_GET_ITEM(user_data, 0); - PyObject *callback_notify = PyTuple_GET_ITEM(user_data, 1); - - const bool is_write_ok = pyrna_write_check(); - if (!is_write_ok) { - pyrna_write_set(true); - } - - PyObject *ret = PyObject_CallObject(callback_notify, callback_args); - - if (ret == NULL) { - PyC_Err_PrintWithFunc(callback_notify); - } - else { - if (ret != Py_None) { - PyErr_SetString(PyExc_ValueError, "the return value must be None"); - PyC_Err_PrintWithFunc(callback_notify); - } - Py_DECREF(ret); - } - - bpy_context_clear(C, &gilstate); - - if (!is_write_ok) { - pyrna_write_set(false); - } + PyGILState_STATE gilstate; + bpy_context_set(C, &gilstate); + + PyObject *user_data = msg_val->user_data; + BLI_assert(PyTuple_GET_SIZE(user_data) == BPY_MSGBUS_USER_DATA_LEN); + + PyObject *callback_args = PyTuple_GET_ITEM(user_data, 0); + PyObject *callback_notify = PyTuple_GET_ITEM(user_data, 1); + + const bool is_write_ok = pyrna_write_check(); + if (!is_write_ok) { + pyrna_write_set(true); + } + + PyObject *ret = PyObject_CallObject(callback_notify, callback_args); + + if (ret == NULL) { + PyC_Err_PrintWithFunc(callback_notify); + } + else { + if (ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + PyC_Err_PrintWithFunc(callback_notify); + } + Py_DECREF(ret); + } + + bpy_context_clear(C, &gilstate); + + if (!is_write_ok) { + pyrna_write_set(false); + } } /* Follow wmMsgSubscribeValueFreeDataFn spec */ -static void bpy_msgbus_subscribe_value_free_data( - struct wmMsgSubscribeKey *UNUSED(msg_key), struct wmMsgSubscribeValue *msg_val) +static void bpy_msgbus_subscribe_value_free_data(struct wmMsgSubscribeKey *UNUSED(msg_key), + struct wmMsgSubscribeValue *msg_val) { - PyGILState_STATE gilstate = PyGILState_Ensure(); - Py_DECREF(msg_val->owner); - Py_DECREF(msg_val->user_data); - PyGILState_Release(gilstate); + PyGILState_STATE gilstate = PyGILState_Ensure(); + Py_DECREF(msg_val->owner); + Py_DECREF(msg_val->user_data); + PyGILState_Release(gilstate); } /** \} */ @@ -214,201 +204,196 @@ static void bpy_msgbus_subscribe_value_free_data( /** \name Public Message Bus API * \{ */ -PyDoc_STRVAR(bpy_msgbus_subscribe_rna_doc, -".. function:: subscribe_rna(data, owner, args, notify, options=set())\n" -"\n" -BPY_MSGBUS_RNA_MSGKEY_DOC -" :arg owner: Handle for this subscription (compared by identity).\n" -" :type owner: Any type.\n" -" :arg options: Change the behavior of the subscriber.\n" -"\n" -" - ``PERSISTENT`` when set, the subscriber will be kept when remapping ID data.\n" -"\n" -" :type options: set of str.\n" -"\n" -" Returns a new vector int property definition.\n" -); +PyDoc_STRVAR( + bpy_msgbus_subscribe_rna_doc, + ".. function:: subscribe_rna(data, owner, args, notify, options=set())\n" + "\n" BPY_MSGBUS_RNA_MSGKEY_DOC + " :arg owner: Handle for this subscription (compared by identity).\n" + " :type owner: Any type.\n" + " :arg options: Change the behavior of the subscriber.\n" + "\n" + " - ``PERSISTENT`` when set, the subscriber will be kept when remapping ID data.\n" + "\n" + " :type options: set of str.\n" + "\n" + " Returns a new vector int property definition.\n"); static PyObject *bpy_msgbus_subscribe_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - const char *error_prefix = "subscribe_rna"; - PyObject *py_sub = NULL; - PyObject *py_owner = NULL; - PyObject *callback_args = NULL; - PyObject *callback_notify = NULL; - - enum { - IS_PERSISTENT = (1 << 0), - }; - PyObject *py_options = NULL; - EnumPropertyItem py_options_enum[] = { - {IS_PERSISTENT, "PERSISTENT", 0, ""}, - {0, NULL, 0, NULL, NULL}, - }; - int options = 0; - - if (PyTuple_GET_SIZE(args) != 0) { - PyErr_Format( - PyExc_TypeError, - "%s: only keyword arguments are supported", - error_prefix); - return NULL; - } - static const char *_keywords[] = { - "key", - "owner", - "args", - "notify", - "options", - NULL, - }; - static _PyArg_Parser _parser = {"OOO!O|O!:subscribe_rna", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &py_sub, &py_owner, - &PyTuple_Type, &callback_args, - &callback_notify, - &PySet_Type, &py_options)) - { - return NULL; - } - - if (py_options && - (pyrna_set_to_enum_bitfield(py_options_enum, py_options, &options, error_prefix)) == -1) - { - return NULL; - } - - /* Note: we may want to have a way to pass this in. */ - bContext *C = (bContext *)BPy_GetContext(); - struct wmMsgBus *mbus = CTX_wm_message_bus(C); - wmMsgParams_RNA msg_key_params = {{{0}}}; - - wmMsgSubscribeValue msg_val_params = {0}; - - if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) { - return NULL; - } - - if (!PyFunction_Check(callback_notify)) { - PyErr_Format( - PyExc_TypeError, - "notify expects a function, found %.200s", - Py_TYPE(callback_notify)->tp_name); - return NULL; - } - - if (options != 0) { - if (options & IS_PERSISTENT) { - msg_val_params.is_persistent = true; - } - } - - /* owner can be anything. */ - { - msg_val_params.owner = py_owner; - Py_INCREF(py_owner); - } - - { - PyObject *user_data = PyTuple_New(2); - PyTuple_SET_ITEMS( - user_data, - Py_INCREF_RET(callback_args), - Py_INCREF_RET(callback_notify)); - msg_val_params.user_data = user_data; - } - - msg_val_params.notify = bpy_msgbus_notify; - msg_val_params.free_data = bpy_msgbus_subscribe_value_free_data; - - WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_val_params, __func__); - - WM_msg_dump(mbus, __func__); - - Py_RETURN_NONE; + const char *error_prefix = "subscribe_rna"; + PyObject *py_sub = NULL; + PyObject *py_owner = NULL; + PyObject *callback_args = NULL; + PyObject *callback_notify = NULL; + + enum { + IS_PERSISTENT = (1 << 0), + }; + PyObject *py_options = NULL; + EnumPropertyItem py_options_enum[] = { + {IS_PERSISTENT, "PERSISTENT", 0, ""}, + {0, NULL, 0, NULL, NULL}, + }; + int options = 0; + + if (PyTuple_GET_SIZE(args) != 0) { + PyErr_Format(PyExc_TypeError, "%s: only keyword arguments are supported", error_prefix); + return NULL; + } + static const char *_keywords[] = { + "key", + "owner", + "args", + "notify", + "options", + NULL, + }; + static _PyArg_Parser _parser = {"OOO!O|O!:subscribe_rna", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &py_sub, + &py_owner, + &PyTuple_Type, + &callback_args, + &callback_notify, + &PySet_Type, + &py_options)) { + return NULL; + } + + if (py_options && + (pyrna_set_to_enum_bitfield(py_options_enum, py_options, &options, error_prefix)) == -1) { + return NULL; + } + + /* Note: we may want to have a way to pass this in. */ + bContext *C = (bContext *)BPy_GetContext(); + struct wmMsgBus *mbus = CTX_wm_message_bus(C); + wmMsgParams_RNA msg_key_params = {{{0}}}; + + wmMsgSubscribeValue msg_val_params = {0}; + + if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) { + return NULL; + } + + if (!PyFunction_Check(callback_notify)) { + PyErr_Format(PyExc_TypeError, + "notify expects a function, found %.200s", + Py_TYPE(callback_notify)->tp_name); + return NULL; + } + + if (options != 0) { + if (options & IS_PERSISTENT) { + msg_val_params.is_persistent = true; + } + } + + /* owner can be anything. */ + { + msg_val_params.owner = py_owner; + Py_INCREF(py_owner); + } + + { + PyObject *user_data = PyTuple_New(2); + PyTuple_SET_ITEMS(user_data, Py_INCREF_RET(callback_args), Py_INCREF_RET(callback_notify)); + msg_val_params.user_data = user_data; + } + + msg_val_params.notify = bpy_msgbus_notify; + msg_val_params.free_data = bpy_msgbus_subscribe_value_free_data; + + WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_val_params, __func__); + + WM_msg_dump(mbus, __func__); + + Py_RETURN_NONE; } -PyDoc_STRVAR(bpy_msgbus_publish_rna_doc, -".. function:: publish_rna(data, owner, args, notify)\n" -"\n" -BPY_MSGBUS_RNA_MSGKEY_DOC -"\n" -" Notify subscribers of changes to this property\n" -" (this typically doesn't need to be called explicitly since changes will automatically publish updates).\n" -" In some cases it may be useful to publish changes explicitly using more general keys.\n" -); +PyDoc_STRVAR( + bpy_msgbus_publish_rna_doc, + ".. function:: publish_rna(data, owner, args, notify)\n" + "\n" BPY_MSGBUS_RNA_MSGKEY_DOC + "\n" + " Notify subscribers of changes to this property\n" + " (this typically doesn't need to be called explicitly since changes will automatically " + "publish updates).\n" + " In some cases it may be useful to publish changes explicitly using more general keys.\n"); static PyObject *bpy_msgbus_publish_rna(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - const char *error_prefix = "publish_rna"; - PyObject *py_sub = NULL; - - if (PyTuple_GET_SIZE(args) != 0) { - PyErr_Format( - PyExc_TypeError, - "%s: only keyword arguments are supported", - error_prefix); - return NULL; - } - static const char *_keywords[] = { - "key", - NULL, - }; - static _PyArg_Parser _parser = {"O:publish_rna", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &py_sub)) - { - return NULL; - } - - /* Note: we may want to have a way to pass this in. */ - bContext *C = (bContext *)BPy_GetContext(); - struct wmMsgBus *mbus = CTX_wm_message_bus(C); - wmMsgParams_RNA msg_key_params = {{{0}}}; - - if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) { - return NULL; - } - - WM_msg_publish_rna_params(mbus, &msg_key_params); - - Py_RETURN_NONE; + const char *error_prefix = "publish_rna"; + PyObject *py_sub = NULL; + + if (PyTuple_GET_SIZE(args) != 0) { + PyErr_Format(PyExc_TypeError, "%s: only keyword arguments are supported", error_prefix); + return NULL; + } + static const char *_keywords[] = { + "key", + NULL, + }; + static _PyArg_Parser _parser = {"O:publish_rna", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &py_sub)) { + return NULL; + } + + /* Note: we may want to have a way to pass this in. */ + bContext *C = (bContext *)BPy_GetContext(); + struct wmMsgBus *mbus = CTX_wm_message_bus(C); + wmMsgParams_RNA msg_key_params = {{{0}}}; + + if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) { + return NULL; + } + + WM_msg_publish_rna_params(mbus, &msg_key_params); + + Py_RETURN_NONE; } PyDoc_STRVAR(bpy_msgbus_clear_by_owner_doc, -".. function:: clear_by_owner(owner)\n" -"\n" -" Clear all subscribers using this owner.\n" -); + ".. function:: clear_by_owner(owner)\n" + "\n" + " Clear all subscribers using this owner.\n"); static PyObject *bpy_msgbus_clear_by_owner(PyObject *UNUSED(self), PyObject *py_owner) { - bContext *C = (bContext *)BPy_GetContext(); - struct wmMsgBus *mbus = CTX_wm_message_bus(C); - WM_msgbus_clear_by_owner(mbus, py_owner); - Py_RETURN_NONE; + bContext *C = (bContext *)BPy_GetContext(); + struct wmMsgBus *mbus = CTX_wm_message_bus(C); + WM_msgbus_clear_by_owner(mbus, py_owner); + Py_RETURN_NONE; } static struct PyMethodDef BPy_msgbus_methods[] = { - {"subscribe_rna", (PyCFunction)bpy_msgbus_subscribe_rna, METH_VARARGS | METH_KEYWORDS, bpy_msgbus_subscribe_rna_doc}, - {"publish_rna", (PyCFunction)bpy_msgbus_publish_rna, METH_VARARGS | METH_KEYWORDS, bpy_msgbus_publish_rna_doc}, - {"clear_by_owner", (PyCFunction)bpy_msgbus_clear_by_owner, METH_O, bpy_msgbus_clear_by_owner_doc}, - {NULL, NULL, 0, NULL}, + {"subscribe_rna", + (PyCFunction)bpy_msgbus_subscribe_rna, + METH_VARARGS | METH_KEYWORDS, + bpy_msgbus_subscribe_rna_doc}, + {"publish_rna", + (PyCFunction)bpy_msgbus_publish_rna, + METH_VARARGS | METH_KEYWORDS, + bpy_msgbus_publish_rna_doc}, + {"clear_by_owner", + (PyCFunction)bpy_msgbus_clear_by_owner, + METH_O, + bpy_msgbus_clear_by_owner_doc}, + {NULL, NULL, 0, NULL}, }; static struct PyModuleDef _bpy_msgbus_def = { - PyModuleDef_HEAD_INIT, - .m_name = "msgbus", - .m_methods = BPy_msgbus_methods, + PyModuleDef_HEAD_INIT, + .m_name = "msgbus", + .m_methods = BPy_msgbus_methods, }; - PyObject *BPY_msgbus_module(void) { - PyObject *submodule; + PyObject *submodule; - submodule = PyModule_Create(&_bpy_msgbus_def); + submodule = PyModule_Create(&_bpy_msgbus_def); - return submodule; + return submodule; } /** \} */ diff --git a/source/blender/python/intern/bpy_msgbus.h b/source/blender/python/intern/bpy_msgbus.h index 179b220c3c2..2b3cc4cfaf4 100644 --- a/source/blender/python/intern/bpy_msgbus.h +++ b/source/blender/python/intern/bpy_msgbus.h @@ -23,4 +23,4 @@ PyObject *BPY_msgbus_module(void); -#endif /* __BPY_MSGBUS_H__ */ +#endif /* __BPY_MSGBUS_H__ */ diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index ff6bd3840e9..1e979ad1d0b 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -59,385 +59,407 @@ static wmOperatorType *ot_lookup_from_py_string(PyObject *value, const char *py_fn_id) { - const char *opname = _PyUnicode_AsString(value); - if (opname == NULL) { - PyErr_Format(PyExc_TypeError, "%s() expects a string argument", py_fn_id); - return NULL; - } - - wmOperatorType *ot = WM_operatortype_find(opname, true); - if (ot == NULL) { - PyErr_Format(PyExc_KeyError, "%s(\"%s\") not found", py_fn_id, opname); - return NULL; - } - return ot; + const char *opname = _PyUnicode_AsString(value); + if (opname == NULL) { + PyErr_Format(PyExc_TypeError, "%s() expects a string argument", py_fn_id); + return NULL; + } + + wmOperatorType *ot = WM_operatortype_find(opname, true); + if (ot == NULL) { + PyErr_Format(PyExc_KeyError, "%s(\"%s\") not found", py_fn_id, opname); + return NULL; + } + return ot; } static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args) { - wmOperatorType *ot; - const char *opname; - PyObject *context_dict = NULL; /* optional args */ - PyObject *context_dict_back; - const char *context_str = NULL; - PyObject *ret; - - int context = WM_OP_EXEC_DEFAULT; - - /* XXX Todo, work out a better solution for passing on context, - * could make a tuple from self and pack the name and Context into it... */ - bContext *C = (bContext *)BPy_GetContext(); - - if (C == NULL) { - PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators"); - return NULL; - } - - if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str)) { - return NULL; - } - - ot = WM_operatortype_find(opname, true); - - if (ot == NULL) { - PyErr_Format(PyExc_AttributeError, - "Polling operator \"bpy.ops.%s\" error, " - "could not be found", opname); - return NULL; - } - - if (context_str) { - if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context) == 0) { - char *enum_str = BPy_enum_as_string(rna_enum_operator_context_items); - PyErr_Format(PyExc_TypeError, - "Calling operator \"bpy.ops.%s.poll\" error, " - "expected a string enum in (%s)", - opname, enum_str); - MEM_freeN(enum_str); - return NULL; - } - } - - if (context_dict == NULL || context_dict == Py_None) { - context_dict = NULL; - } - else if (!PyDict_Check(context_dict)) { - PyErr_Format(PyExc_TypeError, - "Calling operator \"bpy.ops.%s.poll\" error, " - "custom context expected a dict or None, got a %.200s", - opname, Py_TYPE(context_dict)->tp_name); - return NULL; - } - - context_dict_back = CTX_py_dict_get(C); - CTX_py_dict_set(C, (void *)context_dict); - Py_XINCREF(context_dict); /* so we done loose it */ - - /* main purpose of this function */ - ret = WM_operator_poll_context((bContext *)C, ot, context) ? Py_True : Py_False; - - /* restore with original context dict, probably NULL but need this for nested operator calls */ - Py_XDECREF(context_dict); - CTX_py_dict_set(C, (void *)context_dict_back); - - return Py_INCREF_RET(ret); + wmOperatorType *ot; + const char *opname; + PyObject *context_dict = NULL; /* optional args */ + PyObject *context_dict_back; + const char *context_str = NULL; + PyObject *ret; + + int context = WM_OP_EXEC_DEFAULT; + + /* XXX Todo, work out a better solution for passing on context, + * could make a tuple from self and pack the name and Context into it... */ + bContext *C = (bContext *)BPy_GetContext(); + + if (C == NULL) { + PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators"); + return NULL; + } + + if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str)) { + return NULL; + } + + ot = WM_operatortype_find(opname, true); + + if (ot == NULL) { + PyErr_Format(PyExc_AttributeError, + "Polling operator \"bpy.ops.%s\" error, " + "could not be found", + opname); + return NULL; + } + + if (context_str) { + if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context) == 0) { + char *enum_str = BPy_enum_as_string(rna_enum_operator_context_items); + PyErr_Format(PyExc_TypeError, + "Calling operator \"bpy.ops.%s.poll\" error, " + "expected a string enum in (%s)", + opname, + enum_str); + MEM_freeN(enum_str); + return NULL; + } + } + + if (context_dict == NULL || context_dict == Py_None) { + context_dict = NULL; + } + else if (!PyDict_Check(context_dict)) { + PyErr_Format(PyExc_TypeError, + "Calling operator \"bpy.ops.%s.poll\" error, " + "custom context expected a dict or None, got a %.200s", + opname, + Py_TYPE(context_dict)->tp_name); + return NULL; + } + + context_dict_back = CTX_py_dict_get(C); + CTX_py_dict_set(C, (void *)context_dict); + Py_XINCREF(context_dict); /* so we done loose it */ + + /* main purpose of this function */ + ret = WM_operator_poll_context((bContext *)C, ot, context) ? Py_True : Py_False; + + /* restore with original context dict, probably NULL but need this for nested operator calls */ + Py_XDECREF(context_dict); + CTX_py_dict_set(C, (void *)context_dict_back); + + return Py_INCREF_RET(ret); } static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) { - wmOperatorType *ot; - int error_val = 0; - PointerRNA ptr; - int operator_ret = OPERATOR_CANCELLED; - - const char *opname; - const char *context_str = NULL; - PyObject *kw = NULL; /* optional args */ - PyObject *context_dict = NULL; /* optional args */ - PyObject *context_dict_back; - - /* note that context is an int, python does the conversion in this case */ - int context = WM_OP_EXEC_DEFAULT; - int is_undo = false; - - /* XXX Todo, work out a better solution for passing on context, - * could make a tuple from self and pack the name and Context into it... */ - bContext *C = (bContext *)BPy_GetContext(); - - if (C == NULL) { - PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators"); - return NULL; - } - - if (!PyArg_ParseTuple(args, "sO|O!si:_bpy.ops.call", - &opname, &context_dict, &PyDict_Type, &kw, &context_str, &is_undo)) - { - return NULL; - } - - ot = WM_operatortype_find(opname, true); - - if (ot == NULL) { - PyErr_Format(PyExc_AttributeError, - "Calling operator \"bpy.ops.%s\" error, " - "could not be found", opname); - return NULL; - } - - if (!pyrna_write_check()) { - PyErr_Format(PyExc_RuntimeError, - "Calling operator \"bpy.ops.%s\" error, " - "can't modify blend data in this state (drawing/rendering)", - opname); - return NULL; - } - - if (context_str) { - if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context) == 0) { - char *enum_str = BPy_enum_as_string(rna_enum_operator_context_items); - PyErr_Format(PyExc_TypeError, - "Calling operator \"bpy.ops.%s\" error, " - "expected a string enum in (%s)", - opname, enum_str); - MEM_freeN(enum_str); - return NULL; - } - } - - if (context_dict == NULL || context_dict == Py_None) { - context_dict = NULL; - } - else if (!PyDict_Check(context_dict)) { - PyErr_Format(PyExc_TypeError, - "Calling operator \"bpy.ops.%s\" error, " - "custom context expected a dict or None, got a %.200s", - opname, Py_TYPE(context_dict)->tp_name); - return NULL; - } - - context_dict_back = CTX_py_dict_get(C); - - CTX_py_dict_set(C, (void *)context_dict); - Py_XINCREF(context_dict); /* so we done loose it */ - - if (WM_operator_poll_context((bContext *)C, ot, context) == false) { - const char *msg = CTX_wm_operator_poll_msg_get(C); - PyErr_Format(PyExc_RuntimeError, - "Operator bpy.ops.%.200s.poll() %.200s", - opname, msg ? msg : "failed, context is incorrect"); - CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */ - error_val = -1; - } - else { - WM_operator_properties_create_ptr(&ptr, ot); - WM_operator_properties_sanitize(&ptr, 0); - - if (kw && PyDict_Size(kw)) { - error_val = pyrna_pydict_to_props(&ptr, kw, false, "Converting py args to operator properties: "); - } - - if (error_val == 0) { - ReportList *reports; - - reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); - BKE_reports_init(reports, RPT_STORE | RPT_OP_HOLD); /* own so these don't move into global reports */ + wmOperatorType *ot; + int error_val = 0; + PointerRNA ptr; + int operator_ret = OPERATOR_CANCELLED; + + const char *opname; + const char *context_str = NULL; + PyObject *kw = NULL; /* optional args */ + PyObject *context_dict = NULL; /* optional args */ + PyObject *context_dict_back; + + /* note that context is an int, python does the conversion in this case */ + int context = WM_OP_EXEC_DEFAULT; + int is_undo = false; + + /* XXX Todo, work out a better solution for passing on context, + * could make a tuple from self and pack the name and Context into it... */ + bContext *C = (bContext *)BPy_GetContext(); + + if (C == NULL) { + PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators"); + return NULL; + } + + if (!PyArg_ParseTuple(args, + "sO|O!si:_bpy.ops.call", + &opname, + &context_dict, + &PyDict_Type, + &kw, + &context_str, + &is_undo)) { + return NULL; + } + + ot = WM_operatortype_find(opname, true); + + if (ot == NULL) { + PyErr_Format(PyExc_AttributeError, + "Calling operator \"bpy.ops.%s\" error, " + "could not be found", + opname); + return NULL; + } + + if (!pyrna_write_check()) { + PyErr_Format(PyExc_RuntimeError, + "Calling operator \"bpy.ops.%s\" error, " + "can't modify blend data in this state (drawing/rendering)", + opname); + return NULL; + } + + if (context_str) { + if (RNA_enum_value_from_id(rna_enum_operator_context_items, context_str, &context) == 0) { + char *enum_str = BPy_enum_as_string(rna_enum_operator_context_items); + PyErr_Format(PyExc_TypeError, + "Calling operator \"bpy.ops.%s\" error, " + "expected a string enum in (%s)", + opname, + enum_str); + MEM_freeN(enum_str); + return NULL; + } + } + + if (context_dict == NULL || context_dict == Py_None) { + context_dict = NULL; + } + else if (!PyDict_Check(context_dict)) { + PyErr_Format(PyExc_TypeError, + "Calling operator \"bpy.ops.%s\" error, " + "custom context expected a dict or None, got a %.200s", + opname, + Py_TYPE(context_dict)->tp_name); + return NULL; + } + + context_dict_back = CTX_py_dict_get(C); + + CTX_py_dict_set(C, (void *)context_dict); + Py_XINCREF(context_dict); /* so we done loose it */ + + if (WM_operator_poll_context((bContext *)C, ot, context) == false) { + const char *msg = CTX_wm_operator_poll_msg_get(C); + PyErr_Format(PyExc_RuntimeError, + "Operator bpy.ops.%.200s.poll() %.200s", + opname, + msg ? msg : "failed, context is incorrect"); + CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */ + error_val = -1; + } + else { + WM_operator_properties_create_ptr(&ptr, ot); + WM_operator_properties_sanitize(&ptr, 0); + + if (kw && PyDict_Size(kw)) { + error_val = pyrna_pydict_to_props( + &ptr, kw, false, "Converting py args to operator properties: "); + } + + if (error_val == 0) { + ReportList *reports; + + reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); + BKE_reports_init(reports, + RPT_STORE | RPT_OP_HOLD); /* own so these don't move into global reports */ #ifdef BPY_RELEASE_GIL - /* release GIL, since a thread could be started from an operator - * that updates a driver */ - /* note: I have not seen any examples of code that does this - * so it may not be officially supported but seems to work ok. */ - { - PyThreadState *ts = PyEval_SaveThread(); + /* release GIL, since a thread could be started from an operator + * that updates a driver */ + /* note: I have not seen any examples of code that does this + * so it may not be officially supported but seems to work ok. */ + { + PyThreadState *ts = PyEval_SaveThread(); #endif - operator_ret = WM_operator_call_py(C, ot, context, &ptr, reports, is_undo); + operator_ret = WM_operator_call_py(C, ot, context, &ptr, reports, is_undo); #ifdef BPY_RELEASE_GIL - /* regain GIL */ - PyEval_RestoreThread(ts); - } + /* regain GIL */ + PyEval_RestoreThread(ts); + } #endif - error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, false); + error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, false); - /* operator output is nice to have in the terminal/console too */ - if (!BLI_listbase_is_empty(&reports->list)) { - BPy_reports_write_stdout(reports, NULL); - } + /* operator output is nice to have in the terminal/console too */ + if (!BLI_listbase_is_empty(&reports->list)) { + BPy_reports_write_stdout(reports, NULL); + } - BKE_reports_clear(reports); - if ((reports->flag & RPT_FREE) == 0) { - MEM_freeN(reports); - } - else { - /* The WM is now responsible for running the modal operator, - * show reports in the info window. */ - reports->flag &= ~RPT_OP_HOLD; - } - } + BKE_reports_clear(reports); + if ((reports->flag & RPT_FREE) == 0) { + MEM_freeN(reports); + } + else { + /* The WM is now responsible for running the modal operator, + * show reports in the info window. */ + reports->flag &= ~RPT_OP_HOLD; + } + } - WM_operator_properties_free(&ptr); + WM_operator_properties_free(&ptr); #if 0 - /* if there is some way to know an operator takes args we should use this */ - { - /* no props */ - if (kw != NULL) { - PyErr_Format(PyExc_AttributeError, - "Operator \"%s\" does not take any args", - opname); - return NULL; - } - - WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL); - } + /* if there is some way to know an operator takes args we should use this */ + { + /* no props */ + if (kw != NULL) { + PyErr_Format(PyExc_AttributeError, + "Operator \"%s\" does not take any args", + opname); + return NULL; + } + + WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL); + } #endif - } + } - /* restore with original context dict, probably NULL but need this for nested operator calls */ - Py_XDECREF(context_dict); - CTX_py_dict_set(C, (void *)context_dict_back); + /* restore with original context dict, probably NULL but need this for nested operator calls */ + Py_XDECREF(context_dict); + CTX_py_dict_set(C, (void *)context_dict_back); - if (error_val == -1) { - return NULL; - } + if (error_val == -1) { + return NULL; + } - /* when calling bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(), - * further access will crash blender. setting context is not needed in this case, only calling because this - * function corrects bpy.data (internal Main pointer) */ - BPY_modules_update(C); + /* when calling bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(), + * further access will crash blender. setting context is not needed in this case, only calling because this + * function corrects bpy.data (internal Main pointer) */ + BPY_modules_update(C); - /* needed for when WM_OT_read_factory_settings us called from within a script */ - bpy_import_main_set(CTX_data_main(C)); - - /* return operator_ret as a bpy enum */ - return pyrna_enum_bitfield_to_py(rna_enum_operator_return_items, operator_ret); + /* needed for when WM_OT_read_factory_settings us called from within a script */ + bpy_import_main_set(CTX_data_main(C)); + /* return operator_ret as a bpy enum */ + return pyrna_enum_bitfield_to_py(rna_enum_operator_return_items, operator_ret); } static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args) { - wmOperatorType *ot; - PointerRNA ptr; - - const char *opname; - PyObject *kw = NULL; /* optional args */ - bool all_args = true; - bool macro_args = true; - int error_val = 0; - - char *buf = NULL; - PyObject *pybuf; - - bContext *C = (bContext *)BPy_GetContext(); - - if (C == NULL) { - PyErr_SetString(PyExc_RuntimeError, "Context is None, cant get the string representation of this object."); - return NULL; - } - - if (!PyArg_ParseTuple( - args, "s|O!O&O&:_bpy.ops.as_string", - &opname, &PyDict_Type, &kw, - PyC_ParseBool, &all_args, - PyC_ParseBool, ¯o_args)) - { - return NULL; - } - - ot = WM_operatortype_find(opname, true); - - if (ot == NULL) { - PyErr_Format(PyExc_AttributeError, - "_bpy.ops.as_string: operator \"%.200s\" " - "could not be found", opname); - return NULL; - } - - /* WM_operator_properties_create(&ptr, opname); */ - /* Save another lookup */ - RNA_pointer_create(NULL, ot->srna, NULL, &ptr); - - if (kw && PyDict_Size(kw)) { - error_val = pyrna_pydict_to_props(&ptr, kw, false, "Converting py args to operator properties: "); - } - - if (error_val == 0) { - buf = WM_operator_pystring_ex(C, NULL, all_args, macro_args, ot, &ptr); - } - - WM_operator_properties_free(&ptr); - - if (error_val == -1) { - return NULL; - } - - if (buf) { - pybuf = PyUnicode_FromString(buf); - MEM_freeN(buf); - } - else { - pybuf = PyUnicode_FromString(""); - } - - return pybuf; + wmOperatorType *ot; + PointerRNA ptr; + + const char *opname; + PyObject *kw = NULL; /* optional args */ + bool all_args = true; + bool macro_args = true; + int error_val = 0; + + char *buf = NULL; + PyObject *pybuf; + + bContext *C = (bContext *)BPy_GetContext(); + + if (C == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "Context is None, cant get the string representation of this object."); + return NULL; + } + + if (!PyArg_ParseTuple(args, + "s|O!O&O&:_bpy.ops.as_string", + &opname, + &PyDict_Type, + &kw, + PyC_ParseBool, + &all_args, + PyC_ParseBool, + ¯o_args)) { + return NULL; + } + + ot = WM_operatortype_find(opname, true); + + if (ot == NULL) { + PyErr_Format(PyExc_AttributeError, + "_bpy.ops.as_string: operator \"%.200s\" " + "could not be found", + opname); + return NULL; + } + + /* WM_operator_properties_create(&ptr, opname); */ + /* Save another lookup */ + RNA_pointer_create(NULL, ot->srna, NULL, &ptr); + + if (kw && PyDict_Size(kw)) { + error_val = pyrna_pydict_to_props( + &ptr, kw, false, "Converting py args to operator properties: "); + } + + if (error_val == 0) { + buf = WM_operator_pystring_ex(C, NULL, all_args, macro_args, ot, &ptr); + } + + WM_operator_properties_free(&ptr); + + if (error_val == -1) { + return NULL; + } + + if (buf) { + pybuf = PyUnicode_FromString(buf); + MEM_freeN(buf); + } + else { + pybuf = PyUnicode_FromString(""); + } + + return pybuf; } static PyObject *pyop_dir(PyObject *UNUSED(self)) { - GHashIterator iter; - PyObject *list; - int i; + GHashIterator iter; + PyObject *list; + int i; - WM_operatortype_iter(&iter); - list = PyList_New(BLI_ghash_len(iter.gh)); + WM_operatortype_iter(&iter); + list = PyList_New(BLI_ghash_len(iter.gh)); - for (i = 0; !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter), i++) { - wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); - PyList_SET_ITEM(list, i, PyUnicode_FromString(ot->idname)); - } + for (i = 0; !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter), i++) { + wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); + PyList_SET_ITEM(list, i, PyUnicode_FromString(ot->idname)); + } - return list; + return list; } static PyObject *pyop_getrna_type(PyObject *UNUSED(self), PyObject *value) { - wmOperatorType *ot; - if ((ot = ot_lookup_from_py_string(value, "get_rna_type")) == NULL) { - return NULL; - } - - PointerRNA ptr; - RNA_pointer_create(NULL, &RNA_Struct, ot->srna, &ptr); - BPy_StructRNA *pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); - return (PyObject *)pyrna; + wmOperatorType *ot; + if ((ot = ot_lookup_from_py_string(value, "get_rna_type")) == NULL) { + return NULL; + } + + PointerRNA ptr; + RNA_pointer_create(NULL, &RNA_Struct, ot->srna, &ptr); + BPy_StructRNA *pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); + return (PyObject *)pyrna; } static struct PyMethodDef bpy_ops_methods[] = { - {"poll", (PyCFunction) pyop_poll, METH_VARARGS, NULL}, - {"call", (PyCFunction) pyop_call, METH_VARARGS, NULL}, - {"as_string", (PyCFunction) pyop_as_string, METH_VARARGS, NULL}, - {"dir", (PyCFunction) pyop_dir, METH_NOARGS, NULL}, - {"get_rna_type", (PyCFunction) pyop_getrna_type, METH_O, NULL}, - {"macro_define", (PyCFunction) PYOP_wrap_macro_define, METH_VARARGS, NULL}, - {NULL, NULL, 0, NULL}, + {"poll", (PyCFunction)pyop_poll, METH_VARARGS, NULL}, + {"call", (PyCFunction)pyop_call, METH_VARARGS, NULL}, + {"as_string", (PyCFunction)pyop_as_string, METH_VARARGS, NULL}, + {"dir", (PyCFunction)pyop_dir, METH_NOARGS, NULL}, + {"get_rna_type", (PyCFunction)pyop_getrna_type, METH_O, NULL}, + {"macro_define", (PyCFunction)PYOP_wrap_macro_define, METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL}, }; static struct PyModuleDef bpy_ops_module = { - PyModuleDef_HEAD_INIT, - "_bpy.ops", - NULL, - -1, /* multiple "initialization" just copies the module dict. */ - bpy_ops_methods, - NULL, NULL, NULL, NULL, + PyModuleDef_HEAD_INIT, + "_bpy.ops", + NULL, + -1, /* multiple "initialization" just copies the module dict. */ + bpy_ops_methods, + NULL, + NULL, + NULL, + NULL, }; PyObject *BPY_operator_module(void) { - PyObject *submodule; + PyObject *submodule; - submodule = PyModule_Create(&bpy_ops_module); + submodule = PyModule_Create(&bpy_ops_module); - return submodule; + return submodule; } diff --git a/source/blender/python/intern/bpy_operator.h b/source/blender/python/intern/bpy_operator.h index 8ecf66adad7..37f6b90fbdb 100644 --- a/source/blender/python/intern/bpy_operator.h +++ b/source/blender/python/intern/bpy_operator.h @@ -23,10 +23,10 @@ extern PyTypeObject pyop_base_Type; -#define BPy_OperatorBase_Check(v) (PyObject_TypeCheck(v, &pyop_base_Type)) +#define BPy_OperatorBase_Check(v) (PyObject_TypeCheck(v, &pyop_base_Type)) typedef struct { - PyObject_HEAD /* required python macro */ + PyObject_HEAD /* required python macro */ } BPy_OperatorBase; PyObject *BPY_operator_module(void); diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 6a130a7c52b..976ed4611b0 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -35,163 +35,158 @@ #include "bpy_rna.h" #include "bpy_intern_string.h" -#include "bpy_operator_wrap.h" /* own include */ +#include "bpy_operator_wrap.h" /* own include */ static void operator_properties_init(wmOperatorType *ot) { - PyTypeObject *py_class = ot->ext.data; - RNA_struct_blender_type_set(ot->ext.srna, ot); - - /* Only call this so pyrna_deferred_register_class gives a useful error - * WM_operatortype_append_ptr will call RNA_def_struct_identifier later. - * - * Note the 'no_struct_map' function is used since the actual struct name is already used by the operator. - */ - RNA_def_struct_identifier_no_struct_map(ot->srna, ot->idname); - - if (pyrna_deferred_register_class(ot->srna, py_class) != 0) { - PyErr_Print(); /* failed to register operator props */ - PyErr_Clear(); - } - - /* set the default property: ot->prop */ - { - /* picky developers will notice that 'bl_property' won't work with inheritance - * get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */ - PyObject *py_class_dict = py_class->tp_dict; - PyObject *bl_property = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_property); - const char *prop_id; - bool prop_raise_error; - - if (bl_property) { - if (PyUnicode_Check(bl_property)) { - /* since the property is explicitly given, raise an error if its not found */ - prop_id = _PyUnicode_AsString(bl_property); - prop_raise_error = true; - } - else { - PyErr_Format(PyExc_ValueError, - "%.200s.bl_property should be a string, not %.200s", - ot->idname, Py_TYPE(bl_property)->tp_name); - - /* this could be done cleaner, for now its OK */ - PyErr_Print(); - PyErr_Clear(); - - prop_id = NULL; - prop_raise_error = false; - } - } - else { - /* fallback to hard-coded string (pre 2.66, could be deprecated) */ - prop_id = "type"; - prop_raise_error = false; - } - - if (prop_id) { - PointerRNA ptr; - PropertyRNA *prop; - - RNA_pointer_create(NULL, ot->srna, NULL, &ptr); - prop = RNA_struct_find_property(&ptr, prop_id); - if (prop) { - ot->prop = prop; - } - else { - if (prop_raise_error) { - PyErr_Format(PyExc_ValueError, - "%.200s.bl_property '%.200s' not found", - ot->idname, prop_id); - - /* this could be done cleaner, for now its OK */ - PyErr_Print(); - PyErr_Clear(); - } - } - } - } - /* end 'ot->prop' assignment */ - + PyTypeObject *py_class = ot->ext.data; + RNA_struct_blender_type_set(ot->ext.srna, ot); + + /* Only call this so pyrna_deferred_register_class gives a useful error + * WM_operatortype_append_ptr will call RNA_def_struct_identifier later. + * + * Note the 'no_struct_map' function is used since the actual struct name is already used by the operator. + */ + RNA_def_struct_identifier_no_struct_map(ot->srna, ot->idname); + + if (pyrna_deferred_register_class(ot->srna, py_class) != 0) { + PyErr_Print(); /* failed to register operator props */ + PyErr_Clear(); + } + + /* set the default property: ot->prop */ + { + /* picky developers will notice that 'bl_property' won't work with inheritance + * get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal) - campbell */ + PyObject *py_class_dict = py_class->tp_dict; + PyObject *bl_property = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_property); + const char *prop_id; + bool prop_raise_error; + + if (bl_property) { + if (PyUnicode_Check(bl_property)) { + /* since the property is explicitly given, raise an error if its not found */ + prop_id = _PyUnicode_AsString(bl_property); + prop_raise_error = true; + } + else { + PyErr_Format(PyExc_ValueError, + "%.200s.bl_property should be a string, not %.200s", + ot->idname, + Py_TYPE(bl_property)->tp_name); + + /* this could be done cleaner, for now its OK */ + PyErr_Print(); + PyErr_Clear(); + + prop_id = NULL; + prop_raise_error = false; + } + } + else { + /* fallback to hard-coded string (pre 2.66, could be deprecated) */ + prop_id = "type"; + prop_raise_error = false; + } + + if (prop_id) { + PointerRNA ptr; + PropertyRNA *prop; + + RNA_pointer_create(NULL, ot->srna, NULL, &ptr); + prop = RNA_struct_find_property(&ptr, prop_id); + if (prop) { + ot->prop = prop; + } + else { + if (prop_raise_error) { + PyErr_Format( + PyExc_ValueError, "%.200s.bl_property '%.200s' not found", ot->idname, prop_id); + + /* this could be done cleaner, for now its OK */ + PyErr_Print(); + PyErr_Clear(); + } + } + } + } + /* end 'ot->prop' assignment */ } void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata) { - /* take care not to overwrite anything set in - * WM_operatortype_append_ptr before opfunc() is called */ - StructRNA *srna = ot->srna; - *ot = *((wmOperatorType *)userdata); - ot->srna = srna; /* restore */ - - /* Use i18n context from ext.srna if possible (py operators). */ - if (ot->ext.srna) { - RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna)); - } - - operator_properties_init(ot); + /* take care not to overwrite anything set in + * WM_operatortype_append_ptr before opfunc() is called */ + StructRNA *srna = ot->srna; + *ot = *((wmOperatorType *)userdata); + ot->srna = srna; /* restore */ + + /* Use i18n context from ext.srna if possible (py operators). */ + if (ot->ext.srna) { + RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna)); + } + + operator_properties_init(ot); } void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata) { - wmOperatorType *data = (wmOperatorType *)userdata; - - /* only copy a couple of things, the rest is set by the macro registration */ - ot->name = data->name; - ot->idname = data->idname; - ot->description = data->description; - ot->flag |= data->flag; /* append flags to the one set by registration */ - ot->pyop_poll = data->pyop_poll; - ot->ui = data->ui; - ot->ext = data->ext; - - /* Use i18n context from ext.srna if possible (py operators). */ - if (ot->ext.srna) { - RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna)); - } - - operator_properties_init(ot); + wmOperatorType *data = (wmOperatorType *)userdata; + + /* only copy a couple of things, the rest is set by the macro registration */ + ot->name = data->name; + ot->idname = data->idname; + ot->description = data->description; + ot->flag |= data->flag; /* append flags to the one set by registration */ + ot->pyop_poll = data->pyop_poll; + ot->ui = data->ui; + ot->ext = data->ext; + + /* Use i18n context from ext.srna if possible (py operators). */ + if (ot->ext.srna) { + RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna)); + } + + operator_properties_init(ot); } PyObject *PYOP_wrap_macro_define(PyObject *UNUSED(self), PyObject *args) { - wmOperatorType *ot; - wmOperatorTypeMacro *otmacro; - PyObject *macro; - PointerRNA ptr_otmacro; - StructRNA *srna; - - const char *opname; - const char *macroname; - - if (!PyArg_ParseTuple(args, "Os:_bpy.ops.macro_define", ¯o, &opname)) { - return NULL; - } - - if (WM_operatortype_find(opname, true) == NULL) { - PyErr_Format(PyExc_ValueError, - "Macro Define: '%s' is not a valid operator id", - opname); - return NULL; - } - - /* identifiers */ - srna = pyrna_struct_as_srna((PyObject *)macro, false, "Macro Define:"); - if (srna == NULL) { - return NULL; - } - - macroname = RNA_struct_identifier(srna); - ot = WM_operatortype_find(macroname, true); - - if (!ot) { - PyErr_Format(PyExc_ValueError, - "Macro Define: '%s' is not a valid macro", - macroname); - return NULL; - } - - otmacro = WM_operatortype_macro_define(ot, opname); - - RNA_pointer_create(NULL, &RNA_OperatorMacro, otmacro, &ptr_otmacro); - - return pyrna_struct_CreatePyObject(&ptr_otmacro); + wmOperatorType *ot; + wmOperatorTypeMacro *otmacro; + PyObject *macro; + PointerRNA ptr_otmacro; + StructRNA *srna; + + const char *opname; + const char *macroname; + + if (!PyArg_ParseTuple(args, "Os:_bpy.ops.macro_define", ¯o, &opname)) { + return NULL; + } + + if (WM_operatortype_find(opname, true) == NULL) { + PyErr_Format(PyExc_ValueError, "Macro Define: '%s' is not a valid operator id", opname); + return NULL; + } + + /* identifiers */ + srna = pyrna_struct_as_srna((PyObject *)macro, false, "Macro Define:"); + if (srna == NULL) { + return NULL; + } + + macroname = RNA_struct_identifier(srna); + ot = WM_operatortype_find(macroname, true); + + if (!ot) { + PyErr_Format(PyExc_ValueError, "Macro Define: '%s' is not a valid macro", macroname); + return NULL; + } + + otmacro = WM_operatortype_macro_define(ot, opname); + + RNA_pointer_create(NULL, &RNA_OperatorMacro, otmacro, &ptr_otmacro); + + return pyrna_struct_CreatePyObject(&ptr_otmacro); } diff --git a/source/blender/python/intern/bpy_path.c b/source/blender/python/intern/bpy_path.c index 89f7fda9d4f..2ac59a694ec 100644 --- a/source/blender/python/intern/bpy_path.c +++ b/source/blender/python/intern/bpy_path.c @@ -35,26 +35,26 @@ extern const char *imb_ext_audio[]; /*----------------------------MODULE INIT-------------------------*/ static struct PyModuleDef _bpy_path_module_def = { - PyModuleDef_HEAD_INIT, - "_bpy_path", /* m_name */ - NULL, /* m_doc */ - 0, /* m_size */ - NULL, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + PyModuleDef_HEAD_INIT, + "_bpy_path", /* m_name */ + NULL, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; PyObject *BPyInit__bpy_path(void) { - PyObject *submodule; + PyObject *submodule; - submodule = PyModule_Create(&_bpy_path_module_def); + submodule = PyModule_Create(&_bpy_path_module_def); - PyModule_AddObject(submodule, "extensions_image", PyC_FrozenSetFromStrings(imb_ext_image)); - PyModule_AddObject(submodule, "extensions_movie", PyC_FrozenSetFromStrings(imb_ext_movie)); - PyModule_AddObject(submodule, "extensions_audio", PyC_FrozenSetFromStrings(imb_ext_audio)); + PyModule_AddObject(submodule, "extensions_image", PyC_FrozenSetFromStrings(imb_ext_image)); + PyModule_AddObject(submodule, "extensions_movie", PyC_FrozenSetFromStrings(imb_ext_movie)); + PyModule_AddObject(submodule, "extensions_audio", PyC_FrozenSetFromStrings(imb_ext_audio)); - return submodule; + return submodule; } diff --git a/source/blender/python/intern/bpy_path.h b/source/blender/python/intern/bpy_path.h index 7e38e3693fc..3f102ae2bb9 100644 --- a/source/blender/python/intern/bpy_path.h +++ b/source/blender/python/intern/bpy_path.h @@ -18,7 +18,6 @@ * \ingroup pythonintern */ - #ifndef __BPY_PATH_H__ #define __BPY_PATH_H__ diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 18a39f39e70..19315d9f2cc 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -22,7 +22,6 @@ * existing blender types. */ - #include <Python.h> #include "RNA_types.h" @@ -45,102 +44,110 @@ /* initial definition of callback slots we'll probably have more than 1 */ enum { - BPY_DATA_CB_SLOT_UPDATE = 0, - BPY_DATA_CB_SLOT_GET = 1, - BPY_DATA_CB_SLOT_SET = 2, - BPY_DATA_CB_SLOT_POLL = 3, - BPY_DATA_CB_SLOT_SIZE = 4, + BPY_DATA_CB_SLOT_UPDATE = 0, + BPY_DATA_CB_SLOT_GET = 1, + BPY_DATA_CB_SLOT_SET = 2, + BPY_DATA_CB_SLOT_POLL = 3, + BPY_DATA_CB_SLOT_SIZE = 4, }; static const EnumPropertyItem property_flag_items[] = { - {PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""}, - {PROP_SKIP_SAVE, "SKIP_SAVE", 0, "Skip Save", ""}, - {PROP_ANIMATABLE, "ANIMATABLE", 0, "Animatable", ""}, - {PROP_LIB_EXCEPTION, "LIBRARY_EDITABLE", 0, "Library Editable", ""}, - {PROP_PROPORTIONAL, "PROPORTIONAL", 0, "Adjust values proportionally to eachother", ""}, - {PROP_TEXTEDIT_UPDATE, "TEXTEDIT_UPDATE", 0, "Update on every keystroke in textedit 'mode'", ""}, - {0, NULL, 0, NULL, NULL}, + {PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""}, + {PROP_SKIP_SAVE, "SKIP_SAVE", 0, "Skip Save", ""}, + {PROP_ANIMATABLE, "ANIMATABLE", 0, "Animatable", ""}, + {PROP_LIB_EXCEPTION, "LIBRARY_EDITABLE", 0, "Library Editable", ""}, + {PROP_PROPORTIONAL, "PROPORTIONAL", 0, "Adjust values proportionally to eachother", ""}, + {PROP_TEXTEDIT_UPDATE, + "TEXTEDIT_UPDATE", + 0, + "Update on every keystroke in textedit 'mode'", + ""}, + {0, NULL, 0, NULL, NULL}, }; #define BPY_PROPDEF_OPTIONS_DOC \ -" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'LIBRARY_EDITABLE', 'PROPORTIONAL'," \ - "'TEXTEDIT_UPDATE'].\n" \ -" :type options: set\n" \ + " :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'LIBRARY_EDITABLE', " \ + "'PROPORTIONAL'," \ + "'TEXTEDIT_UPDATE'].\n" \ + " :type options: set\n" static const EnumPropertyItem property_flag_enum_items[] = { - {PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""}, - {PROP_SKIP_SAVE, "SKIP_SAVE", 0, "Skip Save", ""}, - {PROP_ANIMATABLE, "ANIMATABLE", 0, "Animatable", ""}, - {PROP_LIB_EXCEPTION, "LIBRARY_EDITABLE", 0, "Library Editable", ""}, - {PROP_ENUM_FLAG, "ENUM_FLAG", 0, "Enum Flag", ""}, - {0, NULL, 0, NULL, NULL}, + {PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""}, + {PROP_SKIP_SAVE, "SKIP_SAVE", 0, "Skip Save", ""}, + {PROP_ANIMATABLE, "ANIMATABLE", 0, "Animatable", ""}, + {PROP_LIB_EXCEPTION, "LIBRARY_EDITABLE", 0, "Library Editable", ""}, + {PROP_ENUM_FLAG, "ENUM_FLAG", 0, "Enum Flag", ""}, + {0, NULL, 0, NULL, NULL}, }; #define BPY_PROPDEF_OPTIONS_ENUM_DOC \ -" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'ENUM_FLAG', 'LIBRARY_EDITABLE'].\n" \ -" :type options: set\n" \ + " :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'ENUM_FLAG', " \ + "'LIBRARY_EDITABLE'].\n" \ + " :type options: set\n" /* subtypes */ /* XXX Keep in sync with rna_rna.c's rna_enum_property_subtype_items ??? * Currently it is not... */ static const EnumPropertyItem property_subtype_string_items[] = { - {PROP_FILEPATH, "FILE_PATH", 0, "File Path", ""}, - {PROP_DIRPATH, "DIR_PATH", 0, "Directory Path", ""}, - {PROP_FILENAME, "FILE_NAME", 0, "Filename", ""}, - {PROP_BYTESTRING, "BYTE_STRING", 0, "Byte String", ""}, - {PROP_PASSWORD, "PASSWORD", 0, "Password", "A string that is displayed hidden ('********')"}, - - {PROP_NONE, "NONE", 0, "None", ""}, - {0, NULL, 0, NULL, NULL}, + {PROP_FILEPATH, "FILE_PATH", 0, "File Path", ""}, + {PROP_DIRPATH, "DIR_PATH", 0, "Directory Path", ""}, + {PROP_FILENAME, "FILE_NAME", 0, "Filename", ""}, + {PROP_BYTESTRING, "BYTE_STRING", 0, "Byte String", ""}, + {PROP_PASSWORD, "PASSWORD", 0, "Password", "A string that is displayed hidden ('********')"}, + + {PROP_NONE, "NONE", 0, "None", ""}, + {0, NULL, 0, NULL, NULL}, }; #define BPY_PROPDEF_SUBTYPE_STRING_DOC \ -" :arg subtype: Enumerator in ['FILE_PATH', 'DIR_PATH', 'FILE_NAME', 'BYTE_STRING', 'PASSWORD', 'NONE'].\n" \ -" :type subtype: string\n" \ + " :arg subtype: Enumerator in ['FILE_PATH', 'DIR_PATH', 'FILE_NAME', 'BYTE_STRING', " \ + "'PASSWORD', 'NONE'].\n" \ + " :type subtype: string\n" static const EnumPropertyItem property_subtype_number_items[] = { - {PROP_PIXEL, "PIXEL", 0, "Pixel", ""}, - {PROP_UNSIGNED, "UNSIGNED", 0, "Unsigned", ""}, - {PROP_PERCENTAGE, "PERCENTAGE", 0, "Percentage", ""}, - {PROP_FACTOR, "FACTOR", 0, "Factor", ""}, - {PROP_ANGLE, "ANGLE", 0, "Angle", ""}, - {PROP_TIME, "TIME", 0, "Time", ""}, - {PROP_DISTANCE, "DISTANCE", 0, "Distance", ""}, - - {PROP_NONE, "NONE", 0, "None", ""}, - {0, NULL, 0, NULL, NULL}, + {PROP_PIXEL, "PIXEL", 0, "Pixel", ""}, + {PROP_UNSIGNED, "UNSIGNED", 0, "Unsigned", ""}, + {PROP_PERCENTAGE, "PERCENTAGE", 0, "Percentage", ""}, + {PROP_FACTOR, "FACTOR", 0, "Factor", ""}, + {PROP_ANGLE, "ANGLE", 0, "Angle", ""}, + {PROP_TIME, "TIME", 0, "Time", ""}, + {PROP_DISTANCE, "DISTANCE", 0, "Distance", ""}, + + {PROP_NONE, "NONE", 0, "None", ""}, + {0, NULL, 0, NULL, NULL}, }; #define BPY_PROPDEF_SUBTYPE_NUMBER_DOC \ -" :arg subtype: Enumerator in ['PIXEL', 'UNSIGNED', 'PERCENTAGE', 'FACTOR', 'ANGLE', 'TIME', 'DISTANCE', 'NONE'].\n" \ -" :type subtype: string\n" \ + " :arg subtype: Enumerator in ['PIXEL', 'UNSIGNED', 'PERCENTAGE', 'FACTOR', 'ANGLE', " \ + "'TIME', 'DISTANCE', 'NONE'].\n" \ + " :type subtype: string\n" static const EnumPropertyItem property_subtype_array_items[] = { - {PROP_COLOR, "COLOR", 0, "Color", ""}, - {PROP_TRANSLATION, "TRANSLATION", 0, "Translation", ""}, - {PROP_DIRECTION, "DIRECTION", 0, "Direction", ""}, - {PROP_VELOCITY, "VELOCITY", 0, "Velocity", ""}, - {PROP_ACCELERATION, "ACCELERATION", 0, "Acceleration", ""}, - {PROP_MATRIX, "MATRIX", 0, "Matrix", ""}, - {PROP_EULER, "EULER", 0, "Euler", ""}, - {PROP_QUATERNION, "QUATERNION", 0, "Quaternion", ""}, - {PROP_AXISANGLE, "AXISANGLE", 0, "Axis Angle", ""}, - {PROP_XYZ, "XYZ", 0, "XYZ", ""}, - {PROP_COLOR_GAMMA, "COLOR_GAMMA", 0, "Color Gamma", ""}, - {PROP_LAYER, "LAYER", 0, "Layer", ""}, - {PROP_LAYER_MEMBER, "LAYER_MEMBER", 0, "Layer Member", ""}, - {PROP_POWER, "POWER", 0, "Power", ""}, - - {PROP_NONE, "NONE", 0, "None", ""}, - {0, NULL, 0, NULL, NULL}, + {PROP_COLOR, "COLOR", 0, "Color", ""}, + {PROP_TRANSLATION, "TRANSLATION", 0, "Translation", ""}, + {PROP_DIRECTION, "DIRECTION", 0, "Direction", ""}, + {PROP_VELOCITY, "VELOCITY", 0, "Velocity", ""}, + {PROP_ACCELERATION, "ACCELERATION", 0, "Acceleration", ""}, + {PROP_MATRIX, "MATRIX", 0, "Matrix", ""}, + {PROP_EULER, "EULER", 0, "Euler", ""}, + {PROP_QUATERNION, "QUATERNION", 0, "Quaternion", ""}, + {PROP_AXISANGLE, "AXISANGLE", 0, "Axis Angle", ""}, + {PROP_XYZ, "XYZ", 0, "XYZ", ""}, + {PROP_COLOR_GAMMA, "COLOR_GAMMA", 0, "Color Gamma", ""}, + {PROP_LAYER, "LAYER", 0, "Layer", ""}, + {PROP_LAYER_MEMBER, "LAYER_MEMBER", 0, "Layer Member", ""}, + {PROP_POWER, "POWER", 0, "Power", ""}, + + {PROP_NONE, "NONE", 0, "None", ""}, + {0, NULL, 0, NULL, NULL}, }; #define BPY_PROPDEF_SUBTYPE_ARRAY_DOC \ -" :arg subtype: Enumerator in ['COLOR', 'TRANSLATION', 'DIRECTION', " \ - "'VELOCITY', 'ACCELERATION', 'MATRIX', 'EULER', 'QUATERNION', 'AXISANGLE', " \ - "'XYZ', 'COLOR_GAMMA', 'LAYER', 'LAYER_MEMBER', 'POWER', 'NONE'].\n" \ -" :type subtype: string\n" + " :arg subtype: Enumerator in ['COLOR', 'TRANSLATION', 'DIRECTION', " \ + "'VELOCITY', 'ACCELERATION', 'MATRIX', 'EULER', 'QUATERNION', 'AXISANGLE', " \ + "'XYZ', 'COLOR_GAMMA', 'LAYER', 'LAYER_MEMBER', 'POWER', 'NONE'].\n" \ + " :type subtype: string\n" /* PyObject's */ static PyObject *pymeth_BoolProperty = NULL; @@ -157,39 +164,39 @@ static PyObject *pymeth_RemoveProperty = NULL; static PyObject *pyrna_struct_as_instance(PointerRNA *ptr) { - PyObject *self = NULL; - /* first get self */ - /* operators can store their own instance for later use */ - if (ptr->data) { - void **instance = RNA_struct_instance(ptr); - - if (instance) { - if (*instance) { - self = *instance; - Py_INCREF(self); - } - } - } - - /* in most cases this will run */ - if (self == NULL) { - self = pyrna_struct_CreatePyObject(ptr); - } - - return self; + PyObject *self = NULL; + /* first get self */ + /* operators can store their own instance for later use */ + if (ptr->data) { + void **instance = RNA_struct_instance(ptr); + + if (instance) { + if (*instance) { + self = *instance; + Py_INCREF(self); + } + } + } + + /* in most cases this will run */ + if (self == NULL) { + self = pyrna_struct_CreatePyObject(ptr); + } + + return self; } static void bpy_prop_assign_flag(PropertyRNA *prop, const int flag) { - const int flag_mask = ((PROP_ANIMATABLE) & ~flag); + const int flag_mask = ((PROP_ANIMATABLE) & ~flag); - if (flag) { - RNA_def_property_flag(prop, flag); - } + if (flag) { + RNA_def_property_flag(prop, flag); + } - if (flag_mask) { - RNA_def_property_clear_flag(prop, flag_mask); - } + if (flag_mask) { + RNA_def_property_clear_flag(prop, flag_mask); + } } /* operators and classes use this so it can store the args given but defer @@ -197,3092 +204,3289 @@ static void bpy_prop_assign_flag(PropertyRNA *prop, const int flag) * the default args for that operator instance */ static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw) { - PyObject *ret = PyTuple_New(2); - PyTuple_SET_ITEM(ret, 0, func); - Py_INCREF(func); + PyObject *ret = PyTuple_New(2); + PyTuple_SET_ITEM(ret, 0, func); + Py_INCREF(func); - if (kw == NULL) { - kw = PyDict_New(); - } - else { - Py_INCREF(kw); - } + if (kw == NULL) { + kw = PyDict_New(); + } + else { + Py_INCREF(kw); + } - PyTuple_SET_ITEM(ret, 1, kw); + PyTuple_SET_ITEM(ret, 1, kw); - return ret; + return ret; } /* callbacks */ -static void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop) +static void bpy_prop_update_cb(struct bContext *C, + struct PointerRNA *ptr, + struct PropertyRNA *prop) { - PyGILState_STATE gilstate; - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - const bool is_write_ok = pyrna_write_check(); + PyGILState_STATE gilstate; + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + const bool is_write_ok = pyrna_write_check(); - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - bpy_context_set(C, &gilstate); + bpy_context_set(C, &gilstate); - py_func = py_data[BPY_DATA_CB_SLOT_UPDATE]; + py_func = py_data[BPY_DATA_CB_SLOT_UPDATE]; - args = PyTuple_New(2); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(2); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - PyTuple_SET_ITEM(args, 1, (PyObject *)bpy_context_module); - Py_INCREF(bpy_context_module); + PyTuple_SET_ITEM(args, 1, (PyObject *)bpy_context_module); + Py_INCREF(bpy_context_module); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - } - else { - if (ret != Py_None) { - PyErr_SetString(PyExc_ValueError, "the return value must be None"); - PyC_Err_PrintWithFunc(py_func); - } + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + } + else { + if (ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + PyC_Err_PrintWithFunc(py_func); + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - bpy_context_clear(C, &gilstate); + bpy_context_clear(C, &gilstate); - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } } static bool bpy_prop_boolean_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - bool value; + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + bool value; - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_GET]; + py_func = py_data[BPY_DATA_CB_SLOT_GET]; - args = PyTuple_New(1); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(1); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - value = false; - } - else { - int value_i = PyC_Long_AsBool(ret); + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + value = false; + } + else { + int value_i = PyC_Long_AsBool(ret); - if (value_i == -1 && PyErr_Occurred()) { - PyC_Err_PrintWithFunc(py_func); - value = false; - } - else { - value = (bool)value_i; - } + if (value_i == -1 && PyErr_Occurred()) { + PyC_Err_PrintWithFunc(py_func); + value = false; + } + else { + value = (bool)value_i; + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } - return value; + return value; } static void bpy_prop_boolean_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, bool value) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_SET]; + py_func = py_data[BPY_DATA_CB_SLOT_SET]; - args = PyTuple_New(2); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(2); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - PyTuple_SET_ITEM(args, 1, PyBool_FromLong(value)); + PyTuple_SET_ITEM(args, 1, PyBool_FromLong(value)); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - } - else { - if (ret != Py_None) { - PyErr_SetString(PyExc_ValueError, "the return value must be None"); - PyC_Err_PrintWithFunc(py_func); - } + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + } + else { + if (ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + PyC_Err_PrintWithFunc(py_func); + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } } -static bool bpy_prop_poll_cb(struct PointerRNA *self, PointerRNA candidate, struct PropertyRNA *prop) +static bool bpy_prop_poll_cb(struct PointerRNA *self, + PointerRNA candidate, + struct PropertyRNA *prop) { - PyObject *py_self; - PyObject *py_candidate; - PyObject *py_func; - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *args; - PyObject *ret; - bool result; - const int is_write_ok = pyrna_write_check(); - PyGILState_STATE gilstate = PyGILState_Ensure(); - - BLI_assert(self != NULL); - - py_self = pyrna_struct_as_instance(self); - py_candidate = pyrna_struct_as_instance(&candidate); - py_func = py_data[BPY_DATA_CB_SLOT_POLL]; - - if (!is_write_ok) { - pyrna_write_set(true); - } - - args = PyTuple_New(2); - PyTuple_SET_ITEM(args, 0, py_self); - PyTuple_SET_ITEM(args, 1, py_candidate); - - ret = PyObject_CallObject(py_func, args); - - Py_DECREF(args); - - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - result = false; - } - else { - result = PyObject_IsTrue(ret); - Py_DECREF(ret); - } - - PyGILState_Release(gilstate); - if (!is_write_ok) { - pyrna_write_set(false); - } - - return result; + PyObject *py_self; + PyObject *py_candidate; + PyObject *py_func; + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *args; + PyObject *ret; + bool result; + const int is_write_ok = pyrna_write_check(); + PyGILState_STATE gilstate = PyGILState_Ensure(); + + BLI_assert(self != NULL); + + py_self = pyrna_struct_as_instance(self); + py_candidate = pyrna_struct_as_instance(&candidate); + py_func = py_data[BPY_DATA_CB_SLOT_POLL]; + + if (!is_write_ok) { + pyrna_write_set(true); + } + + args = PyTuple_New(2); + PyTuple_SET_ITEM(args, 0, py_self); + PyTuple_SET_ITEM(args, 1, py_candidate); + + ret = PyObject_CallObject(py_func, args); + + Py_DECREF(args); + + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + result = false; + } + else { + result = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + + PyGILState_Release(gilstate); + if (!is_write_ok) { + pyrna_write_set(false); + } + + return result; } -static void bpy_prop_boolean_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, bool *values) +static void bpy_prop_boolean_array_get_cb(struct PointerRNA *ptr, + struct PropertyRNA *prop, + bool *values) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - int i, len = RNA_property_array_length(ptr, prop); - - BLI_assert(py_data != NULL); - - if (!is_write_ok) { - pyrna_write_set(true); - } - - use_gil = true; /* !PyC_IsInterpreterActive(); */ - - if (use_gil) { - gilstate = PyGILState_Ensure(); - } - - py_func = py_data[BPY_DATA_CB_SLOT_GET]; - - args = PyTuple_New(1); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); - - ret = PyObject_CallObject(py_func, args); - - Py_DECREF(args); - - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - - for (i = 0; i < len; ++i) { - values[i] = false; - } - } - else { - if (PyC_AsArray(values, ret, len, &PyBool_Type, false, "BoolVectorProperty get") == -1) { - PyC_Err_PrintWithFunc(py_func); - - for (i = 0; i < len; ++i) { - values[i] = false; - } - - /* PyC_AsArray decrements refcount internally on error */ - } - else { - Py_DECREF(ret); - } - } - - if (use_gil) { - PyGILState_Release(gilstate); - } - - if (!is_write_ok) { - pyrna_write_set(false); - } + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + int i, len = RNA_property_array_length(ptr, prop); + + BLI_assert(py_data != NULL); + + if (!is_write_ok) { + pyrna_write_set(true); + } + + use_gil = true; /* !PyC_IsInterpreterActive(); */ + + if (use_gil) { + gilstate = PyGILState_Ensure(); + } + + py_func = py_data[BPY_DATA_CB_SLOT_GET]; + + args = PyTuple_New(1); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); + + ret = PyObject_CallObject(py_func, args); + + Py_DECREF(args); + + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + + for (i = 0; i < len; ++i) { + values[i] = false; + } + } + else { + if (PyC_AsArray(values, ret, len, &PyBool_Type, false, "BoolVectorProperty get") == -1) { + PyC_Err_PrintWithFunc(py_func); + + for (i = 0; i < len; ++i) { + values[i] = false; + } + + /* PyC_AsArray decrements refcount internally on error */ + } + else { + Py_DECREF(ret); + } + } + + if (use_gil) { + PyGILState_Release(gilstate); + } + + if (!is_write_ok) { + pyrna_write_set(false); + } } -static void bpy_prop_boolean_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const bool *values) +static void bpy_prop_boolean_array_set_cb(struct PointerRNA *ptr, + struct PropertyRNA *prop, + const bool *values) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyObject *py_values; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - int len = RNA_property_array_length(ptr, prop); + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyObject *py_values; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + int len = RNA_property_array_length(ptr, prop); - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_SET]; + py_func = py_data[BPY_DATA_CB_SLOT_SET]; - args = PyTuple_New(2); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(2); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - py_values = PyC_Tuple_PackArray_Bool(values, len); - PyTuple_SET_ITEM(args, 1, py_values); + py_values = PyC_Tuple_PackArray_Bool(values, len); + PyTuple_SET_ITEM(args, 1, py_values); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - } - else { - if (ret != Py_None) { - PyErr_SetString(PyExc_ValueError, "the return value must be None"); - PyC_Err_PrintWithFunc(py_func); - } + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + } + else { + if (ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + PyC_Err_PrintWithFunc(py_func); + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } } static int bpy_prop_int_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - int value; + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + int value; - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_GET]; + py_func = py_data[BPY_DATA_CB_SLOT_GET]; - args = PyTuple_New(1); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(1); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - value = 0.0f; - } - else { - value = PyC_Long_AsI32(ret); + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + value = 0.0f; + } + else { + value = PyC_Long_AsI32(ret); - if (value == -1 && PyErr_Occurred()) { - PyC_Err_PrintWithFunc(py_func); - value = 0; - } + if (value == -1 && PyErr_Occurred()) { + PyC_Err_PrintWithFunc(py_func); + value = 0; + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } - return value; + return value; } static void bpy_prop_int_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_SET]; + py_func = py_data[BPY_DATA_CB_SLOT_SET]; - args = PyTuple_New(2); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(2); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - PyTuple_SET_ITEM(args, 1, PyLong_FromLong(value)); + PyTuple_SET_ITEM(args, 1, PyLong_FromLong(value)); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - } - else { - if (ret != Py_None) { - PyErr_SetString(PyExc_ValueError, "the return value must be None"); - PyC_Err_PrintWithFunc(py_func); - } + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + } + else { + if (ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + PyC_Err_PrintWithFunc(py_func); + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } } -static void bpy_prop_int_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values) +static void bpy_prop_int_array_get_cb(struct PointerRNA *ptr, + struct PropertyRNA *prop, + int *values) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - int i, len = RNA_property_array_length(ptr, prop); - - BLI_assert(py_data != NULL); - - if (!is_write_ok) { - pyrna_write_set(true); - } - - use_gil = true; /* !PyC_IsInterpreterActive(); */ - - if (use_gil) { - gilstate = PyGILState_Ensure(); - } - - py_func = py_data[BPY_DATA_CB_SLOT_GET]; - - args = PyTuple_New(1); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); - - ret = PyObject_CallObject(py_func, args); - - Py_DECREF(args); - - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - - for (i = 0; i < len; ++i) { - values[i] = 0; - } - } - else { - if (PyC_AsArray(values, ret, len, &PyLong_Type, false, "IntVectorProperty get") == -1) { - PyC_Err_PrintWithFunc(py_func); - - for (i = 0; i < len; ++i) { - values[i] = 0; - } - - /* PyC_AsArray decrements refcount internally on error */ - } - else { - Py_DECREF(ret); - } - } - - if (use_gil) { - PyGILState_Release(gilstate); - } - - if (!is_write_ok) { - pyrna_write_set(false); - } + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + int i, len = RNA_property_array_length(ptr, prop); + + BLI_assert(py_data != NULL); + + if (!is_write_ok) { + pyrna_write_set(true); + } + + use_gil = true; /* !PyC_IsInterpreterActive(); */ + + if (use_gil) { + gilstate = PyGILState_Ensure(); + } + + py_func = py_data[BPY_DATA_CB_SLOT_GET]; + + args = PyTuple_New(1); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); + + ret = PyObject_CallObject(py_func, args); + + Py_DECREF(args); + + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + + for (i = 0; i < len; ++i) { + values[i] = 0; + } + } + else { + if (PyC_AsArray(values, ret, len, &PyLong_Type, false, "IntVectorProperty get") == -1) { + PyC_Err_PrintWithFunc(py_func); + + for (i = 0; i < len; ++i) { + values[i] = 0; + } + + /* PyC_AsArray decrements refcount internally on error */ + } + else { + Py_DECREF(ret); + } + } + + if (use_gil) { + PyGILState_Release(gilstate); + } + + if (!is_write_ok) { + pyrna_write_set(false); + } } -static void bpy_prop_int_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values) +static void bpy_prop_int_array_set_cb(struct PointerRNA *ptr, + struct PropertyRNA *prop, + const int *values) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyObject *py_values; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - int len = RNA_property_array_length(ptr, prop); + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyObject *py_values; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + int len = RNA_property_array_length(ptr, prop); - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_SET]; + py_func = py_data[BPY_DATA_CB_SLOT_SET]; - args = PyTuple_New(2); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(2); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - py_values = PyC_Tuple_PackArray_I32(values, len); - PyTuple_SET_ITEM(args, 1, py_values); + py_values = PyC_Tuple_PackArray_I32(values, len); + PyTuple_SET_ITEM(args, 1, py_values); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - } - else { - if (ret != Py_None) { - PyErr_SetString(PyExc_ValueError, "the return value must be None"); - PyC_Err_PrintWithFunc(py_func); - } + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + } + else { + if (ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + PyC_Err_PrintWithFunc(py_func); + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } } static float bpy_prop_float_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - float value; + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + float value; - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_GET]; + py_func = py_data[BPY_DATA_CB_SLOT_GET]; - args = PyTuple_New(1); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(1); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - value = 0.0f; - } - else { - value = PyFloat_AsDouble(ret); + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + value = 0.0f; + } + else { + value = PyFloat_AsDouble(ret); - if (value == -1.0f && PyErr_Occurred()) { - PyC_Err_PrintWithFunc(py_func); - value = 0.0f; - } + if (value == -1.0f && PyErr_Occurred()) { + PyC_Err_PrintWithFunc(py_func); + value = 0.0f; + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } - return value; + return value; } static void bpy_prop_float_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, float value) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_SET]; + py_func = py_data[BPY_DATA_CB_SLOT_SET]; - args = PyTuple_New(2); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(2); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - PyTuple_SET_ITEM(args, 1, PyFloat_FromDouble(value)); + PyTuple_SET_ITEM(args, 1, PyFloat_FromDouble(value)); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - } - else { - if (ret != Py_None) { - PyErr_SetString(PyExc_ValueError, "the return value must be None"); - PyC_Err_PrintWithFunc(py_func); - } + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + } + else { + if (ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + PyC_Err_PrintWithFunc(py_func); + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } } -static void bpy_prop_float_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, float *values) +static void bpy_prop_float_array_get_cb(struct PointerRNA *ptr, + struct PropertyRNA *prop, + float *values) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - int i, len = RNA_property_array_length(ptr, prop); - - BLI_assert(py_data != NULL); - - if (!is_write_ok) { - pyrna_write_set(true); - } - - use_gil = true; /* !PyC_IsInterpreterActive(); */ - - if (use_gil) { - gilstate = PyGILState_Ensure(); - } - - py_func = py_data[BPY_DATA_CB_SLOT_GET]; - - args = PyTuple_New(1); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); - - ret = PyObject_CallObject(py_func, args); - - Py_DECREF(args); - - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - - for (i = 0; i < len; ++i) { - values[i] = 0.0f; - } - } - else { - if (PyC_AsArray(values, ret, len, &PyFloat_Type, false, "FloatVectorProperty get") == -1) { - PyC_Err_PrintWithFunc(py_func); - - for (i = 0; i < len; ++i) { - values[i] = 0.0f; - } - - /* PyC_AsArray decrements refcount internally on error */ - } - else { - Py_DECREF(ret); - } - } - - if (use_gil) { - PyGILState_Release(gilstate); - } - - if (!is_write_ok) { - pyrna_write_set(false); - } + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + int i, len = RNA_property_array_length(ptr, prop); + + BLI_assert(py_data != NULL); + + if (!is_write_ok) { + pyrna_write_set(true); + } + + use_gil = true; /* !PyC_IsInterpreterActive(); */ + + if (use_gil) { + gilstate = PyGILState_Ensure(); + } + + py_func = py_data[BPY_DATA_CB_SLOT_GET]; + + args = PyTuple_New(1); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); + + ret = PyObject_CallObject(py_func, args); + + Py_DECREF(args); + + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + + for (i = 0; i < len; ++i) { + values[i] = 0.0f; + } + } + else { + if (PyC_AsArray(values, ret, len, &PyFloat_Type, false, "FloatVectorProperty get") == -1) { + PyC_Err_PrintWithFunc(py_func); + + for (i = 0; i < len; ++i) { + values[i] = 0.0f; + } + + /* PyC_AsArray decrements refcount internally on error */ + } + else { + Py_DECREF(ret); + } + } + + if (use_gil) { + PyGILState_Release(gilstate); + } + + if (!is_write_ok) { + pyrna_write_set(false); + } } -static void bpy_prop_float_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const float *values) +static void bpy_prop_float_array_set_cb(struct PointerRNA *ptr, + struct PropertyRNA *prop, + const float *values) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyObject *py_values; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - int len = RNA_property_array_length(ptr, prop); + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyObject *py_values; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + int len = RNA_property_array_length(ptr, prop); - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_SET]; + py_func = py_data[BPY_DATA_CB_SLOT_SET]; - args = PyTuple_New(2); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(2); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - py_values = PyC_Tuple_PackArray_F32(values, len); - PyTuple_SET_ITEM(args, 1, py_values); + py_values = PyC_Tuple_PackArray_F32(values, len); + PyTuple_SET_ITEM(args, 1, py_values); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - } - else { - if (ret != Py_None) { - PyErr_SetString(PyExc_ValueError, "the return value must be None"); - PyC_Err_PrintWithFunc(py_func); - } + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + } + else { + if (ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + PyC_Err_PrintWithFunc(py_func); + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } } static void bpy_prop_string_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, char *value) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - - BLI_assert(py_data != NULL); - - if (!is_write_ok) { - pyrna_write_set(true); - } - - use_gil = true; /* !PyC_IsInterpreterActive(); */ - - if (use_gil) { - gilstate = PyGILState_Ensure(); - } - - py_func = py_data[BPY_DATA_CB_SLOT_GET]; - - args = PyTuple_New(1); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); - - ret = PyObject_CallObject(py_func, args); - - Py_DECREF(args); - - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - value[0] = '\0'; - } - else if (!PyUnicode_Check(ret)) { - PyErr_Format(PyExc_TypeError, - "return value must be a string, not %.200s", - Py_TYPE(ret)->tp_name); - PyC_Err_PrintWithFunc(py_func); - value[0] = '\0'; - Py_DECREF(ret); - } - else { - Py_ssize_t length; - const char *buffer = _PyUnicode_AsStringAndSize(ret, &length); - memcpy(value, buffer, length + 1); - Py_DECREF(ret); - } - - if (use_gil) { - PyGILState_Release(gilstate); - } - - if (!is_write_ok) { - pyrna_write_set(false); - } + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + + BLI_assert(py_data != NULL); + + if (!is_write_ok) { + pyrna_write_set(true); + } + + use_gil = true; /* !PyC_IsInterpreterActive(); */ + + if (use_gil) { + gilstate = PyGILState_Ensure(); + } + + py_func = py_data[BPY_DATA_CB_SLOT_GET]; + + args = PyTuple_New(1); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); + + ret = PyObject_CallObject(py_func, args); + + Py_DECREF(args); + + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + value[0] = '\0'; + } + else if (!PyUnicode_Check(ret)) { + PyErr_Format( + PyExc_TypeError, "return value must be a string, not %.200s", Py_TYPE(ret)->tp_name); + PyC_Err_PrintWithFunc(py_func); + value[0] = '\0'; + Py_DECREF(ret); + } + else { + Py_ssize_t length; + const char *buffer = _PyUnicode_AsStringAndSize(ret, &length); + memcpy(value, buffer, length + 1); + Py_DECREF(ret); + } + + if (use_gil) { + PyGILState_Release(gilstate); + } + + if (!is_write_ok) { + pyrna_write_set(false); + } } static int bpy_prop_string_length_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - int length; - - BLI_assert(py_data != NULL); - - if (!is_write_ok) { - pyrna_write_set(true); - } - - use_gil = true; /* !PyC_IsInterpreterActive(); */ - - if (use_gil) { - gilstate = PyGILState_Ensure(); - } - - py_func = py_data[BPY_DATA_CB_SLOT_GET]; - - args = PyTuple_New(1); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); - - ret = PyObject_CallObject(py_func, args); - - Py_DECREF(args); - - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - length = 0; - } - else if (!PyUnicode_Check(ret)) { - PyErr_Format(PyExc_TypeError, - "return value must be a string, not %.200s", - Py_TYPE(ret)->tp_name); - PyC_Err_PrintWithFunc(py_func); - length = 0; - Py_DECREF(ret); - } - else { - Py_ssize_t length_ssize_t = 0; - _PyUnicode_AsStringAndSize(ret, &length_ssize_t); - length = length_ssize_t; - Py_DECREF(ret); - } - - if (use_gil) { - PyGILState_Release(gilstate); - } - - if (!is_write_ok) { - pyrna_write_set(false); - } - - return length; + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + int length; + + BLI_assert(py_data != NULL); + + if (!is_write_ok) { + pyrna_write_set(true); + } + + use_gil = true; /* !PyC_IsInterpreterActive(); */ + + if (use_gil) { + gilstate = PyGILState_Ensure(); + } + + py_func = py_data[BPY_DATA_CB_SLOT_GET]; + + args = PyTuple_New(1); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); + + ret = PyObject_CallObject(py_func, args); + + Py_DECREF(args); + + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + length = 0; + } + else if (!PyUnicode_Check(ret)) { + PyErr_Format( + PyExc_TypeError, "return value must be a string, not %.200s", Py_TYPE(ret)->tp_name); + PyC_Err_PrintWithFunc(py_func); + length = 0; + Py_DECREF(ret); + } + else { + Py_ssize_t length_ssize_t = 0; + _PyUnicode_AsStringAndSize(ret, &length_ssize_t); + length = length_ssize_t; + Py_DECREF(ret); + } + + if (use_gil) { + PyGILState_Release(gilstate); + } + + if (!is_write_ok) { + pyrna_write_set(false); + } + + return length; } -static void bpy_prop_string_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const char *value) +static void bpy_prop_string_set_cb(struct PointerRNA *ptr, + struct PropertyRNA *prop, + const char *value) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - PyObject *py_value; - - BLI_assert(py_data != NULL); - - if (!is_write_ok) { - pyrna_write_set(true); - } - - use_gil = true; /* !PyC_IsInterpreterActive(); */ - - if (use_gil) { - gilstate = PyGILState_Ensure(); - } - - py_func = py_data[BPY_DATA_CB_SLOT_SET]; - - args = PyTuple_New(2); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); - - py_value = PyUnicode_FromString(value); - if (!py_value) { - PyErr_SetString(PyExc_ValueError, "the return value must be a string"); - PyC_Err_PrintWithFunc(py_func); - } - else { - PyTuple_SET_ITEM(args, 1, py_value); - } - - ret = PyObject_CallObject(py_func, args); - - Py_DECREF(args); - - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - } - else { - if (ret != Py_None) { - PyErr_SetString(PyExc_ValueError, "the return value must be None"); - PyC_Err_PrintWithFunc(py_func); - } - - Py_DECREF(ret); - } - - if (use_gil) { - PyGILState_Release(gilstate); - } - - if (!is_write_ok) { - pyrna_write_set(false); - } + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + PyObject *py_value; + + BLI_assert(py_data != NULL); + + if (!is_write_ok) { + pyrna_write_set(true); + } + + use_gil = true; /* !PyC_IsInterpreterActive(); */ + + if (use_gil) { + gilstate = PyGILState_Ensure(); + } + + py_func = py_data[BPY_DATA_CB_SLOT_SET]; + + args = PyTuple_New(2); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); + + py_value = PyUnicode_FromString(value); + if (!py_value) { + PyErr_SetString(PyExc_ValueError, "the return value must be a string"); + PyC_Err_PrintWithFunc(py_func); + } + else { + PyTuple_SET_ITEM(args, 1, py_value); + } + + ret = PyObject_CallObject(py_func, args); + + Py_DECREF(args); + + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + } + else { + if (ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + PyC_Err_PrintWithFunc(py_func); + } + + Py_DECREF(ret); + } + + if (use_gil) { + PyGILState_Release(gilstate); + } + + if (!is_write_ok) { + pyrna_write_set(false); + } } static int bpy_prop_enum_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); - int value; + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); + int value; - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_GET]; + py_func = py_data[BPY_DATA_CB_SLOT_GET]; - args = PyTuple_New(1); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(1); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - value = RNA_property_enum_get_default(ptr, prop); - } - else { - value = PyC_Long_AsI32(ret); + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + value = RNA_property_enum_get_default(ptr, prop); + } + else { + value = PyC_Long_AsI32(ret); - if (value == -1 && PyErr_Occurred()) { - PyC_Err_PrintWithFunc(py_func); - value = RNA_property_enum_get_default(ptr, prop); - } + if (value == -1 && PyErr_Occurred()) { + PyC_Err_PrintWithFunc(py_func); + value = RNA_property_enum_get_default(ptr, prop); + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } - return value; + return value; } static void bpy_prop_enum_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value) { - PyObject **py_data = RNA_property_py_data_get(prop); - PyObject *py_func; - PyObject *args; - PyObject *self; - PyObject *ret; - PyGILState_STATE gilstate; - bool use_gil; - const bool is_write_ok = pyrna_write_check(); + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + PyGILState_STATE gilstate; + bool use_gil; + const bool is_write_ok = pyrna_write_check(); - BLI_assert(py_data != NULL); + BLI_assert(py_data != NULL); - if (!is_write_ok) { - pyrna_write_set(true); - } + if (!is_write_ok) { + pyrna_write_set(true); + } - use_gil = true; /* !PyC_IsInterpreterActive(); */ + use_gil = true; /* !PyC_IsInterpreterActive(); */ - if (use_gil) { - gilstate = PyGILState_Ensure(); - } + if (use_gil) { + gilstate = PyGILState_Ensure(); + } - py_func = py_data[BPY_DATA_CB_SLOT_SET]; + py_func = py_data[BPY_DATA_CB_SLOT_SET]; - args = PyTuple_New(2); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); + args = PyTuple_New(2); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); - PyTuple_SET_ITEM(args, 1, PyLong_FromLong(value)); + PyTuple_SET_ITEM(args, 1, PyLong_FromLong(value)); - ret = PyObject_CallObject(py_func, args); + ret = PyObject_CallObject(py_func, args); - Py_DECREF(args); + Py_DECREF(args); - if (ret == NULL) { - PyC_Err_PrintWithFunc(py_func); - } - else { - if (ret != Py_None) { - PyErr_SetString(PyExc_ValueError, "the return value must be None"); - PyC_Err_PrintWithFunc(py_func); - } + if (ret == NULL) { + PyC_Err_PrintWithFunc(py_func); + } + else { + if (ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + PyC_Err_PrintWithFunc(py_func); + } - Py_DECREF(ret); - } + Py_DECREF(ret); + } - if (use_gil) { - PyGILState_Release(gilstate); - } + if (use_gil) { + PyGILState_Release(gilstate); + } - if (!is_write_ok) { - pyrna_write_set(false); - } + if (!is_write_ok) { + pyrna_write_set(false); + } } /* utility function we need for parsing int's in an if statement */ static int py_long_as_int(PyObject *py_long, int *r_int) { - if (PyLong_CheckExact(py_long)) { - *r_int = (int)PyLong_AS_LONG(py_long); - return 0; - } - else { - return -1; - } + if (PyLong_CheckExact(py_long)) { + *r_int = (int)PyLong_AS_LONG(py_long); + return 0; + } + else { + return -1; + } } #if 0 /* copies orig to buf, then sets orig to buf, returns copy length */ static size_t strswapbufcpy(char *buf, const char **orig) { - const char *src = *orig; - char *dst = buf; - size_t i = 0; - *orig = buf; - while ((*dst = *src)) { dst++; src++; i++; } - return i + 1; /* include '\0' */ + const char *src = *orig; + char *dst = buf; + size_t i = 0; + *orig = buf; + while ((*dst = *src)) { dst++; src++; i++; } + return i + 1; /* include '\0' */ } #endif static int icon_id_from_name(const char *name) { - const EnumPropertyItem *item; - int id; - - if (name[0]) { - for (item = rna_enum_icon_items, id = 0; item->identifier; item++, id++) { - if (STREQ(item->name, name)) { - return item->value; - } - } - } - - return 0; + const EnumPropertyItem *item; + int id; + + if (name[0]) { + for (item = rna_enum_icon_items, id = 0; item->identifier; item++, id++) { + if (STREQ(item->name, name)) { + return item->value; + } + } + } + + return 0; } -static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, int *defvalue, const bool is_enum_flag) +static const EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, + PyObject *def, + int *defvalue, + const bool is_enum_flag) { - EnumPropertyItem *items; - PyObject *item; - const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast); - PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast); - Py_ssize_t totbuf = 0; - int i; - short def_used = 0; - const char *def_cmp = NULL; - - if (is_enum_flag) { - if (seq_len > RNA_ENUM_BITFLAG_SIZE) { - PyErr_SetString(PyExc_TypeError, - "EnumProperty(...): maximum " - STRINGIFY(RNA_ENUM_BITFLAG_SIZE) - " members for a ENUM_FLAG type property"); - return NULL; - } - if (def && !PySet_Check(def)) { - PyErr_Format(PyExc_TypeError, - "EnumProperty(...): default option must be a 'set' " - "type when ENUM_FLAG is enabled, not a '%.200s'", - Py_TYPE(def)->tp_name); - return NULL; - } - } - else { - if (def) { - def_cmp = _PyUnicode_AsString(def); - if (def_cmp == NULL) { - PyErr_Format(PyExc_TypeError, - "EnumProperty(...): default option must be a 'str' " - "type when ENUM_FLAG is disabled, not a '%.200s'", - Py_TYPE(def)->tp_name); - return NULL; - } - } - } - - /* blank value */ - *defvalue = 0; - - items = MEM_callocN(sizeof(EnumPropertyItem) * (seq_len + 1), "enum_items_from_py1"); - - for (i = 0; i < seq_len; i++) { - EnumPropertyItem tmp = {0, "", 0, "", ""}; - const char *tmp_icon = NULL; - Py_ssize_t item_size; - Py_ssize_t id_str_size; - Py_ssize_t name_str_size; - Py_ssize_t desc_str_size; - - item = seq_fast_items[i]; - - if ((PyTuple_CheckExact(item)) && - (item_size = PyTuple_GET_SIZE(item)) && - (item_size >= 3 && item_size <= 5) && - (tmp.identifier = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && - (tmp.name = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && - (tmp.description = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) && - /* TODO, number isn't ensured to be unique from the script author */ - (item_size != 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1) && - (item_size != 5 || ((py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.icon) != -1 || - (tmp_icon = _PyUnicode_AsString(PyTuple_GET_ITEM(item, 3)))) && - py_long_as_int(PyTuple_GET_ITEM(item, 4), &tmp.value) != -1))) - { - if (is_enum_flag) { - if (item_size < 4) { - tmp.value = 1 << i; - } - - if (def && PySet_Contains(def, PyTuple_GET_ITEM(item, 0))) { - *defvalue |= tmp.value; - def_used++; - } - } - else { - if (item_size < 4) { - tmp.value = i; - } - - if (def && def_used == 0 && STREQ(def_cmp, tmp.identifier)) { - *defvalue = tmp.value; - def_used++; /* only ever 1 */ - } - } - - if (tmp_icon) { - tmp.icon = icon_id_from_name(tmp_icon); - } - - items[i] = tmp; - - /* calculate combine string length */ - totbuf += id_str_size + name_str_size + desc_str_size + 3; /* 3 is for '\0's */ - } - else { - MEM_freeN(items); - PyErr_SetString(PyExc_TypeError, - "EnumProperty(...): expected a tuple containing " - "(identifier, name, description) and optionally an " - "icon name and unique number"); - return NULL; - } - - } - - if (is_enum_flag) { - /* strict check that all set members were used */ - if (def && def_used != PySet_GET_SIZE(def)) { - MEM_freeN(items); - - PyErr_Format(PyExc_TypeError, - "EnumProperty(..., default={...}): set has %d unused member(s)", - PySet_GET_SIZE(def) - def_used); - return NULL; - } - } - else { - if (def && def_used == 0) { - MEM_freeN(items); - - PyErr_Format(PyExc_TypeError, - "EnumProperty(..., default=\'%s\'): not found in enum members", - def_cmp); - return NULL; - } - } - - /* disabled duplicating strings because the array can still be freed and - * the strings from it referenced, for now we can't support dynamically - * created strings from python. */ + EnumPropertyItem *items; + PyObject *item; + const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast); + PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast); + Py_ssize_t totbuf = 0; + int i; + short def_used = 0; + const char *def_cmp = NULL; + + if (is_enum_flag) { + if (seq_len > RNA_ENUM_BITFLAG_SIZE) { + PyErr_SetString(PyExc_TypeError, + "EnumProperty(...): maximum " STRINGIFY( + RNA_ENUM_BITFLAG_SIZE) " members for a ENUM_FLAG type property"); + return NULL; + } + if (def && !PySet_Check(def)) { + PyErr_Format(PyExc_TypeError, + "EnumProperty(...): default option must be a 'set' " + "type when ENUM_FLAG is enabled, not a '%.200s'", + Py_TYPE(def)->tp_name); + return NULL; + } + } + else { + if (def) { + def_cmp = _PyUnicode_AsString(def); + if (def_cmp == NULL) { + PyErr_Format(PyExc_TypeError, + "EnumProperty(...): default option must be a 'str' " + "type when ENUM_FLAG is disabled, not a '%.200s'", + Py_TYPE(def)->tp_name); + return NULL; + } + } + } + + /* blank value */ + *defvalue = 0; + + items = MEM_callocN(sizeof(EnumPropertyItem) * (seq_len + 1), "enum_items_from_py1"); + + for (i = 0; i < seq_len; i++) { + EnumPropertyItem tmp = {0, "", 0, "", ""}; + const char *tmp_icon = NULL; + Py_ssize_t item_size; + Py_ssize_t id_str_size; + Py_ssize_t name_str_size; + Py_ssize_t desc_str_size; + + item = seq_fast_items[i]; + + if ((PyTuple_CheckExact(item)) && (item_size = PyTuple_GET_SIZE(item)) && + (item_size >= 3 && item_size <= 5) && + (tmp.identifier = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && + (tmp.name = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && + (tmp.description = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), + &desc_str_size)) && + /* TODO, number isn't ensured to be unique from the script author */ + (item_size != 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1) && + (item_size != 5 || ((py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.icon) != -1 || + (tmp_icon = _PyUnicode_AsString(PyTuple_GET_ITEM(item, 3)))) && + py_long_as_int(PyTuple_GET_ITEM(item, 4), &tmp.value) != -1))) { + if (is_enum_flag) { + if (item_size < 4) { + tmp.value = 1 << i; + } + + if (def && PySet_Contains(def, PyTuple_GET_ITEM(item, 0))) { + *defvalue |= tmp.value; + def_used++; + } + } + else { + if (item_size < 4) { + tmp.value = i; + } + + if (def && def_used == 0 && STREQ(def_cmp, tmp.identifier)) { + *defvalue = tmp.value; + def_used++; /* only ever 1 */ + } + } + + if (tmp_icon) { + tmp.icon = icon_id_from_name(tmp_icon); + } + + items[i] = tmp; + + /* calculate combine string length */ + totbuf += id_str_size + name_str_size + desc_str_size + 3; /* 3 is for '\0's */ + } + else { + MEM_freeN(items); + PyErr_SetString(PyExc_TypeError, + "EnumProperty(...): expected a tuple containing " + "(identifier, name, description) and optionally an " + "icon name and unique number"); + return NULL; + } + } + + if (is_enum_flag) { + /* strict check that all set members were used */ + if (def && def_used != PySet_GET_SIZE(def)) { + MEM_freeN(items); + + PyErr_Format(PyExc_TypeError, + "EnumProperty(..., default={...}): set has %d unused member(s)", + PySet_GET_SIZE(def) - def_used); + return NULL; + } + } + else { + if (def && def_used == 0) { + MEM_freeN(items); + + PyErr_Format(PyExc_TypeError, + "EnumProperty(..., default=\'%s\'): not found in enum members", + def_cmp); + return NULL; + } + } + + /* disabled duplicating strings because the array can still be freed and + * the strings from it referenced, for now we can't support dynamically + * created strings from python. */ #if 0 - /* this would all work perfectly _but_ the python strings may be freed - * immediately after use, so we need to duplicate them, ugh. - * annoying because it works most of the time without this. */ - { - EnumPropertyItem *items_dup = MEM_mallocN((sizeof(EnumPropertyItem) * (seq_len + 1)) + (sizeof(char) * totbuf), - "enum_items_from_py2"); - EnumPropertyItem *items_ptr = items_dup; - char *buf = ((char *)items_dup) + (sizeof(EnumPropertyItem) * (seq_len + 1)); - memcpy(items_dup, items, sizeof(EnumPropertyItem) * (seq_len + 1)); - for (i = 0; i < seq_len; i++, items_ptr++) { - buf += strswapbufcpy(buf, &items_ptr->identifier); - buf += strswapbufcpy(buf, &items_ptr->name); - buf += strswapbufcpy(buf, &items_ptr->description); - } - MEM_freeN(items); - items = items_dup; - } - /* end string duplication */ + /* this would all work perfectly _but_ the python strings may be freed + * immediately after use, so we need to duplicate them, ugh. + * annoying because it works most of the time without this. */ + { + EnumPropertyItem *items_dup = MEM_mallocN((sizeof(EnumPropertyItem) * (seq_len + 1)) + (sizeof(char) * totbuf), + "enum_items_from_py2"); + EnumPropertyItem *items_ptr = items_dup; + char *buf = ((char *)items_dup) + (sizeof(EnumPropertyItem) * (seq_len + 1)); + memcpy(items_dup, items, sizeof(EnumPropertyItem) * (seq_len + 1)); + for (i = 0; i < seq_len; i++, items_ptr++) { + buf += strswapbufcpy(buf, &items_ptr->identifier); + buf += strswapbufcpy(buf, &items_ptr->name); + buf += strswapbufcpy(buf, &items_ptr->description); + } + MEM_freeN(items); + items = items_dup; + } + /* end string duplication */ #endif - return items; + return items; } -static const EnumPropertyItem *bpy_prop_enum_itemf_cb(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free) +static const EnumPropertyItem *bpy_prop_enum_itemf_cb(struct bContext *C, + PointerRNA *ptr, + PropertyRNA *prop, + bool *r_free) { - PyGILState_STATE gilstate; - - PyObject *py_func = RNA_property_enum_py_data_get(prop); - PyObject *self = NULL; - PyObject *args; - PyObject *items; /* returned from the function call */ - - const EnumPropertyItem *eitems = NULL; - int err = 0; - - if (C) { - bpy_context_set(C, &gilstate); - } - else { - gilstate = PyGILState_Ensure(); - } - - args = PyTuple_New(2); - self = pyrna_struct_as_instance(ptr); - PyTuple_SET_ITEM(args, 0, self); - - /* now get the context */ - if (C) { - PyTuple_SET_ITEM(args, 1, (PyObject *)bpy_context_module); - Py_INCREF(bpy_context_module); - } - else { - PyTuple_SET_ITEM(args, 1, Py_None); - Py_INCREF(Py_None); - } - - items = PyObject_CallObject(py_func, args); - - Py_DECREF(args); - - if (items == NULL) { - err = -1; - } - else { - PyObject *items_fast; - int defvalue_dummy = 0; - - if (!(items_fast = PySequence_Fast(items, "EnumProperty(...): " - "return value from the callback was not a sequence"))) - { - err = -1; - } - else { - eitems = enum_items_from_py(items_fast, NULL, &defvalue_dummy, - (RNA_property_flag(prop) & PROP_ENUM_FLAG) != 0); - - Py_DECREF(items_fast); - - if (!eitems) { - err = -1; - } - } - - Py_DECREF(items); - } - - if (err != -1) { /* worked */ - *r_free = true; - } - else { - PyC_Err_PrintWithFunc(py_func); - - eitems = DummyRNA_NULL_items; - } - - if (C) { - bpy_context_clear(C, &gilstate); - } - else { - PyGILState_Release(gilstate); - } - - return eitems; + PyGILState_STATE gilstate; + + PyObject *py_func = RNA_property_enum_py_data_get(prop); + PyObject *self = NULL; + PyObject *args; + PyObject *items; /* returned from the function call */ + + const EnumPropertyItem *eitems = NULL; + int err = 0; + + if (C) { + bpy_context_set(C, &gilstate); + } + else { + gilstate = PyGILState_Ensure(); + } + + args = PyTuple_New(2); + self = pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); + + /* now get the context */ + if (C) { + PyTuple_SET_ITEM(args, 1, (PyObject *)bpy_context_module); + Py_INCREF(bpy_context_module); + } + else { + PyTuple_SET_ITEM(args, 1, Py_None); + Py_INCREF(Py_None); + } + + items = PyObject_CallObject(py_func, args); + + Py_DECREF(args); + + if (items == NULL) { + err = -1; + } + else { + PyObject *items_fast; + int defvalue_dummy = 0; + + if (!(items_fast = PySequence_Fast(items, + "EnumProperty(...): " + "return value from the callback was not a sequence"))) { + err = -1; + } + else { + eitems = enum_items_from_py( + items_fast, NULL, &defvalue_dummy, (RNA_property_flag(prop) & PROP_ENUM_FLAG) != 0); + + Py_DECREF(items_fast); + + if (!eitems) { + err = -1; + } + } + + Py_DECREF(items); + } + + if (err != -1) { /* worked */ + *r_free = true; + } + else { + PyC_Err_PrintWithFunc(py_func); + + eitems = DummyRNA_NULL_items; + } + + if (C) { + bpy_context_clear(C, &gilstate); + } + else { + PyGILState_Release(gilstate); + } + + return eitems; } static int bpy_prop_callback_check(PyObject *py_func, const char *keyword, int argcount) { - if (py_func && py_func != Py_None) { - if (!PyFunction_Check(py_func)) { - PyErr_Format(PyExc_TypeError, - "%s keyword: expected a function type, not a %.200s", - keyword, Py_TYPE(py_func)->tp_name); - return -1; - } - else { - PyCodeObject *f_code = (PyCodeObject *)PyFunction_GET_CODE(py_func); - if (f_code->co_argcount != argcount) { - PyErr_Format(PyExc_TypeError, - "%s keyword: expected a function taking %d arguments, not %d", - keyword, argcount, f_code->co_argcount); - return -1; - } - } - } - - return 0; + if (py_func && py_func != Py_None) { + if (!PyFunction_Check(py_func)) { + PyErr_Format(PyExc_TypeError, + "%s keyword: expected a function type, not a %.200s", + keyword, + Py_TYPE(py_func)->tp_name); + return -1; + } + else { + PyCodeObject *f_code = (PyCodeObject *)PyFunction_GET_CODE(py_func); + if (f_code->co_argcount != argcount) { + PyErr_Format(PyExc_TypeError, + "%s keyword: expected a function taking %d arguments, not %d", + keyword, + argcount, + f_code->co_argcount); + return -1; + } + } + } + + return 0; } static PyObject **bpy_prop_py_data_get(struct PropertyRNA *prop) { - PyObject **py_data = RNA_property_py_data_get(prop); - if (!py_data) { - py_data = MEM_callocN(sizeof(PyObject *) * BPY_DATA_CB_SLOT_SIZE, __func__); - RNA_def_py_data(prop, py_data); - } - return py_data; + PyObject **py_data = RNA_property_py_data_get(prop); + if (!py_data) { + py_data = MEM_callocN(sizeof(PyObject *) * BPY_DATA_CB_SLOT_SIZE, __func__); + RNA_def_py_data(prop, py_data); + } + return py_data; } static void bpy_prop_callback_assign_update(struct PropertyRNA *prop, PyObject *update_cb) { - /* assume this is already checked for type and arg length */ - if (update_cb && update_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + /* assume this is already checked for type and arg length */ + if (update_cb && update_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - RNA_def_property_update_runtime(prop, (void *)bpy_prop_update_cb); - py_data[BPY_DATA_CB_SLOT_UPDATE] = update_cb; + RNA_def_property_update_runtime(prop, (void *)bpy_prop_update_cb); + py_data[BPY_DATA_CB_SLOT_UPDATE] = update_cb; - RNA_def_property_flag(prop, PROP_CONTEXT_PROPERTY_UPDATE); - } + RNA_def_property_flag(prop, PROP_CONTEXT_PROPERTY_UPDATE); + } } static void bpy_prop_callback_assign_pointer(struct PropertyRNA *prop, PyObject *poll_cb) { - if (poll_cb && poll_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (poll_cb && poll_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - RNA_def_property_poll_runtime(prop, (void *) bpy_prop_poll_cb); - py_data[BPY_DATA_CB_SLOT_POLL] = poll_cb; - } + RNA_def_property_poll_runtime(prop, (void *)bpy_prop_poll_cb); + py_data[BPY_DATA_CB_SLOT_POLL] = poll_cb; + } } -static void bpy_prop_callback_assign_boolean(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb) +static void bpy_prop_callback_assign_boolean(struct PropertyRNA *prop, + PyObject *get_cb, + PyObject *set_cb) { - BooleanPropertyGetFunc rna_get_cb = NULL; - BooleanPropertySetFunc rna_set_cb = NULL; + BooleanPropertyGetFunc rna_get_cb = NULL; + BooleanPropertySetFunc rna_set_cb = NULL; - if (get_cb && get_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (get_cb && get_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_get_cb = bpy_prop_boolean_get_cb; - py_data[BPY_DATA_CB_SLOT_GET] = get_cb; - } + rna_get_cb = bpy_prop_boolean_get_cb; + py_data[BPY_DATA_CB_SLOT_GET] = get_cb; + } - if (set_cb && set_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (set_cb && set_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_set_cb = bpy_prop_boolean_set_cb; - py_data[BPY_DATA_CB_SLOT_SET] = set_cb; - } + rna_set_cb = bpy_prop_boolean_set_cb; + py_data[BPY_DATA_CB_SLOT_SET] = set_cb; + } - RNA_def_property_boolean_funcs_runtime(prop, rna_get_cb, rna_set_cb); + RNA_def_property_boolean_funcs_runtime(prop, rna_get_cb, rna_set_cb); } -static void bpy_prop_callback_assign_boolean_array(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb) +static void bpy_prop_callback_assign_boolean_array(struct PropertyRNA *prop, + PyObject *get_cb, + PyObject *set_cb) { - BooleanArrayPropertyGetFunc rna_get_cb = NULL; - BooleanArrayPropertySetFunc rna_set_cb = NULL; + BooleanArrayPropertyGetFunc rna_get_cb = NULL; + BooleanArrayPropertySetFunc rna_set_cb = NULL; - if (get_cb && get_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (get_cb && get_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_get_cb = bpy_prop_boolean_array_get_cb; - py_data[BPY_DATA_CB_SLOT_GET] = get_cb; - } + rna_get_cb = bpy_prop_boolean_array_get_cb; + py_data[BPY_DATA_CB_SLOT_GET] = get_cb; + } - if (set_cb && set_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (set_cb && set_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_set_cb = bpy_prop_boolean_array_set_cb; - py_data[BPY_DATA_CB_SLOT_SET] = set_cb; - } + rna_set_cb = bpy_prop_boolean_array_set_cb; + py_data[BPY_DATA_CB_SLOT_SET] = set_cb; + } - RNA_def_property_boolean_array_funcs_runtime(prop, rna_get_cb, rna_set_cb); + RNA_def_property_boolean_array_funcs_runtime(prop, rna_get_cb, rna_set_cb); } -static void bpy_prop_callback_assign_int(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb) +static void bpy_prop_callback_assign_int(struct PropertyRNA *prop, + PyObject *get_cb, + PyObject *set_cb) { - IntPropertyGetFunc rna_get_cb = NULL; - IntPropertySetFunc rna_set_cb = NULL; + IntPropertyGetFunc rna_get_cb = NULL; + IntPropertySetFunc rna_set_cb = NULL; - if (get_cb && get_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (get_cb && get_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_get_cb = bpy_prop_int_get_cb; - py_data[BPY_DATA_CB_SLOT_GET] = get_cb; - } + rna_get_cb = bpy_prop_int_get_cb; + py_data[BPY_DATA_CB_SLOT_GET] = get_cb; + } - if (set_cb && set_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (set_cb && set_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_set_cb = bpy_prop_int_set_cb; - py_data[BPY_DATA_CB_SLOT_SET] = set_cb; - } + rna_set_cb = bpy_prop_int_set_cb; + py_data[BPY_DATA_CB_SLOT_SET] = set_cb; + } - RNA_def_property_int_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL); + RNA_def_property_int_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL); } -static void bpy_prop_callback_assign_int_array(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb) +static void bpy_prop_callback_assign_int_array(struct PropertyRNA *prop, + PyObject *get_cb, + PyObject *set_cb) { - IntArrayPropertyGetFunc rna_get_cb = NULL; - IntArrayPropertySetFunc rna_set_cb = NULL; + IntArrayPropertyGetFunc rna_get_cb = NULL; + IntArrayPropertySetFunc rna_set_cb = NULL; - if (get_cb && get_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (get_cb && get_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_get_cb = bpy_prop_int_array_get_cb; - py_data[BPY_DATA_CB_SLOT_GET] = get_cb; - } + rna_get_cb = bpy_prop_int_array_get_cb; + py_data[BPY_DATA_CB_SLOT_GET] = get_cb; + } - if (set_cb && set_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (set_cb && set_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_set_cb = bpy_prop_int_array_set_cb; - py_data[BPY_DATA_CB_SLOT_SET] = set_cb; - } + rna_set_cb = bpy_prop_int_array_set_cb; + py_data[BPY_DATA_CB_SLOT_SET] = set_cb; + } - RNA_def_property_int_array_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL); + RNA_def_property_int_array_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL); } -static void bpy_prop_callback_assign_float(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb) +static void bpy_prop_callback_assign_float(struct PropertyRNA *prop, + PyObject *get_cb, + PyObject *set_cb) { - FloatPropertyGetFunc rna_get_cb = NULL; - FloatPropertySetFunc rna_set_cb = NULL; + FloatPropertyGetFunc rna_get_cb = NULL; + FloatPropertySetFunc rna_set_cb = NULL; - if (get_cb && get_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (get_cb && get_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_get_cb = bpy_prop_float_get_cb; - py_data[BPY_DATA_CB_SLOT_GET] = get_cb; - } + rna_get_cb = bpy_prop_float_get_cb; + py_data[BPY_DATA_CB_SLOT_GET] = get_cb; + } - if (set_cb && set_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (set_cb && set_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_set_cb = bpy_prop_float_set_cb; - py_data[BPY_DATA_CB_SLOT_SET] = set_cb; - } + rna_set_cb = bpy_prop_float_set_cb; + py_data[BPY_DATA_CB_SLOT_SET] = set_cb; + } - RNA_def_property_float_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL); + RNA_def_property_float_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL); } -static void bpy_prop_callback_assign_float_array(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb) +static void bpy_prop_callback_assign_float_array(struct PropertyRNA *prop, + PyObject *get_cb, + PyObject *set_cb) { - FloatArrayPropertyGetFunc rna_get_cb = NULL; - FloatArrayPropertySetFunc rna_set_cb = NULL; + FloatArrayPropertyGetFunc rna_get_cb = NULL; + FloatArrayPropertySetFunc rna_set_cb = NULL; - if (get_cb && get_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (get_cb && get_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_get_cb = bpy_prop_float_array_get_cb; - py_data[BPY_DATA_CB_SLOT_GET] = get_cb; - } + rna_get_cb = bpy_prop_float_array_get_cb; + py_data[BPY_DATA_CB_SLOT_GET] = get_cb; + } - if (set_cb && set_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (set_cb && set_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_set_cb = bpy_prop_float_array_set_cb; - py_data[BPY_DATA_CB_SLOT_SET] = set_cb; - } + rna_set_cb = bpy_prop_float_array_set_cb; + py_data[BPY_DATA_CB_SLOT_SET] = set_cb; + } - RNA_def_property_float_array_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL); + RNA_def_property_float_array_funcs_runtime(prop, rna_get_cb, rna_set_cb, NULL); } -static void bpy_prop_callback_assign_string(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb) +static void bpy_prop_callback_assign_string(struct PropertyRNA *prop, + PyObject *get_cb, + PyObject *set_cb) { - StringPropertyGetFunc rna_get_cb = NULL; - StringPropertyLengthFunc rna_length_cb = NULL; - StringPropertySetFunc rna_set_cb = NULL; + StringPropertyGetFunc rna_get_cb = NULL; + StringPropertyLengthFunc rna_length_cb = NULL; + StringPropertySetFunc rna_set_cb = NULL; - if (get_cb && get_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (get_cb && get_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_get_cb = bpy_prop_string_get_cb; - rna_length_cb = bpy_prop_string_length_cb; - py_data[BPY_DATA_CB_SLOT_GET] = get_cb; - } + rna_get_cb = bpy_prop_string_get_cb; + rna_length_cb = bpy_prop_string_length_cb; + py_data[BPY_DATA_CB_SLOT_GET] = get_cb; + } - if (set_cb && set_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (set_cb && set_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_set_cb = bpy_prop_string_set_cb; - py_data[BPY_DATA_CB_SLOT_SET] = set_cb; - } + rna_set_cb = bpy_prop_string_set_cb; + py_data[BPY_DATA_CB_SLOT_SET] = set_cb; + } - RNA_def_property_string_funcs_runtime(prop, rna_get_cb, rna_length_cb, rna_set_cb); + RNA_def_property_string_funcs_runtime(prop, rna_get_cb, rna_length_cb, rna_set_cb); } -static void bpy_prop_callback_assign_enum(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb, PyObject *itemf_cb) +static void bpy_prop_callback_assign_enum(struct PropertyRNA *prop, + PyObject *get_cb, + PyObject *set_cb, + PyObject *itemf_cb) { - EnumPropertyGetFunc rna_get_cb = NULL; - EnumPropertyItemFunc rna_itemf_cb = NULL; - EnumPropertySetFunc rna_set_cb = NULL; + EnumPropertyGetFunc rna_get_cb = NULL; + EnumPropertyItemFunc rna_itemf_cb = NULL; + EnumPropertySetFunc rna_set_cb = NULL; - if (get_cb && get_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (get_cb && get_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_get_cb = bpy_prop_enum_get_cb; - py_data[BPY_DATA_CB_SLOT_GET] = get_cb; - } + rna_get_cb = bpy_prop_enum_get_cb; + py_data[BPY_DATA_CB_SLOT_GET] = get_cb; + } - if (set_cb && set_cb != Py_None) { - PyObject **py_data = bpy_prop_py_data_get(prop); + if (set_cb && set_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); - rna_set_cb = bpy_prop_enum_set_cb; - py_data[BPY_DATA_CB_SLOT_SET] = set_cb; - } + rna_set_cb = bpy_prop_enum_set_cb; + py_data[BPY_DATA_CB_SLOT_SET] = set_cb; + } - if (itemf_cb && itemf_cb != Py_None) { - rna_itemf_cb = bpy_prop_enum_itemf_cb; - RNA_def_property_enum_py_data(prop, (void *)itemf_cb); + if (itemf_cb && itemf_cb != Py_None) { + rna_itemf_cb = bpy_prop_enum_itemf_cb; + RNA_def_property_enum_py_data(prop, (void *)itemf_cb); - /* watch out!, if a user is tricky they can probably crash blender - * if they manage to free the callback, take care! */ - /* Py_INCREF(itemf_cb); */ - } + /* watch out!, if a user is tricky they can probably crash blender + * if they manage to free the callback, take care! */ + /* Py_INCREF(itemf_cb); */ + } - RNA_def_property_enum_funcs_runtime(prop, rna_get_cb, rna_set_cb, rna_itemf_cb); + RNA_def_property_enum_funcs_runtime(prop, rna_get_cb, rna_set_cb, rna_itemf_cb); } /* this define runs at the start of each function and deals with * returning a deferred property (to be registered later) */ -#define BPY_PROPDEF_HEAD(_func) \ - if (PyTuple_GET_SIZE(args) == 1) { \ - PyObject *ret; \ - self = PyTuple_GET_ITEM(args, 0); \ - args = PyTuple_New(0); \ - ret = BPy_##_func(self, args, kw); \ - Py_DECREF(args); \ - return ret; \ - } \ - else if (PyTuple_GET_SIZE(args) > 1) { \ - PyErr_SetString(PyExc_ValueError, "all args must be keywords"); \ - return NULL; \ - } \ - srna = srna_from_self(self, #_func"(...):"); \ - if (srna == NULL) { \ - if (PyErr_Occurred()) \ - return NULL; \ - return bpy_prop_deferred_return(pymeth_##_func, kw); \ - } (void)0 +#define BPY_PROPDEF_HEAD(_func) \ + if (PyTuple_GET_SIZE(args) == 1) { \ + PyObject *ret; \ + self = PyTuple_GET_ITEM(args, 0); \ + args = PyTuple_New(0); \ + ret = BPy_##_func(self, args, kw); \ + Py_DECREF(args); \ + return ret; \ + } \ + else if (PyTuple_GET_SIZE(args) > 1) { \ + PyErr_SetString(PyExc_ValueError, "all args must be keywords"); \ + return NULL; \ + } \ + srna = srna_from_self(self, #_func "(...):"); \ + if (srna == NULL) { \ + if (PyErr_Occurred()) \ + return NULL; \ + return bpy_prop_deferred_return(pymeth_##_func, kw); \ + } \ + (void)0 /* terse macros for error checks shared between all funcs cant use function * calls because of static strings passed to pyrna_set_to_enum_bitfield */ -#define BPY_PROPDEF_CHECK(_func, _property_flag_items) \ - if (UNLIKELY(id_len >= MAX_IDPROP_NAME)) { \ - PyErr_Format(PyExc_TypeError, \ - #_func"(): '%.200s' too long, max length is %d", \ - id, MAX_IDPROP_NAME - 1); \ - return NULL; \ - } \ - if (UNLIKELY(RNA_def_property_free_identifier(srna, id) == -1)) { \ - PyErr_Format(PyExc_TypeError, \ - #_func"(): '%s' is defined as a non-dynamic type", \ - id); \ - return NULL; \ - } \ - if (UNLIKELY(pyopts && pyrna_set_to_enum_bitfield(_property_flag_items, \ - pyopts, \ - &opts, \ - #_func"(options={ ...}):"))) \ - { \ - return NULL; \ - } \ - { \ - const EnumPropertyItem *tag_defines = RNA_struct_property_tag_defines(srna); \ - if (py_tags && !tag_defines) { \ - PyErr_Format(PyExc_TypeError, \ - #_func"(): property-tags not available for '%s'", \ - RNA_struct_identifier(srna)); \ - return NULL; \ - } \ - if (UNLIKELY(py_tags && pyrna_set_to_enum_bitfield( \ - tag_defines, py_tags, \ - &prop_tags, #_func"(tags={ ...}):"))) \ - { \ - return NULL; \ - } \ - }(void)0 - -#define BPY_PROPDEF_SUBTYPE_CHECK(_func, _property_flag_items, _subtype) \ - BPY_PROPDEF_CHECK(_func, _property_flag_items); \ - if (UNLIKELY(pysubtype && RNA_enum_value_from_id(_subtype, \ - pysubtype, \ - &subtype) == 0)) \ - { \ - const char *enum_str = BPy_enum_as_string(_subtype); \ - PyErr_Format(PyExc_TypeError, \ - #_func"(subtype='%s'): " \ - "subtype not found in (%s)", \ - pysubtype, enum_str); \ - MEM_freeN((void *)enum_str); \ - return NULL; \ - } (void)0 - +#define BPY_PROPDEF_CHECK(_func, _property_flag_items) \ + if (UNLIKELY(id_len >= MAX_IDPROP_NAME)) { \ + PyErr_Format(PyExc_TypeError, \ + #_func "(): '%.200s' too long, max length is %d", \ + id, \ + MAX_IDPROP_NAME - 1); \ + return NULL; \ + } \ + if (UNLIKELY(RNA_def_property_free_identifier(srna, id) == -1)) { \ + PyErr_Format(PyExc_TypeError, #_func "(): '%s' is defined as a non-dynamic type", id); \ + return NULL; \ + } \ + if (UNLIKELY(pyopts && pyrna_set_to_enum_bitfield( \ + _property_flag_items, pyopts, &opts, #_func "(options={ ...}):"))) { \ + return NULL; \ + } \ + { \ + const EnumPropertyItem *tag_defines = RNA_struct_property_tag_defines(srna); \ + if (py_tags && !tag_defines) { \ + PyErr_Format(PyExc_TypeError, \ + #_func "(): property-tags not available for '%s'", \ + RNA_struct_identifier(srna)); \ + return NULL; \ + } \ + if (UNLIKELY(py_tags && pyrna_set_to_enum_bitfield( \ + tag_defines, py_tags, &prop_tags, #_func "(tags={ ...}):"))) { \ + return NULL; \ + } \ + } \ + (void)0 + +#define BPY_PROPDEF_SUBTYPE_CHECK(_func, _property_flag_items, _subtype) \ + BPY_PROPDEF_CHECK(_func, _property_flag_items); \ + if (UNLIKELY(pysubtype && RNA_enum_value_from_id(_subtype, pysubtype, &subtype) == 0)) { \ + const char *enum_str = BPy_enum_as_string(_subtype); \ + PyErr_Format(PyExc_TypeError, \ + #_func \ + "(subtype='%s'): " \ + "subtype not found in (%s)", \ + pysubtype, \ + enum_str); \ + MEM_freeN((void *)enum_str); \ + return NULL; \ + } \ + (void)0 #define BPY_PROPDEF_NAME_DOC \ -" :arg name: Name used in the user interface.\n" \ -" :type name: string\n" \ + " :arg name: Name used in the user interface.\n" \ + " :type name: string\n" #define BPY_PROPDEF_DESC_DOC \ -" :arg description: Text used for the tooltip and api documentation.\n" \ -" :type description: string\n" \ + " :arg description: Text used for the tooltip and api documentation.\n" \ + " :type description: string\n" #define BPY_PROPDEF_UNIT_DOC \ -" :arg unit: Enumerator in ['NONE', 'LENGTH', 'AREA', 'VOLUME', 'ROTATION', 'TIME', 'VELOCITY', 'ACCELERATION', 'MASS', 'CAMERA', 'POWER'].\n" \ -" :type unit: string\n" \ + " :arg unit: Enumerator in ['NONE', 'LENGTH', 'AREA', 'VOLUME', 'ROTATION', 'TIME', " \ + "'VELOCITY', 'ACCELERATION', 'MASS', 'CAMERA', 'POWER'].\n" \ + " :type unit: string\n" #define BPY_PROPDEF_NUM_MIN_DOC \ -" :arg min: Hard minimum, trying to assign a value below will silently assign this minimum instead.\n" \ + " :arg min: Hard minimum, trying to assign a value below will silently assign this minimum " \ + "instead.\n" #define BPY_PROPDEF_NUM_MAX_DOC \ -" :arg max: Hard maximum, trying to assign a value above will silently assign this maximum instead.\n" \ + " :arg max: Hard maximum, trying to assign a value above will silently assign this maximum " \ + "instead.\n" #define BPY_PROPDEF_NUM_SOFTMIN_DOC \ -" :arg soft_min: Soft minimum (>= *min*), user won't be able to drag the widget below this value in the UI.\n" \ + " :arg soft_min: Soft minimum (>= *min*), user won't be able to drag the widget below this " \ + "value in the UI.\n" #define BPY_PROPDEF_NUM_SOFTMAX_DOC \ -" :arg soft_max: Soft maximum (<= *max*), user won't be able to drag the widget above this value in the UI.\n" \ + " :arg soft_max: Soft maximum (<= *max*), user won't be able to drag the widget above this " \ + "value in the UI.\n" #define BPY_PROPDEF_VECSIZE_DOC \ -" :arg size: Vector dimensions in [1, " STRINGIFY(PYRNA_STACK_ARRAY) "].\n" \ -" :type size: int\n" \ + " :arg size: Vector dimensions in [1, " STRINGIFY(PYRNA_STACK_ARRAY) "].\n" \ +" :type size: int\n" #define BPY_PROPDEF_INT_STEP_DOC \ -" :arg step: Step of increment/decrement in UI, in [1, 100], defaults to 1 (WARNING: unused currently!).\n" \ -" :type step: int\n" \ + " :arg step: Step of increment/decrement in UI, in [1, 100], defaults to 1 (WARNING: unused " \ + "currently!).\n" \ + " :type step: int\n" #define BPY_PROPDEF_FLOAT_STEP_DOC \ -" :arg step: Step of increment/decrement in UI, in [1, 100], defaults to 3 (WARNING: actual value is /100).\n" \ -" :type step: int\n" \ + " :arg step: Step of increment/decrement in UI, in [1, 100], defaults to 3 (WARNING: actual " \ + "value is /100).\n" \ + " :type step: int\n" #define BPY_PROPDEF_FLOAT_PREC_DOC \ -" :arg precision: Maximum number of decimal digits to display, in [0, 6].\n" \ -" :type precision: int\n" \ + " :arg precision: Maximum number of decimal digits to display, in [0, 6].\n" \ + " :type precision: int\n" #define BPY_PROPDEF_UPDATE_DOC \ -" :arg update: Function to be called when this value is modified,\n" \ -" This function must take 2 values (self, context) and return None.\n" \ -" *Warning* there are no safety checks to avoid infinite recursion.\n" \ -" :type update: function\n" \ + " :arg update: Function to be called when this value is modified,\n" \ + " This function must take 2 values (self, context) and return None.\n" \ + " *Warning* there are no safety checks to avoid infinite recursion.\n" \ + " :type update: function\n" #define BPY_PROPDEF_POLL_DOC \ -" :arg poll: function to be called to determine whether an item is valid for this property.\n" \ -" The function must take 2 values (self, object) and return Bool.\n" \ -" :type poll: function\n" \ + " :arg poll: function to be called to determine whether an item is valid for this " \ + "property.\n" \ + " The function must take 2 values (self, object) and return Bool.\n" \ + " :type poll: function\n" #define BPY_PROPDEF_GET_DOC \ -" :arg get: Function to be called when this value is 'read',\n" \ -" This function must take 1 value (self) and return the value of the property.\n" \ -" :type get: function\n" \ + " :arg get: Function to be called when this value is 'read',\n" \ + " This function must take 1 value (self) and return the value of the property.\n" \ + " :type get: function\n" #define BPY_PROPDEF_SET_DOC \ -" :arg set: Function to be called when this value is 'written',\n" \ -" This function must take 2 values (self, value) and return None.\n" \ -" :type set: function\n" \ + " :arg set: Function to be called when this value is 'written',\n" \ + " This function must take 2 values (self, value) and return None.\n" \ + " :type set: function\n" #define BPY_PROPDEF_TYPE_DOC \ -" :arg type: A subclass of :class:`bpy.types.PropertyGroup` or :class:`bpy.types.ID`.\n" \ -" :type type: class\n" \ + " :arg type: A subclass of :class:`bpy.types.PropertyGroup` or :class:`bpy.types.ID`.\n" \ + " :type type: class\n" #define BPY_PROPDEF_TAGS_DOC \ -" :arg tags: Enumerator of tags that are defined by parent class.\n" \ -" :type tags: set\n" \ + " :arg tags: Enumerator of tags that are defined by parent class.\n" \ + " :type tags: set\n" #if 0 static int bpy_struct_id_used(StructRNA *srna, char *identifier) { - PointerRNA ptr; - RNA_pointer_create(NULL, srna, NULL, &ptr); - return (RNA_struct_find_property(&ptr, identifier) != NULL); + PointerRNA ptr; + RNA_pointer_create(NULL, srna, NULL, &ptr); + return (RNA_struct_find_property(&ptr, identifier) != NULL); } #endif - /* Function that sets RNA, NOTE - self is NULL when called from python, * but being abused from C so we can pass the srna along. * This isn't incorrect since its a python object - but be careful */ PyDoc_STRVAR(BPy_BoolProperty_doc, -".. function:: BoolProperty(name=\"\", " - "description=\"\", " - "default=False, " - "options={'ANIMATABLE'}, " - "tags={}, " - "subtype='NONE', " - "update=None, " - "get=None, " - "set=None)\n" -"\n" -" Returns a new boolean property definition.\n" -"\n" -BPY_PROPDEF_NAME_DOC -BPY_PROPDEF_DESC_DOC -BPY_PROPDEF_OPTIONS_DOC -BPY_PROPDEF_TAGS_DOC -BPY_PROPDEF_SUBTYPE_NUMBER_DOC -BPY_PROPDEF_UPDATE_DOC -BPY_PROPDEF_GET_DOC -BPY_PROPDEF_SET_DOC -); + ".. function:: BoolProperty(name=\"\", " + "description=\"\", " + "default=False, " + "options={'ANIMATABLE'}, " + "tags={}, " + "subtype='NONE', " + "update=None, " + "get=None, " + "set=None)\n" + "\n" + " Returns a new boolean property definition.\n" + "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC BPY_PROPDEF_OPTIONS_DOC + BPY_PROPDEF_TAGS_DOC BPY_PROPDEF_SUBTYPE_NUMBER_DOC BPY_PROPDEF_UPDATE_DOC + BPY_PROPDEF_GET_DOC BPY_PROPDEF_SET_DOC); static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - BPY_PROPDEF_HEAD(BoolProperty); - - if (srna) { - const char *id = NULL, *name = NULL, *description = ""; - int id_len; - bool def = false; - PropertyRNA *prop; - PyObject *pyopts = NULL; - int opts = 0; - int prop_tags = 0; - const char *pysubtype = NULL; - int subtype = PROP_NONE; - PyObject *update_cb = NULL; - PyObject *get_cb = NULL; - PyObject *set_cb = NULL; - PyObject *py_tags = NULL; - - static const char *_keywords[] = { - "attr", "name", "description", "default", - "options", "tags", "subtype", - "update", "get", "set", NULL, - }; - static _PyArg_Parser _parser = {"s#|ssO&O!O!sOOO:BoolProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id, &id_len, - &name, &description, PyC_ParseBool, &def, - &PySet_Type, &pyopts, &PySet_Type, &py_tags, &pysubtype, - &update_cb, &get_cb, &set_cb)) - { - return NULL; - } - - BPY_PROPDEF_SUBTYPE_CHECK(BoolProperty, property_flag_items, property_subtype_number_items); - - if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { - return NULL; - } - if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { - return NULL; - } - if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { - return NULL; - } - - prop = RNA_def_property(srna, id, PROP_BOOLEAN, subtype); - RNA_def_property_boolean_default(prop, def); - RNA_def_property_ui_text(prop, name ? name : id, description); - - if (py_tags) { - RNA_def_property_tags(prop, prop_tags); - } - if (pyopts) { - bpy_prop_assign_flag(prop, opts); - } - bpy_prop_callback_assign_update(prop, update_cb); - bpy_prop_callback_assign_boolean(prop, get_cb, set_cb); - RNA_def_property_duplicate_pointers(srna, prop); - } - - Py_RETURN_NONE; + StructRNA *srna; + + BPY_PROPDEF_HEAD(BoolProperty); + + if (srna) { + const char *id = NULL, *name = NULL, *description = ""; + int id_len; + bool def = false; + PropertyRNA *prop; + PyObject *pyopts = NULL; + int opts = 0; + int prop_tags = 0; + const char *pysubtype = NULL; + int subtype = PROP_NONE; + PyObject *update_cb = NULL; + PyObject *get_cb = NULL; + PyObject *set_cb = NULL; + PyObject *py_tags = NULL; + + static const char *_keywords[] = { + "attr", + "name", + "description", + "default", + "options", + "tags", + "subtype", + "update", + "get", + "set", + NULL, + }; + static _PyArg_Parser _parser = {"s#|ssO&O!O!sOOO:BoolProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &id, + &id_len, + &name, + &description, + PyC_ParseBool, + &def, + &PySet_Type, + &pyopts, + &PySet_Type, + &py_tags, + &pysubtype, + &update_cb, + &get_cb, + &set_cb)) { + return NULL; + } + + BPY_PROPDEF_SUBTYPE_CHECK(BoolProperty, property_flag_items, property_subtype_number_items); + + if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { + return NULL; + } + if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { + return NULL; + } + if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { + return NULL; + } + + prop = RNA_def_property(srna, id, PROP_BOOLEAN, subtype); + RNA_def_property_boolean_default(prop, def); + RNA_def_property_ui_text(prop, name ? name : id, description); + + if (py_tags) { + RNA_def_property_tags(prop, prop_tags); + } + if (pyopts) { + bpy_prop_assign_flag(prop, opts); + } + bpy_prop_callback_assign_update(prop, update_cb); + bpy_prop_callback_assign_boolean(prop, get_cb, set_cb); + RNA_def_property_duplicate_pointers(srna, prop); + } + + Py_RETURN_NONE; } PyDoc_STRVAR(BPy_BoolVectorProperty_doc, -".. function:: BoolVectorProperty(name=\"\", " - "description=\"\", " - "default=(False, False, False), " - "options={'ANIMATABLE'}, " - "tags={}, " - "subtype='NONE', " - "size=3, " - "update=None, " - "get=None, " - "set=None)\n" -"\n" -" Returns a new vector boolean property definition.\n" -"\n" -BPY_PROPDEF_NAME_DOC -BPY_PROPDEF_DESC_DOC -" :arg default: sequence of booleans the length of *size*.\n" -" :type default: sequence\n" -BPY_PROPDEF_OPTIONS_DOC -BPY_PROPDEF_TAGS_DOC -BPY_PROPDEF_SUBTYPE_ARRAY_DOC -BPY_PROPDEF_VECSIZE_DOC -BPY_PROPDEF_UPDATE_DOC -BPY_PROPDEF_GET_DOC -BPY_PROPDEF_SET_DOC -); + ".. function:: BoolVectorProperty(name=\"\", " + "description=\"\", " + "default=(False, False, False), " + "options={'ANIMATABLE'}, " + "tags={}, " + "subtype='NONE', " + "size=3, " + "update=None, " + "get=None, " + "set=None)\n" + "\n" + " Returns a new vector boolean property definition.\n" + "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC + " :arg default: sequence of booleans the length of *size*.\n" + " :type default: sequence\n" BPY_PROPDEF_OPTIONS_DOC BPY_PROPDEF_TAGS_DOC + BPY_PROPDEF_SUBTYPE_ARRAY_DOC BPY_PROPDEF_VECSIZE_DOC BPY_PROPDEF_UPDATE_DOC + BPY_PROPDEF_GET_DOC BPY_PROPDEF_SET_DOC); static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - BPY_PROPDEF_HEAD(BoolVectorProperty); - - if (srna) { - const char *id = NULL, *name = NULL, *description = ""; - int id_len; - bool def[PYRNA_STACK_ARRAY] = {0}; - int size = 3; - PropertyRNA *prop; - PyObject *pydef = NULL; - PyObject *pyopts = NULL; - int opts = 0; - int prop_tags = 0; - const char *pysubtype = NULL; - int subtype = PROP_NONE; - PyObject *update_cb = NULL; - PyObject *get_cb = NULL; - PyObject *set_cb = NULL; - PyObject *py_tags = NULL; - - static const char *_keywords[] = { - "attr", "name", "description", "default", - "options", "tags", "subtype", "size", - "update", "get", "set", NULL, - }; - static _PyArg_Parser _parser = {"s#|ssOO!O!siOOO:BoolVectorProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id, &id_len, - &name, &description, &pydef, - &PySet_Type, &pyopts, &PySet_Type, &py_tags, - &pysubtype, &size, - &update_cb, &get_cb, &set_cb)) - { - return NULL; - } - - BPY_PROPDEF_SUBTYPE_CHECK(BoolVectorProperty, property_flag_items, property_subtype_array_items); - - if (size < 1 || size > PYRNA_STACK_ARRAY) { - PyErr_Format(PyExc_TypeError, - "BoolVectorProperty(size=%d): size must be between 0 and " - STRINGIFY(PYRNA_STACK_ARRAY), size); - return NULL; - } - - if (pydef && PyC_AsArray(def, pydef, size, &PyBool_Type, false, "BoolVectorProperty(default=sequence)") == -1) { - return NULL; - } - - if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { - return NULL; - } - if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { - return NULL; - } - if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { - return NULL; - } - - // prop = RNA_def_boolean_array(srna, id, size, pydef ? def:NULL, name ? name : id, description); - prop = RNA_def_property(srna, id, PROP_BOOLEAN, subtype); - RNA_def_property_array(prop, size); - if (pydef) { - RNA_def_property_boolean_array_default(prop, def); - } - RNA_def_property_ui_text(prop, name ? name : id, description); - - if (py_tags) { - RNA_def_property_tags(prop, prop_tags); - } - if (pyopts) { - bpy_prop_assign_flag(prop, opts); - } - bpy_prop_callback_assign_update(prop, update_cb); - bpy_prop_callback_assign_boolean_array(prop, get_cb, set_cb); - RNA_def_property_duplicate_pointers(srna, prop); - } - - Py_RETURN_NONE; + StructRNA *srna; + + BPY_PROPDEF_HEAD(BoolVectorProperty); + + if (srna) { + const char *id = NULL, *name = NULL, *description = ""; + int id_len; + bool def[PYRNA_STACK_ARRAY] = {0}; + int size = 3; + PropertyRNA *prop; + PyObject *pydef = NULL; + PyObject *pyopts = NULL; + int opts = 0; + int prop_tags = 0; + const char *pysubtype = NULL; + int subtype = PROP_NONE; + PyObject *update_cb = NULL; + PyObject *get_cb = NULL; + PyObject *set_cb = NULL; + PyObject *py_tags = NULL; + + static const char *_keywords[] = { + "attr", + "name", + "description", + "default", + "options", + "tags", + "subtype", + "size", + "update", + "get", + "set", + NULL, + }; + static _PyArg_Parser _parser = {"s#|ssOO!O!siOOO:BoolVectorProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &id, + &id_len, + &name, + &description, + &pydef, + &PySet_Type, + &pyopts, + &PySet_Type, + &py_tags, + &pysubtype, + &size, + &update_cb, + &get_cb, + &set_cb)) { + return NULL; + } + + BPY_PROPDEF_SUBTYPE_CHECK( + BoolVectorProperty, property_flag_items, property_subtype_array_items); + + if (size < 1 || size > PYRNA_STACK_ARRAY) { + PyErr_Format( + PyExc_TypeError, + "BoolVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), + size); + return NULL; + } + + if (pydef && + PyC_AsArray( + def, pydef, size, &PyBool_Type, false, "BoolVectorProperty(default=sequence)") == -1) { + return NULL; + } + + if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { + return NULL; + } + if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { + return NULL; + } + if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { + return NULL; + } + + // prop = RNA_def_boolean_array(srna, id, size, pydef ? def:NULL, name ? name : id, description); + prop = RNA_def_property(srna, id, PROP_BOOLEAN, subtype); + RNA_def_property_array(prop, size); + if (pydef) { + RNA_def_property_boolean_array_default(prop, def); + } + RNA_def_property_ui_text(prop, name ? name : id, description); + + if (py_tags) { + RNA_def_property_tags(prop, prop_tags); + } + if (pyopts) { + bpy_prop_assign_flag(prop, opts); + } + bpy_prop_callback_assign_update(prop, update_cb); + bpy_prop_callback_assign_boolean_array(prop, get_cb, set_cb); + RNA_def_property_duplicate_pointers(srna, prop); + } + + Py_RETURN_NONE; } PyDoc_STRVAR(BPy_IntProperty_doc, -".. function:: IntProperty(name=\"\", " - "description=\"\", " - "default=0, " - "min=-2**31, max=2**31-1, " - "soft_min=-2**31, soft_max=2**31-1, " - "step=1, " - "options={'ANIMATABLE'}, " - "tags={}, " - "subtype='NONE', " - "update=None, " - "get=None, " - "set=None)\n" -"\n" -" Returns a new int property definition.\n" -"\n" -BPY_PROPDEF_NAME_DOC -BPY_PROPDEF_DESC_DOC -BPY_PROPDEF_NUM_MIN_DOC -" :type min: int\n" -BPY_PROPDEF_NUM_MAX_DOC -" :type max: int\n" -BPY_PROPDEF_NUM_SOFTMAX_DOC -" :type soft_min: int\n" -BPY_PROPDEF_NUM_SOFTMIN_DOC -" :type soft_max: int\n" -BPY_PROPDEF_INT_STEP_DOC -BPY_PROPDEF_OPTIONS_DOC -BPY_PROPDEF_TAGS_DOC -BPY_PROPDEF_SUBTYPE_NUMBER_DOC -BPY_PROPDEF_UPDATE_DOC -BPY_PROPDEF_GET_DOC -BPY_PROPDEF_SET_DOC -); + ".. function:: IntProperty(name=\"\", " + "description=\"\", " + "default=0, " + "min=-2**31, max=2**31-1, " + "soft_min=-2**31, soft_max=2**31-1, " + "step=1, " + "options={'ANIMATABLE'}, " + "tags={}, " + "subtype='NONE', " + "update=None, " + "get=None, " + "set=None)\n" + "\n" + " Returns a new int property definition.\n" + "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC BPY_PROPDEF_NUM_MIN_DOC + " :type min: int\n" BPY_PROPDEF_NUM_MAX_DOC + " :type max: int\n" BPY_PROPDEF_NUM_SOFTMAX_DOC + " :type soft_min: int\n" BPY_PROPDEF_NUM_SOFTMIN_DOC + " :type soft_max: int\n" BPY_PROPDEF_INT_STEP_DOC BPY_PROPDEF_OPTIONS_DOC + BPY_PROPDEF_TAGS_DOC BPY_PROPDEF_SUBTYPE_NUMBER_DOC BPY_PROPDEF_UPDATE_DOC + BPY_PROPDEF_GET_DOC BPY_PROPDEF_SET_DOC); static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - BPY_PROPDEF_HEAD(IntProperty); - - if (srna) { - const char *id = NULL, *name = NULL, *description = ""; - int id_len; - int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1, def = 0; - PropertyRNA *prop; - PyObject *pyopts = NULL; - int opts = 0; - int prop_tags = 0; - const char *pysubtype = NULL; - int subtype = PROP_NONE; - PyObject *update_cb = NULL; - PyObject *get_cb = NULL; - PyObject *set_cb = NULL; - PyObject *py_tags = NULL; - - static const char *_keywords[] = { - "attr", "name", "description", "default", - "min", "max", "soft_min", "soft_max", - "step", "options", "tags", "subtype", - "update", "get", "set", NULL, - }; - static _PyArg_Parser _parser = {"s#|ssiiiiiiO!O!sOOO:IntProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id, &id_len, - &name, &description, &def, - &min, &max, &soft_min, &soft_max, - &step, &PySet_Type, &pyopts, &PySet_Type, &py_tags, &pysubtype, - &update_cb, &get_cb, &set_cb)) - { - return NULL; - } - - BPY_PROPDEF_SUBTYPE_CHECK(IntProperty, property_flag_items, property_subtype_number_items); - - if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { - return NULL; - } - if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { - return NULL; - } - if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { - return NULL; - } - - prop = RNA_def_property(srna, id, PROP_INT, subtype); - RNA_def_property_int_default(prop, def); - RNA_def_property_ui_text(prop, name ? name : id, description); - RNA_def_property_range(prop, min, max); - RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3); - - if (py_tags) { - RNA_def_property_tags(prop, prop_tags); - } - if (pyopts) { - bpy_prop_assign_flag(prop, opts); - } - bpy_prop_callback_assign_update(prop, update_cb); - bpy_prop_callback_assign_int(prop, get_cb, set_cb); - RNA_def_property_duplicate_pointers(srna, prop); - } - Py_RETURN_NONE; + StructRNA *srna; + + BPY_PROPDEF_HEAD(IntProperty); + + if (srna) { + const char *id = NULL, *name = NULL, *description = ""; + int id_len; + int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1, def = 0; + PropertyRNA *prop; + PyObject *pyopts = NULL; + int opts = 0; + int prop_tags = 0; + const char *pysubtype = NULL; + int subtype = PROP_NONE; + PyObject *update_cb = NULL; + PyObject *get_cb = NULL; + PyObject *set_cb = NULL; + PyObject *py_tags = NULL; + + static const char *_keywords[] = { + "attr", + "name", + "description", + "default", + "min", + "max", + "soft_min", + "soft_max", + "step", + "options", + "tags", + "subtype", + "update", + "get", + "set", + NULL, + }; + static _PyArg_Parser _parser = {"s#|ssiiiiiiO!O!sOOO:IntProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &id, + &id_len, + &name, + &description, + &def, + &min, + &max, + &soft_min, + &soft_max, + &step, + &PySet_Type, + &pyopts, + &PySet_Type, + &py_tags, + &pysubtype, + &update_cb, + &get_cb, + &set_cb)) { + return NULL; + } + + BPY_PROPDEF_SUBTYPE_CHECK(IntProperty, property_flag_items, property_subtype_number_items); + + if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { + return NULL; + } + if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { + return NULL; + } + if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { + return NULL; + } + + prop = RNA_def_property(srna, id, PROP_INT, subtype); + RNA_def_property_int_default(prop, def); + RNA_def_property_ui_text(prop, name ? name : id, description); + RNA_def_property_range(prop, min, max); + RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3); + + if (py_tags) { + RNA_def_property_tags(prop, prop_tags); + } + if (pyopts) { + bpy_prop_assign_flag(prop, opts); + } + bpy_prop_callback_assign_update(prop, update_cb); + bpy_prop_callback_assign_int(prop, get_cb, set_cb); + RNA_def_property_duplicate_pointers(srna, prop); + } + Py_RETURN_NONE; } PyDoc_STRVAR(BPy_IntVectorProperty_doc, -".. function:: IntVectorProperty(name=\"\", " - "description=\"\", " - "default=(0, 0, 0), min=-2**31, max=2**31-1, " - "soft_min=-2**31, " - "soft_max=2**31-1, " - "step=1, " - "options={'ANIMATABLE'}, " - "tags={}, " - "subtype='NONE', " - "size=3, " - "update=None, " - "get=None, " - "set=None)\n" -"\n" -" Returns a new vector int property definition.\n" -"\n" -BPY_PROPDEF_NAME_DOC -BPY_PROPDEF_DESC_DOC -" :arg default: sequence of ints the length of *size*.\n" -" :type default: sequence\n" -BPY_PROPDEF_NUM_MIN_DOC -" :type min: int\n" -BPY_PROPDEF_NUM_MAX_DOC -" :type max: int\n" -BPY_PROPDEF_NUM_SOFTMIN_DOC -" :type soft_min: int\n" -BPY_PROPDEF_NUM_SOFTMAX_DOC -" :type soft_max: int\n" -BPY_PROPDEF_INT_STEP_DOC -BPY_PROPDEF_OPTIONS_DOC -BPY_PROPDEF_TAGS_DOC -BPY_PROPDEF_SUBTYPE_ARRAY_DOC -BPY_PROPDEF_VECSIZE_DOC -BPY_PROPDEF_UPDATE_DOC -BPY_PROPDEF_GET_DOC -BPY_PROPDEF_SET_DOC -); + ".. function:: IntVectorProperty(name=\"\", " + "description=\"\", " + "default=(0, 0, 0), min=-2**31, max=2**31-1, " + "soft_min=-2**31, " + "soft_max=2**31-1, " + "step=1, " + "options={'ANIMATABLE'}, " + "tags={}, " + "subtype='NONE', " + "size=3, " + "update=None, " + "get=None, " + "set=None)\n" + "\n" + " Returns a new vector int property definition.\n" + "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC + " :arg default: sequence of ints the length of *size*.\n" + " :type default: sequence\n" BPY_PROPDEF_NUM_MIN_DOC + " :type min: int\n" BPY_PROPDEF_NUM_MAX_DOC + " :type max: int\n" BPY_PROPDEF_NUM_SOFTMIN_DOC + " :type soft_min: int\n" BPY_PROPDEF_NUM_SOFTMAX_DOC + " :type soft_max: int\n" BPY_PROPDEF_INT_STEP_DOC BPY_PROPDEF_OPTIONS_DOC + BPY_PROPDEF_TAGS_DOC BPY_PROPDEF_SUBTYPE_ARRAY_DOC BPY_PROPDEF_VECSIZE_DOC + BPY_PROPDEF_UPDATE_DOC BPY_PROPDEF_GET_DOC BPY_PROPDEF_SET_DOC); static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - BPY_PROPDEF_HEAD(IntVectorProperty); - - if (srna) { - const char *id = NULL, *name = NULL, *description = ""; - int id_len; - int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1; - int def[PYRNA_STACK_ARRAY] = {0}; - int size = 3; - PropertyRNA *prop; - PyObject *pydef = NULL; - PyObject *pyopts = NULL; - int opts = 0; - int prop_tags = 0; - const char *pysubtype = NULL; - int subtype = PROP_NONE; - PyObject *update_cb = NULL; - PyObject *get_cb = NULL; - PyObject *set_cb = NULL; - PyObject *py_tags = NULL; - - static const char *_keywords[] = { - "attr", "name", "description", "default", - "min", "max", "soft_min", "soft_max", - "step", "options", "tags", "subtype", "size", - "update", "get", "set", NULL, - }; - static _PyArg_Parser _parser = {"s#|ssOiiiiiO!O!siOOO:IntVectorProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id, &id_len, - &name, &description, &pydef, - &min, &max, &soft_min, &soft_max, - &step, &PySet_Type, &pyopts, &PySet_Type, &py_tags, - &pysubtype, &size, - &update_cb, &get_cb, &set_cb)) - { - return NULL; - } - - BPY_PROPDEF_SUBTYPE_CHECK(IntVectorProperty, property_flag_items, property_subtype_array_items); - - if (size < 1 || size > PYRNA_STACK_ARRAY) { - PyErr_Format(PyExc_TypeError, - "IntVectorProperty(size=%d): size must be between 0 and " - STRINGIFY(PYRNA_STACK_ARRAY), size); - return NULL; - } - - if (pydef && PyC_AsArray(def, pydef, size, &PyLong_Type, false, "IntVectorProperty(default=sequence)") == -1) { - return NULL; - } - - if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { - return NULL; - } - if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { - return NULL; - } - if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { - return NULL; - } - - prop = RNA_def_property(srna, id, PROP_INT, subtype); - RNA_def_property_array(prop, size); - if (pydef) { - RNA_def_property_int_array_default(prop, def); - } - RNA_def_property_range(prop, min, max); - RNA_def_property_ui_text(prop, name ? name : id, description); - RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3); - - if (py_tags) { - RNA_def_property_tags(prop, prop_tags); - } - if (pyopts) { - bpy_prop_assign_flag(prop, opts); - } - bpy_prop_callback_assign_update(prop, update_cb); - bpy_prop_callback_assign_int_array(prop, get_cb, set_cb); - RNA_def_property_duplicate_pointers(srna, prop); - } - Py_RETURN_NONE; + StructRNA *srna; + + BPY_PROPDEF_HEAD(IntVectorProperty); + + if (srna) { + const char *id = NULL, *name = NULL, *description = ""; + int id_len; + int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1; + int def[PYRNA_STACK_ARRAY] = {0}; + int size = 3; + PropertyRNA *prop; + PyObject *pydef = NULL; + PyObject *pyopts = NULL; + int opts = 0; + int prop_tags = 0; + const char *pysubtype = NULL; + int subtype = PROP_NONE; + PyObject *update_cb = NULL; + PyObject *get_cb = NULL; + PyObject *set_cb = NULL; + PyObject *py_tags = NULL; + + static const char *_keywords[] = { + "attr", + "name", + "description", + "default", + "min", + "max", + "soft_min", + "soft_max", + "step", + "options", + "tags", + "subtype", + "size", + "update", + "get", + "set", + NULL, + }; + static _PyArg_Parser _parser = {"s#|ssOiiiiiO!O!siOOO:IntVectorProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &id, + &id_len, + &name, + &description, + &pydef, + &min, + &max, + &soft_min, + &soft_max, + &step, + &PySet_Type, + &pyopts, + &PySet_Type, + &py_tags, + &pysubtype, + &size, + &update_cb, + &get_cb, + &set_cb)) { + return NULL; + } + + BPY_PROPDEF_SUBTYPE_CHECK( + IntVectorProperty, property_flag_items, property_subtype_array_items); + + if (size < 1 || size > PYRNA_STACK_ARRAY) { + PyErr_Format( + PyExc_TypeError, + "IntVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), + size); + return NULL; + } + + if (pydef && + PyC_AsArray( + def, pydef, size, &PyLong_Type, false, "IntVectorProperty(default=sequence)") == -1) { + return NULL; + } + + if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { + return NULL; + } + if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { + return NULL; + } + if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { + return NULL; + } + + prop = RNA_def_property(srna, id, PROP_INT, subtype); + RNA_def_property_array(prop, size); + if (pydef) { + RNA_def_property_int_array_default(prop, def); + } + RNA_def_property_range(prop, min, max); + RNA_def_property_ui_text(prop, name ? name : id, description); + RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3); + + if (py_tags) { + RNA_def_property_tags(prop, prop_tags); + } + if (pyopts) { + bpy_prop_assign_flag(prop, opts); + } + bpy_prop_callback_assign_update(prop, update_cb); + bpy_prop_callback_assign_int_array(prop, get_cb, set_cb); + RNA_def_property_duplicate_pointers(srna, prop); + } + Py_RETURN_NONE; } - PyDoc_STRVAR(BPy_FloatProperty_doc, -".. function:: FloatProperty(name=\"\", " - "description=\"\", " - "default=0.0, " - "min=sys.float_info.min, max=sys.float_info.max, " - "soft_min=sys.float_info.min, soft_max=sys.float_info.max, " - "step=3, " - "precision=2, " - "options={'ANIMATABLE'}, " - "tags={}, " - "subtype='NONE', " - "unit='NONE', " - "update=None, " - "get=None, " - "set=None)\n" -"\n" -" Returns a new float property definition.\n" -"\n" -BPY_PROPDEF_NAME_DOC -BPY_PROPDEF_DESC_DOC -BPY_PROPDEF_NUM_MIN_DOC -" :type min: float\n" -BPY_PROPDEF_NUM_MAX_DOC -" :type max: float\n" -BPY_PROPDEF_NUM_SOFTMIN_DOC -" :type soft_min: float\n" -BPY_PROPDEF_NUM_SOFTMAX_DOC -" :type soft_max: float\n" -BPY_PROPDEF_FLOAT_STEP_DOC -BPY_PROPDEF_FLOAT_PREC_DOC -BPY_PROPDEF_OPTIONS_DOC -BPY_PROPDEF_TAGS_DOC -BPY_PROPDEF_SUBTYPE_NUMBER_DOC -BPY_PROPDEF_UNIT_DOC -BPY_PROPDEF_UPDATE_DOC -BPY_PROPDEF_GET_DOC -BPY_PROPDEF_SET_DOC -); + ".. function:: FloatProperty(name=\"\", " + "description=\"\", " + "default=0.0, " + "min=sys.float_info.min, max=sys.float_info.max, " + "soft_min=sys.float_info.min, soft_max=sys.float_info.max, " + "step=3, " + "precision=2, " + "options={'ANIMATABLE'}, " + "tags={}, " + "subtype='NONE', " + "unit='NONE', " + "update=None, " + "get=None, " + "set=None)\n" + "\n" + " Returns a new float property definition.\n" + "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC BPY_PROPDEF_NUM_MIN_DOC + " :type min: float\n" BPY_PROPDEF_NUM_MAX_DOC + " :type max: float\n" BPY_PROPDEF_NUM_SOFTMIN_DOC + " :type soft_min: float\n" BPY_PROPDEF_NUM_SOFTMAX_DOC + " :type soft_max: float\n" BPY_PROPDEF_FLOAT_STEP_DOC BPY_PROPDEF_FLOAT_PREC_DOC + BPY_PROPDEF_OPTIONS_DOC BPY_PROPDEF_TAGS_DOC BPY_PROPDEF_SUBTYPE_NUMBER_DOC + BPY_PROPDEF_UNIT_DOC BPY_PROPDEF_UPDATE_DOC BPY_PROPDEF_GET_DOC + BPY_PROPDEF_SET_DOC); static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - BPY_PROPDEF_HEAD(FloatProperty); - - if (srna) { - const char *id = NULL, *name = NULL, *description = ""; - int id_len; - float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3, def = 0.0f; - int precision = 2; - PropertyRNA *prop; - PyObject *pyopts = NULL; - int opts = 0; - int prop_tags = 0; - const char *pysubtype = NULL; - int subtype = PROP_NONE; - const char *pyunit = NULL; - int unit = PROP_UNIT_NONE; - PyObject *update_cb = NULL; - PyObject *get_cb = NULL; - PyObject *set_cb = NULL; - PyObject *py_tags = NULL; - - static const char *_keywords[] = { - "attr", "name", "description", "default", - "min", "max", "soft_min", "soft_max", - "step", "precision", "options", "tags", "subtype", - "unit", "update", "get", "set", NULL, - }; - static _PyArg_Parser _parser = {"s#|ssffffffiO!O!ssOOO:FloatProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id, &id_len, - &name, &description, &def, - &min, &max, &soft_min, &soft_max, - &step, &precision, &PySet_Type, - &pyopts, &PySet_Type, &py_tags, &pysubtype, &pyunit, - &update_cb, &get_cb, &set_cb)) - { - return NULL; - } - - BPY_PROPDEF_SUBTYPE_CHECK(FloatProperty, property_flag_items, property_subtype_number_items); - - if (pyunit && RNA_enum_value_from_id(rna_enum_property_unit_items, pyunit, &unit) == 0) { - PyErr_Format(PyExc_TypeError, "FloatProperty(unit='%s'): invalid unit", pyunit); - return NULL; - } - - if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { - return NULL; - } - if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { - return NULL; - } - if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { - return NULL; - } - - prop = RNA_def_property(srna, id, PROP_FLOAT, subtype | unit); - RNA_def_property_float_default(prop, def); - RNA_def_property_range(prop, min, max); - RNA_def_property_ui_text(prop, name ? name : id, description); - RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision); - - if (py_tags) { - RNA_def_property_tags(prop, prop_tags); - } - if (pyopts) { - bpy_prop_assign_flag(prop, opts); - } - bpy_prop_callback_assign_update(prop, update_cb); - bpy_prop_callback_assign_float(prop, get_cb, set_cb); - RNA_def_property_duplicate_pointers(srna, prop); - } - Py_RETURN_NONE; + StructRNA *srna; + + BPY_PROPDEF_HEAD(FloatProperty); + + if (srna) { + const char *id = NULL, *name = NULL, *description = ""; + int id_len; + float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3, + def = 0.0f; + int precision = 2; + PropertyRNA *prop; + PyObject *pyopts = NULL; + int opts = 0; + int prop_tags = 0; + const char *pysubtype = NULL; + int subtype = PROP_NONE; + const char *pyunit = NULL; + int unit = PROP_UNIT_NONE; + PyObject *update_cb = NULL; + PyObject *get_cb = NULL; + PyObject *set_cb = NULL; + PyObject *py_tags = NULL; + + static const char *_keywords[] = { + "attr", + "name", + "description", + "default", + "min", + "max", + "soft_min", + "soft_max", + "step", + "precision", + "options", + "tags", + "subtype", + "unit", + "update", + "get", + "set", + NULL, + }; + static _PyArg_Parser _parser = {"s#|ssffffffiO!O!ssOOO:FloatProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &id, + &id_len, + &name, + &description, + &def, + &min, + &max, + &soft_min, + &soft_max, + &step, + &precision, + &PySet_Type, + &pyopts, + &PySet_Type, + &py_tags, + &pysubtype, + &pyunit, + &update_cb, + &get_cb, + &set_cb)) { + return NULL; + } + + BPY_PROPDEF_SUBTYPE_CHECK(FloatProperty, property_flag_items, property_subtype_number_items); + + if (pyunit && RNA_enum_value_from_id(rna_enum_property_unit_items, pyunit, &unit) == 0) { + PyErr_Format(PyExc_TypeError, "FloatProperty(unit='%s'): invalid unit", pyunit); + return NULL; + } + + if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { + return NULL; + } + if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { + return NULL; + } + if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { + return NULL; + } + + prop = RNA_def_property(srna, id, PROP_FLOAT, subtype | unit); + RNA_def_property_float_default(prop, def); + RNA_def_property_range(prop, min, max); + RNA_def_property_ui_text(prop, name ? name : id, description); + RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision); + + if (py_tags) { + RNA_def_property_tags(prop, prop_tags); + } + if (pyopts) { + bpy_prop_assign_flag(prop, opts); + } + bpy_prop_callback_assign_update(prop, update_cb); + bpy_prop_callback_assign_float(prop, get_cb, set_cb); + RNA_def_property_duplicate_pointers(srna, prop); + } + Py_RETURN_NONE; } PyDoc_STRVAR(BPy_FloatVectorProperty_doc, -".. function:: FloatVectorProperty(name=\"\", " - "description=\"\", " - "default=(0.0, 0.0, 0.0), " - "min=sys.float_info.min, max=sys.float_info.max, " - "soft_min=sys.float_info.min, soft_max=sys.float_info.max, " - "step=3, " - "precision=2, " - "options={'ANIMATABLE'}, " - "tags={}, " - "subtype='NONE', " - "unit='NONE', " - "size=3, " - "update=None, " - "get=None, " - "set=None)\n" -"\n" -" Returns a new vector float property definition.\n" -"\n" -BPY_PROPDEF_NAME_DOC -BPY_PROPDEF_DESC_DOC -" :arg default: sequence of floats the length of *size*.\n" -" :type default: sequence\n" -BPY_PROPDEF_NUM_MIN_DOC -" :type min: float\n" -BPY_PROPDEF_NUM_MAX_DOC -" :type max: float\n" -BPY_PROPDEF_NUM_SOFTMIN_DOC -" :type soft_min: float\n" -BPY_PROPDEF_NUM_SOFTMAX_DOC -" :type soft_max: float\n" -BPY_PROPDEF_OPTIONS_DOC -BPY_PROPDEF_TAGS_DOC -BPY_PROPDEF_FLOAT_STEP_DOC -BPY_PROPDEF_FLOAT_PREC_DOC -BPY_PROPDEF_SUBTYPE_ARRAY_DOC -BPY_PROPDEF_UNIT_DOC -BPY_PROPDEF_VECSIZE_DOC -BPY_PROPDEF_UPDATE_DOC -BPY_PROPDEF_GET_DOC -BPY_PROPDEF_SET_DOC -); + ".. function:: FloatVectorProperty(name=\"\", " + "description=\"\", " + "default=(0.0, 0.0, 0.0), " + "min=sys.float_info.min, max=sys.float_info.max, " + "soft_min=sys.float_info.min, soft_max=sys.float_info.max, " + "step=3, " + "precision=2, " + "options={'ANIMATABLE'}, " + "tags={}, " + "subtype='NONE', " + "unit='NONE', " + "size=3, " + "update=None, " + "get=None, " + "set=None)\n" + "\n" + " Returns a new vector float property definition.\n" + "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC + " :arg default: sequence of floats the length of *size*.\n" + " :type default: sequence\n" BPY_PROPDEF_NUM_MIN_DOC + " :type min: float\n" BPY_PROPDEF_NUM_MAX_DOC + " :type max: float\n" BPY_PROPDEF_NUM_SOFTMIN_DOC + " :type soft_min: float\n" BPY_PROPDEF_NUM_SOFTMAX_DOC + " :type soft_max: float\n" BPY_PROPDEF_OPTIONS_DOC BPY_PROPDEF_TAGS_DOC + BPY_PROPDEF_FLOAT_STEP_DOC BPY_PROPDEF_FLOAT_PREC_DOC + BPY_PROPDEF_SUBTYPE_ARRAY_DOC BPY_PROPDEF_UNIT_DOC BPY_PROPDEF_VECSIZE_DOC + BPY_PROPDEF_UPDATE_DOC BPY_PROPDEF_GET_DOC BPY_PROPDEF_SET_DOC); static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - BPY_PROPDEF_HEAD(FloatVectorProperty); - - if (srna) { - const char *id = NULL, *name = NULL, *description = ""; - int id_len; - float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3; - float def[PYRNA_STACK_ARRAY] = {0.0f}; - int precision = 2, size = 3; - PropertyRNA *prop; - PyObject *pydef = NULL; - PyObject *pyopts = NULL; - int opts = 0; - int prop_tags = 0; - const char *pysubtype = NULL; - int subtype = PROP_NONE; - const char *pyunit = NULL; - int unit = PROP_UNIT_NONE; - PyObject *update_cb = NULL; - PyObject *get_cb = NULL; - PyObject *set_cb = NULL; - PyObject *py_tags = NULL; - - static const char *_keywords[] = { - "attr", "name", "description", "default", - "min", "max", "soft_min", "soft_max", - "step", "precision", "options", "tags", "subtype", - "unit", "size", "update", "get", "set", NULL, - }; - static _PyArg_Parser _parser = {"s#|ssOfffffiO!O!ssiOOO:FloatVectorProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id, &id_len, - &name, &description, &pydef, - &min, &max, &soft_min, &soft_max, - &step, &precision, &PySet_Type, - &pyopts, &PySet_Type, &py_tags, &pysubtype, &pyunit, &size, - &update_cb, &get_cb, &set_cb)) - { - return NULL; - } - - BPY_PROPDEF_SUBTYPE_CHECK(FloatVectorProperty, property_flag_items, property_subtype_array_items); - - if (pyunit && RNA_enum_value_from_id(rna_enum_property_unit_items, pyunit, &unit) == 0) { - PyErr_Format(PyExc_TypeError, "FloatVectorProperty(unit='%s'): invalid unit", pyunit); - return NULL; - } - - if (size < 1 || size > PYRNA_STACK_ARRAY) { - PyErr_Format(PyExc_TypeError, - "FloatVectorProperty(size=%d): size must be between 0 and " - STRINGIFY(PYRNA_STACK_ARRAY), size); - return NULL; - } - - if (pydef && PyC_AsArray(def, pydef, size, &PyFloat_Type, false, "FloatVectorProperty(default=sequence)") == -1) { - return NULL; - } - - if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { - return NULL; - } - if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { - return NULL; - } - if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { - return NULL; - } - - prop = RNA_def_property(srna, id, PROP_FLOAT, subtype | unit); - RNA_def_property_array(prop, size); - if (pydef) { - RNA_def_property_float_array_default(prop, def); - } - RNA_def_property_range(prop, min, max); - RNA_def_property_ui_text(prop, name ? name : id, description); - RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision); - - if (py_tags) { - RNA_def_property_tags(prop, prop_tags); - } - if (pyopts) { - bpy_prop_assign_flag(prop, opts); - } - bpy_prop_callback_assign_update(prop, update_cb); - bpy_prop_callback_assign_float_array(prop, get_cb, set_cb); - RNA_def_property_duplicate_pointers(srna, prop); - } - Py_RETURN_NONE; + StructRNA *srna; + + BPY_PROPDEF_HEAD(FloatVectorProperty); + + if (srna) { + const char *id = NULL, *name = NULL, *description = ""; + int id_len; + float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3; + float def[PYRNA_STACK_ARRAY] = {0.0f}; + int precision = 2, size = 3; + PropertyRNA *prop; + PyObject *pydef = NULL; + PyObject *pyopts = NULL; + int opts = 0; + int prop_tags = 0; + const char *pysubtype = NULL; + int subtype = PROP_NONE; + const char *pyunit = NULL; + int unit = PROP_UNIT_NONE; + PyObject *update_cb = NULL; + PyObject *get_cb = NULL; + PyObject *set_cb = NULL; + PyObject *py_tags = NULL; + + static const char *_keywords[] = { + "attr", "name", "description", "default", "min", "max", "soft_min", + "soft_max", "step", "precision", "options", "tags", "subtype", "unit", + "size", "update", "get", "set", NULL, + }; + static _PyArg_Parser _parser = {"s#|ssOfffffiO!O!ssiOOO:FloatVectorProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &id, + &id_len, + &name, + &description, + &pydef, + &min, + &max, + &soft_min, + &soft_max, + &step, + &precision, + &PySet_Type, + &pyopts, + &PySet_Type, + &py_tags, + &pysubtype, + &pyunit, + &size, + &update_cb, + &get_cb, + &set_cb)) { + return NULL; + } + + BPY_PROPDEF_SUBTYPE_CHECK( + FloatVectorProperty, property_flag_items, property_subtype_array_items); + + if (pyunit && RNA_enum_value_from_id(rna_enum_property_unit_items, pyunit, &unit) == 0) { + PyErr_Format(PyExc_TypeError, "FloatVectorProperty(unit='%s'): invalid unit", pyunit); + return NULL; + } + + if (size < 1 || size > PYRNA_STACK_ARRAY) { + PyErr_Format( + PyExc_TypeError, + "FloatVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), + size); + return NULL; + } + + if (pydef && + PyC_AsArray( + def, pydef, size, &PyFloat_Type, false, "FloatVectorProperty(default=sequence)") == + -1) { + return NULL; + } + + if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { + return NULL; + } + if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { + return NULL; + } + if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { + return NULL; + } + + prop = RNA_def_property(srna, id, PROP_FLOAT, subtype | unit); + RNA_def_property_array(prop, size); + if (pydef) { + RNA_def_property_float_array_default(prop, def); + } + RNA_def_property_range(prop, min, max); + RNA_def_property_ui_text(prop, name ? name : id, description); + RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision); + + if (py_tags) { + RNA_def_property_tags(prop, prop_tags); + } + if (pyopts) { + bpy_prop_assign_flag(prop, opts); + } + bpy_prop_callback_assign_update(prop, update_cb); + bpy_prop_callback_assign_float_array(prop, get_cb, set_cb); + RNA_def_property_duplicate_pointers(srna, prop); + } + Py_RETURN_NONE; } PyDoc_STRVAR(BPy_StringProperty_doc, -".. function:: StringProperty(name=\"\", " - "description=\"\", " - "default=\"\", " - "maxlen=0, " - "options={'ANIMATABLE'}, " - "tags={}, " - "subtype='NONE', " - "update=None, " - "get=None, " - "set=None)\n" -"\n" -" Returns a new string property definition.\n" -"\n" -BPY_PROPDEF_NAME_DOC -BPY_PROPDEF_DESC_DOC -" :arg default: initializer string.\n" -" :type default: string\n" -" :arg maxlen: maximum length of the string.\n" -" :type maxlen: int\n" -BPY_PROPDEF_OPTIONS_DOC -BPY_PROPDEF_TAGS_DOC -BPY_PROPDEF_SUBTYPE_STRING_DOC -BPY_PROPDEF_UPDATE_DOC -BPY_PROPDEF_GET_DOC -BPY_PROPDEF_SET_DOC -); + ".. function:: StringProperty(name=\"\", " + "description=\"\", " + "default=\"\", " + "maxlen=0, " + "options={'ANIMATABLE'}, " + "tags={}, " + "subtype='NONE', " + "update=None, " + "get=None, " + "set=None)\n" + "\n" + " Returns a new string property definition.\n" + "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC + " :arg default: initializer string.\n" + " :type default: string\n" + " :arg maxlen: maximum length of the string.\n" + " :type maxlen: int\n" BPY_PROPDEF_OPTIONS_DOC BPY_PROPDEF_TAGS_DOC + BPY_PROPDEF_SUBTYPE_STRING_DOC BPY_PROPDEF_UPDATE_DOC BPY_PROPDEF_GET_DOC + BPY_PROPDEF_SET_DOC); static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - BPY_PROPDEF_HEAD(StringProperty); - - if (srna) { - const char *id = NULL, *name = NULL, *description = "", *def = ""; - int id_len; - int maxlen = 0; - PropertyRNA *prop; - PyObject *pyopts = NULL; - int opts = 0; - int prop_tags = 0; - const char *pysubtype = NULL; - int subtype = PROP_NONE; - PyObject *update_cb = NULL; - PyObject *get_cb = NULL; - PyObject *set_cb = NULL; - PyObject *py_tags = NULL; - - static const char *_keywords[] = { - "attr", "name", "description", "default", - "maxlen", "options", "tags", "subtype", - "update", "get", "set", NULL, - }; - static _PyArg_Parser _parser = {"s#|sssiO!O!sOOO:StringProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id, &id_len, - &name, &description, &def, - &maxlen, &PySet_Type, &pyopts, &PySet_Type, &py_tags, &pysubtype, - &update_cb, &get_cb, &set_cb)) - { - return NULL; - } - - BPY_PROPDEF_SUBTYPE_CHECK(StringProperty, property_flag_items, property_subtype_string_items); - - if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { - return NULL; - } - if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { - return NULL; - } - if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { - return NULL; - } - - prop = RNA_def_property(srna, id, PROP_STRING, subtype); - if (maxlen != 0) { - RNA_def_property_string_maxlength(prop, maxlen + 1); /* +1 since it includes null terminator */ - } - if (def && def[0]) { - RNA_def_property_string_default(prop, def); - } - RNA_def_property_ui_text(prop, name ? name : id, description); - - if (py_tags) { - RNA_def_property_tags(prop, prop_tags); - } - if (pyopts) { - bpy_prop_assign_flag(prop, opts); - } - bpy_prop_callback_assign_update(prop, update_cb); - bpy_prop_callback_assign_string(prop, get_cb, set_cb); - RNA_def_property_duplicate_pointers(srna, prop); - } - Py_RETURN_NONE; + StructRNA *srna; + + BPY_PROPDEF_HEAD(StringProperty); + + if (srna) { + const char *id = NULL, *name = NULL, *description = "", *def = ""; + int id_len; + int maxlen = 0; + PropertyRNA *prop; + PyObject *pyopts = NULL; + int opts = 0; + int prop_tags = 0; + const char *pysubtype = NULL; + int subtype = PROP_NONE; + PyObject *update_cb = NULL; + PyObject *get_cb = NULL; + PyObject *set_cb = NULL; + PyObject *py_tags = NULL; + + static const char *_keywords[] = { + "attr", + "name", + "description", + "default", + "maxlen", + "options", + "tags", + "subtype", + "update", + "get", + "set", + NULL, + }; + static _PyArg_Parser _parser = {"s#|sssiO!O!sOOO:StringProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &id, + &id_len, + &name, + &description, + &def, + &maxlen, + &PySet_Type, + &pyopts, + &PySet_Type, + &py_tags, + &pysubtype, + &update_cb, + &get_cb, + &set_cb)) { + return NULL; + } + + BPY_PROPDEF_SUBTYPE_CHECK(StringProperty, property_flag_items, property_subtype_string_items); + + if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { + return NULL; + } + if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { + return NULL; + } + if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { + return NULL; + } + + prop = RNA_def_property(srna, id, PROP_STRING, subtype); + if (maxlen != 0) { + RNA_def_property_string_maxlength(prop, + maxlen + 1); /* +1 since it includes null terminator */ + } + if (def && def[0]) { + RNA_def_property_string_default(prop, def); + } + RNA_def_property_ui_text(prop, name ? name : id, description); + + if (py_tags) { + RNA_def_property_tags(prop, prop_tags); + } + if (pyopts) { + bpy_prop_assign_flag(prop, opts); + } + bpy_prop_callback_assign_update(prop, update_cb); + bpy_prop_callback_assign_string(prop, get_cb, set_cb); + RNA_def_property_duplicate_pointers(srna, prop); + } + Py_RETURN_NONE; } -PyDoc_STRVAR(BPy_EnumProperty_doc, -".. function:: EnumProperty(items, " - "name=\"\", " - "description=\"\", " - "default=None, " - "options={'ANIMATABLE'}, " - "tags={}, " - "update=None, " - "get=None, " - "set=None)\n" -"\n" -" Returns a new enumerator property definition.\n" -"\n" -" :arg items: sequence of enum items formatted:\n" -" ``[(identifier, name, description, icon, number), ...]``.\n" -"\n" -" The first three elements of the tuples are mandatory.\n" -"\n" -" :identifier: The identifier is used for Python access.\n" -" :name: Name for the interace.\n" -" :description: Used for documentation and tooltips.\n" -" :icon: An icon string identifier or integer icon value\n" -" (e.g. returned by :class:`bpy.types.UILayout.icon`)\n" -" :number: Unique value used as the identifier for this item (stored in file data).\n" -" Use when the identifier may need to change. If the *ENUM_FLAG* option is used,\n" -" the values are bitmasks and should be powers of two.\n" -"\n" -" When an item only contains 4 items they define ``(identifier, name, description, number)``.\n" -"\n" -" For dynamic values a callback can be passed which returns a list in\n" -" the same format as the static list.\n" -" This function must take 2 arguments ``(self, context)``, **context may be None**.\n" -"\n" -" .. warning::\n" -"\n" -" There is a known bug with using a callback,\n" -" Python must keep a reference to the strings returned or Blender will misbehave\n" -" or even crash." -"\n" -" :type items: sequence of string tuples or a function\n" -BPY_PROPDEF_NAME_DOC -BPY_PROPDEF_DESC_DOC -" :arg default: The default value for this enum, a string from the identifiers used in *items*.\n" -" If the *ENUM_FLAG* option is used this must be a set of such string identifiers instead.\n" -" WARNING: It shall not be specified (or specified to its default *None* value) for dynamic enums\n" -" (i.e. if a callback function is given as *items* parameter).\n" -" :type default: string or set\n" -BPY_PROPDEF_OPTIONS_ENUM_DOC -BPY_PROPDEF_TAGS_DOC -BPY_PROPDEF_UPDATE_DOC -BPY_PROPDEF_GET_DOC -BPY_PROPDEF_SET_DOC -); +PyDoc_STRVAR( + BPy_EnumProperty_doc, + ".. function:: EnumProperty(items, " + "name=\"\", " + "description=\"\", " + "default=None, " + "options={'ANIMATABLE'}, " + "tags={}, " + "update=None, " + "get=None, " + "set=None)\n" + "\n" + " Returns a new enumerator property definition.\n" + "\n" + " :arg items: sequence of enum items formatted:\n" + " ``[(identifier, name, description, icon, number), ...]``.\n" + "\n" + " The first three elements of the tuples are mandatory.\n" + "\n" + " :identifier: The identifier is used for Python access.\n" + " :name: Name for the interace.\n" + " :description: Used for documentation and tooltips.\n" + " :icon: An icon string identifier or integer icon value\n" + " (e.g. returned by :class:`bpy.types.UILayout.icon`)\n" + " :number: Unique value used as the identifier for this item (stored in file data).\n" + " Use when the identifier may need to change. If the *ENUM_FLAG* option is used,\n" + " the values are bitmasks and should be powers of two.\n" + "\n" + " When an item only contains 4 items they define ``(identifier, name, description, " + "number)``.\n" + "\n" + " For dynamic values a callback can be passed which returns a list in\n" + " the same format as the static list.\n" + " This function must take 2 arguments ``(self, context)``, **context may be None**.\n" + "\n" + " .. warning::\n" + "\n" + " There is a known bug with using a callback,\n" + " Python must keep a reference to the strings returned or Blender will misbehave\n" + " or even crash." + "\n" + " :type items: sequence of string tuples or a function\n" BPY_PROPDEF_NAME_DOC + BPY_PROPDEF_DESC_DOC + " :arg default: The default value for this enum, a string from the identifiers used in " + "*items*.\n" + " If the *ENUM_FLAG* option is used this must be a set of such string identifiers " + "instead.\n" + " WARNING: It shall not be specified (or specified to its default *None* value) for " + "dynamic enums\n" + " (i.e. if a callback function is given as *items* parameter).\n" + " :type default: string or set\n" BPY_PROPDEF_OPTIONS_ENUM_DOC BPY_PROPDEF_TAGS_DOC + BPY_PROPDEF_UPDATE_DOC BPY_PROPDEF_GET_DOC BPY_PROPDEF_SET_DOC); static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - BPY_PROPDEF_HEAD(EnumProperty); - - if (srna) { - const char *id = NULL, *name = NULL, *description = ""; - PyObject *def = NULL; - int id_len; - int defvalue = 0; - PyObject *items, *items_fast; - const EnumPropertyItem *eitems; - PropertyRNA *prop; - PyObject *pyopts = NULL; - int opts = 0; - int prop_tags = 0; - bool is_itemf = false; - PyObject *update_cb = NULL; - PyObject *get_cb = NULL; - PyObject *set_cb = NULL; - PyObject *py_tags = NULL; - - static const char *_keywords[] = { - "attr", "items", "name", "description", "default", - "options", "tags", "update", "get", "set", NULL, - }; - static _PyArg_Parser _parser = {"s#O|ssOO!O!OOO:EnumProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id, &id_len, - &items, &name, &description, - &def, &PySet_Type, &pyopts, &PySet_Type, &py_tags, - &update_cb, &get_cb, &set_cb)) - { - return NULL; - } - - BPY_PROPDEF_CHECK(EnumProperty, property_flag_enum_items); - - if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { - return NULL; - } - if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { - return NULL; - } - if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { - return NULL; - } - - if (def == Py_None) { - /* This allows to get same behavior when explicitly passing None as default value, - * and not defining a default value at all! */ - def = NULL; - } - - /* items can be a list or a callable */ - if (PyFunction_Check(items)) { /* don't use PyCallable_Check because we need the function code for errors */ - PyCodeObject *f_code = (PyCodeObject *)PyFunction_GET_CODE(items); - if (f_code->co_argcount != 2) { - PyErr_Format(PyExc_ValueError, - "EnumProperty(...): expected 'items' function to take 2 arguments, not %d", - f_code->co_argcount); - return NULL; - } - - if (def) { - /* note, using type error here is odd but python does this for invalid arguments */ - PyErr_SetString(PyExc_TypeError, - "EnumProperty(...): 'default' can't be set when 'items' is a function"); - return NULL; - } - - is_itemf = true; - eitems = DummyRNA_NULL_items; - } - else { - if (!(items_fast = PySequence_Fast(items, "EnumProperty(...): " - "expected a sequence of tuples for the enum items or a function"))) - { - return NULL; - } - - eitems = enum_items_from_py(items_fast, def, &defvalue, - (opts & PROP_ENUM_FLAG) != 0); - - if (!eitems) { - Py_DECREF(items_fast); - return NULL; - } - } - - if (opts & PROP_ENUM_FLAG) { - prop = RNA_def_enum_flag(srna, id, eitems, defvalue, name ? name : id, description); - } - else { - prop = RNA_def_enum(srna, id, eitems, defvalue, name ? name : id, description); - } - - if (py_tags) { - RNA_def_property_tags(prop, prop_tags); - } - if (pyopts) { - bpy_prop_assign_flag(prop, opts); - } - bpy_prop_callback_assign_update(prop, update_cb); - bpy_prop_callback_assign_enum(prop, get_cb, set_cb, (is_itemf ? items : NULL)); - RNA_def_property_duplicate_pointers(srna, prop); - - if (is_itemf == false) { - /* note: this must be postponed until after #RNA_def_property_duplicate_pointers - * otherwise if this is a generator it may free the strings before we copy them */ - Py_DECREF(items_fast); - - MEM_freeN((void *)eitems); - } - } - Py_RETURN_NONE; + StructRNA *srna; + + BPY_PROPDEF_HEAD(EnumProperty); + + if (srna) { + const char *id = NULL, *name = NULL, *description = ""; + PyObject *def = NULL; + int id_len; + int defvalue = 0; + PyObject *items, *items_fast; + const EnumPropertyItem *eitems; + PropertyRNA *prop; + PyObject *pyopts = NULL; + int opts = 0; + int prop_tags = 0; + bool is_itemf = false; + PyObject *update_cb = NULL; + PyObject *get_cb = NULL; + PyObject *set_cb = NULL; + PyObject *py_tags = NULL; + + static const char *_keywords[] = { + "attr", + "items", + "name", + "description", + "default", + "options", + "tags", + "update", + "get", + "set", + NULL, + }; + static _PyArg_Parser _parser = {"s#O|ssOO!O!OOO:EnumProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &id, + &id_len, + &items, + &name, + &description, + &def, + &PySet_Type, + &pyopts, + &PySet_Type, + &py_tags, + &update_cb, + &get_cb, + &set_cb)) { + return NULL; + } + + BPY_PROPDEF_CHECK(EnumProperty, property_flag_enum_items); + + if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { + return NULL; + } + if (bpy_prop_callback_check(get_cb, "get", 1) == -1) { + return NULL; + } + if (bpy_prop_callback_check(set_cb, "set", 2) == -1) { + return NULL; + } + + if (def == Py_None) { + /* This allows to get same behavior when explicitly passing None as default value, + * and not defining a default value at all! */ + def = NULL; + } + + /* items can be a list or a callable */ + if (PyFunction_Check( + items)) { /* don't use PyCallable_Check because we need the function code for errors */ + PyCodeObject *f_code = (PyCodeObject *)PyFunction_GET_CODE(items); + if (f_code->co_argcount != 2) { + PyErr_Format(PyExc_ValueError, + "EnumProperty(...): expected 'items' function to take 2 arguments, not %d", + f_code->co_argcount); + return NULL; + } + + if (def) { + /* note, using type error here is odd but python does this for invalid arguments */ + PyErr_SetString(PyExc_TypeError, + "EnumProperty(...): 'default' can't be set when 'items' is a function"); + return NULL; + } + + is_itemf = true; + eitems = DummyRNA_NULL_items; + } + else { + if (!(items_fast = PySequence_Fast( + items, + "EnumProperty(...): " + "expected a sequence of tuples for the enum items or a function"))) { + return NULL; + } + + eitems = enum_items_from_py(items_fast, def, &defvalue, (opts & PROP_ENUM_FLAG) != 0); + + if (!eitems) { + Py_DECREF(items_fast); + return NULL; + } + } + + if (opts & PROP_ENUM_FLAG) { + prop = RNA_def_enum_flag(srna, id, eitems, defvalue, name ? name : id, description); + } + else { + prop = RNA_def_enum(srna, id, eitems, defvalue, name ? name : id, description); + } + + if (py_tags) { + RNA_def_property_tags(prop, prop_tags); + } + if (pyopts) { + bpy_prop_assign_flag(prop, opts); + } + bpy_prop_callback_assign_update(prop, update_cb); + bpy_prop_callback_assign_enum(prop, get_cb, set_cb, (is_itemf ? items : NULL)); + RNA_def_property_duplicate_pointers(srna, prop); + + if (is_itemf == false) { + /* note: this must be postponed until after #RNA_def_property_duplicate_pointers + * otherwise if this is a generator it may free the strings before we copy them */ + Py_DECREF(items_fast); + + MEM_freeN((void *)eitems); + } + } + Py_RETURN_NONE; } StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix) { - StructRNA *srna; - - srna = srna_from_self(value, ""); - if (!srna) { - if (PyErr_Occurred()) { - PyObject *msg = PyC_ExceptionBuffer(); - const char *msg_char = _PyUnicode_AsString(msg); - PyErr_Format(PyExc_TypeError, - "%.200s expected an RNA type, failed with: %s", - error_prefix, msg_char); - Py_DECREF(msg); - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s expected an RNA type, failed with type '%s'", - error_prefix, Py_TYPE(value)->tp_name); - } - return NULL; - } - - return srna; + StructRNA *srna; + + srna = srna_from_self(value, ""); + if (!srna) { + if (PyErr_Occurred()) { + PyObject *msg = PyC_ExceptionBuffer(); + const char *msg_char = _PyUnicode_AsString(msg); + PyErr_Format( + PyExc_TypeError, "%.200s expected an RNA type, failed with: %s", error_prefix, msg_char); + Py_DECREF(msg); + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s expected an RNA type, failed with type '%s'", + error_prefix, + Py_TYPE(value)->tp_name); + } + return NULL; + } + + return srna; } PyDoc_STRVAR(BPy_PointerProperty_doc, -".. function:: PointerProperty(type=None, " - "name=\"\", " - "description=\"\", " - "options={'ANIMATABLE'}, " - "tags={}, " - "poll=None, " - "update=None)\n" -"\n" -" Returns a new pointer property definition.\n" -"\n" -BPY_PROPDEF_TYPE_DOC -BPY_PROPDEF_NAME_DOC -BPY_PROPDEF_DESC_DOC -BPY_PROPDEF_OPTIONS_DOC -BPY_PROPDEF_TAGS_DOC -BPY_PROPDEF_POLL_DOC -BPY_PROPDEF_UPDATE_DOC -); + ".. function:: PointerProperty(type=None, " + "name=\"\", " + "description=\"\", " + "options={'ANIMATABLE'}, " + "tags={}, " + "poll=None, " + "update=None)\n" + "\n" + " Returns a new pointer property definition.\n" + "\n" BPY_PROPDEF_TYPE_DOC BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC + BPY_PROPDEF_OPTIONS_DOC BPY_PROPDEF_TAGS_DOC BPY_PROPDEF_POLL_DOC + BPY_PROPDEF_UPDATE_DOC); PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - BPY_PROPDEF_HEAD(PointerProperty); - - if (srna) { - const char *id = NULL, *name = NULL, *description = ""; - int id_len; - PropertyRNA *prop; - StructRNA *ptype; - PyObject *type = Py_None; - PyObject *pyopts = NULL; - PyObject *py_tags = NULL; - int opts = 0; - int prop_tags = 0; - PyObject *update_cb = NULL, *poll_cb = NULL; - - static const char *_keywords[] = { - "attr", "type", "name", "description", "options", - "tags", "poll", "update", NULL, - }; - static _PyArg_Parser _parser = {"s#O|ssO!O!OO:PointerProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id, &id_len, - &type, &name, &description, - &PySet_Type, &pyopts, &PySet_Type, &py_tags, - &poll_cb, &update_cb)) - { - return NULL; - } - - BPY_PROPDEF_CHECK(PointerProperty, property_flag_items); - - ptype = pointer_type_from_py(type, "PointerProperty(...)"); - if (!ptype) { - return NULL; - } - if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup) && !RNA_struct_is_ID(ptype)) { - PyErr_Format(PyExc_TypeError, - "PointerProperty(...) expected an RNA type derived from %.200s or %.200s", - RNA_struct_ui_name(&RNA_ID), RNA_struct_ui_name(&RNA_PropertyGroup)); - return NULL; - } - if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { - return NULL; - } - if (bpy_prop_callback_check(poll_cb, "poll", 2) == -1) { - return NULL; - } - prop = RNA_def_pointer_runtime(srna, id, ptype, name ? name : id, description); - if (py_tags) { - RNA_def_property_tags(prop, prop_tags); - } - if (pyopts) { - bpy_prop_assign_flag(prop, opts); - } - - if (RNA_struct_idprops_contains_datablock(ptype)) { - if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) { - RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES); - } - } - bpy_prop_callback_assign_update(prop, update_cb); - bpy_prop_callback_assign_pointer(prop, poll_cb); - RNA_def_property_duplicate_pointers(srna, prop); - } - Py_RETURN_NONE; + StructRNA *srna; + + BPY_PROPDEF_HEAD(PointerProperty); + + if (srna) { + const char *id = NULL, *name = NULL, *description = ""; + int id_len; + PropertyRNA *prop; + StructRNA *ptype; + PyObject *type = Py_None; + PyObject *pyopts = NULL; + PyObject *py_tags = NULL; + int opts = 0; + int prop_tags = 0; + PyObject *update_cb = NULL, *poll_cb = NULL; + + static const char *_keywords[] = { + "attr", + "type", + "name", + "description", + "options", + "tags", + "poll", + "update", + NULL, + }; + static _PyArg_Parser _parser = {"s#O|ssO!O!OO:PointerProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &id, + &id_len, + &type, + &name, + &description, + &PySet_Type, + &pyopts, + &PySet_Type, + &py_tags, + &poll_cb, + &update_cb)) { + return NULL; + } + + BPY_PROPDEF_CHECK(PointerProperty, property_flag_items); + + ptype = pointer_type_from_py(type, "PointerProperty(...)"); + if (!ptype) { + return NULL; + } + if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup) && !RNA_struct_is_ID(ptype)) { + PyErr_Format(PyExc_TypeError, + "PointerProperty(...) expected an RNA type derived from %.200s or %.200s", + RNA_struct_ui_name(&RNA_ID), + RNA_struct_ui_name(&RNA_PropertyGroup)); + return NULL; + } + if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { + return NULL; + } + if (bpy_prop_callback_check(poll_cb, "poll", 2) == -1) { + return NULL; + } + prop = RNA_def_pointer_runtime(srna, id, ptype, name ? name : id, description); + if (py_tags) { + RNA_def_property_tags(prop, prop_tags); + } + if (pyopts) { + bpy_prop_assign_flag(prop, opts); + } + + if (RNA_struct_idprops_contains_datablock(ptype)) { + if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) { + RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES); + } + } + bpy_prop_callback_assign_update(prop, update_cb); + bpy_prop_callback_assign_pointer(prop, poll_cb); + RNA_def_property_duplicate_pointers(srna, prop); + } + Py_RETURN_NONE; } PyDoc_STRVAR(BPy_CollectionProperty_doc, -".. function:: CollectionProperty(type=None, " - "name=\"\", " - "description=\"\", " - "options={'ANIMATABLE'}, " - "tags={})\n" -"\n" -" Returns a new collection property definition.\n" -"\n" -BPY_PROPDEF_TYPE_DOC -BPY_PROPDEF_NAME_DOC -BPY_PROPDEF_DESC_DOC -BPY_PROPDEF_OPTIONS_DOC -BPY_PROPDEF_TAGS_DOC -); + ".. function:: CollectionProperty(type=None, " + "name=\"\", " + "description=\"\", " + "options={'ANIMATABLE'}, " + "tags={})\n" + "\n" + " Returns a new collection property definition.\n" + "\n" BPY_PROPDEF_TYPE_DOC BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC + BPY_PROPDEF_OPTIONS_DOC BPY_PROPDEF_TAGS_DOC); PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - BPY_PROPDEF_HEAD(CollectionProperty); - - if (srna) { - int id_len; - const char *id = NULL, *name = NULL, *description = ""; - PropertyRNA *prop; - StructRNA *ptype; - PyObject *type = Py_None; - PyObject *pyopts = NULL; - PyObject *py_tags = NULL; - int opts = 0; - int prop_tags = 0; - - static const char *_keywords[] = { - "attr", "type", "name", "description", - "options", "tags", NULL, - }; - static _PyArg_Parser _parser = {"s#O|ssO!O!:CollectionProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id, &id_len, - &type, &name, &description, - &PySet_Type, &pyopts, &PySet_Type, &py_tags)) - { - return NULL; - } - - BPY_PROPDEF_CHECK(CollectionProperty, property_flag_items); - - ptype = pointer_type_from_py(type, "CollectionProperty(...):"); - if (!ptype) { - return NULL; - } - - if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup)) { - PyErr_Format( - PyExc_TypeError, - "CollectionProperty(...) expected an RNA type derived from %.200s", - RNA_struct_ui_name(&RNA_ID), RNA_struct_ui_name(&RNA_PropertyGroup)); - return NULL; - } - - prop = RNA_def_collection_runtime(srna, id, ptype, name ? name : id, description); - if (py_tags) { - RNA_def_property_tags(prop, prop_tags); - } - if (pyopts) { - bpy_prop_assign_flag(prop, opts); - } - - if (RNA_struct_idprops_contains_datablock(ptype)) { - if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) { - RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES); - } - } - RNA_def_property_duplicate_pointers(srna, prop); - } - Py_RETURN_NONE; + StructRNA *srna; + + BPY_PROPDEF_HEAD(CollectionProperty); + + if (srna) { + int id_len; + const char *id = NULL, *name = NULL, *description = ""; + PropertyRNA *prop; + StructRNA *ptype; + PyObject *type = Py_None; + PyObject *pyopts = NULL; + PyObject *py_tags = NULL; + int opts = 0; + int prop_tags = 0; + + static const char *_keywords[] = { + "attr", + "type", + "name", + "description", + "options", + "tags", + NULL, + }; + static _PyArg_Parser _parser = {"s#O|ssO!O!:CollectionProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &id, + &id_len, + &type, + &name, + &description, + &PySet_Type, + &pyopts, + &PySet_Type, + &py_tags)) { + return NULL; + } + + BPY_PROPDEF_CHECK(CollectionProperty, property_flag_items); + + ptype = pointer_type_from_py(type, "CollectionProperty(...):"); + if (!ptype) { + return NULL; + } + + if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup)) { + PyErr_Format(PyExc_TypeError, + "CollectionProperty(...) expected an RNA type derived from %.200s", + RNA_struct_ui_name(&RNA_ID), + RNA_struct_ui_name(&RNA_PropertyGroup)); + return NULL; + } + + prop = RNA_def_collection_runtime(srna, id, ptype, name ? name : id, description); + if (py_tags) { + RNA_def_property_tags(prop, prop_tags); + } + if (pyopts) { + bpy_prop_assign_flag(prop, opts); + } + + if (RNA_struct_idprops_contains_datablock(ptype)) { + if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) { + RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES); + } + } + RNA_def_property_duplicate_pointers(srna, prop); + } + Py_RETURN_NONE; } PyDoc_STRVAR(BPy_RemoveProperty_doc, -".. function:: RemoveProperty(cls, attr)\n" -"\n" -" Removes a dynamically defined property.\n" -"\n" -" :arg cls: The class containing the property (must be a positional argument).\n" -" :type cls: type\n" -" :arg attr: Property name (must be passed as a keyword).\n" -" :type attr: string\n" -"\n" -".. note:: Typically this function doesn't need to be accessed directly.\n" -" Instead use ``del cls.attr``\n" -); + ".. function:: RemoveProperty(cls, attr)\n" + "\n" + " Removes a dynamically defined property.\n" + "\n" + " :arg cls: The class containing the property (must be a positional argument).\n" + " :type cls: type\n" + " :arg attr: Property name (must be passed as a keyword).\n" + " :type attr: string\n" + "\n" + ".. note:: Typically this function doesn't need to be accessed directly.\n" + " Instead use ``del cls.attr``\n"); static PyObject *BPy_RemoveProperty(PyObject *self, PyObject *args, PyObject *kw) { - StructRNA *srna; - - if (PyTuple_GET_SIZE(args) == 1) { - PyObject *ret; - self = PyTuple_GET_ITEM(args, 0); - args = PyTuple_New(0); - ret = BPy_RemoveProperty(self, args, kw); - Py_DECREF(args); - return ret; - } - else if (PyTuple_GET_SIZE(args) > 1) { - PyErr_SetString(PyExc_ValueError, "expected one positional arg, one keyword arg"); - return NULL; - } - - srna = srna_from_self(self, "RemoveProperty(...):"); - if (srna == NULL && PyErr_Occurred()) { - return NULL; /* self's type was compatible but error getting the srna */ - } - else if (srna == NULL) { - PyErr_SetString(PyExc_TypeError, "RemoveProperty(): struct rna not available for this type"); - return NULL; - } - else { - const char *id = NULL; - - static const char *_keywords[] = { - "attr", NULL, - }; - static _PyArg_Parser _parser = {"s:RemoveProperty", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &id)) - { - return NULL; - } - - if (RNA_def_property_free_identifier(srna, id) != 1) { - PyErr_Format(PyExc_TypeError, "RemoveProperty(): '%s' not a defined dynamic property", id); - return NULL; - } - } - Py_RETURN_NONE; + StructRNA *srna; + + if (PyTuple_GET_SIZE(args) == 1) { + PyObject *ret; + self = PyTuple_GET_ITEM(args, 0); + args = PyTuple_New(0); + ret = BPy_RemoveProperty(self, args, kw); + Py_DECREF(args); + return ret; + } + else if (PyTuple_GET_SIZE(args) > 1) { + PyErr_SetString(PyExc_ValueError, "expected one positional arg, one keyword arg"); + return NULL; + } + + srna = srna_from_self(self, "RemoveProperty(...):"); + if (srna == NULL && PyErr_Occurred()) { + return NULL; /* self's type was compatible but error getting the srna */ + } + else if (srna == NULL) { + PyErr_SetString(PyExc_TypeError, "RemoveProperty(): struct rna not available for this type"); + return NULL; + } + else { + const char *id = NULL; + + static const char *_keywords[] = { + "attr", + NULL, + }; + static _PyArg_Parser _parser = {"s:RemoveProperty", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &id)) { + return NULL; + } + + if (RNA_def_property_free_identifier(srna, id) != 1) { + PyErr_Format(PyExc_TypeError, "RemoveProperty(): '%s' not a defined dynamic property", id); + return NULL; + } + } + Py_RETURN_NONE; } static struct PyMethodDef props_methods[] = { - {"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS | METH_KEYWORDS, BPy_BoolProperty_doc}, - {"BoolVectorProperty", (PyCFunction)BPy_BoolVectorProperty, METH_VARARGS | METH_KEYWORDS, BPy_BoolVectorProperty_doc}, - {"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS | METH_KEYWORDS, BPy_IntProperty_doc}, - {"IntVectorProperty", (PyCFunction)BPy_IntVectorProperty, METH_VARARGS | METH_KEYWORDS, BPy_IntVectorProperty_doc}, - {"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS | METH_KEYWORDS, BPy_FloatProperty_doc}, - {"FloatVectorProperty", (PyCFunction)BPy_FloatVectorProperty, METH_VARARGS | METH_KEYWORDS, BPy_FloatVectorProperty_doc}, - {"StringProperty", (PyCFunction)BPy_StringProperty, METH_VARARGS | METH_KEYWORDS, BPy_StringProperty_doc}, - {"EnumProperty", (PyCFunction)BPy_EnumProperty, METH_VARARGS | METH_KEYWORDS, BPy_EnumProperty_doc}, - {"PointerProperty", (PyCFunction)BPy_PointerProperty, METH_VARARGS | METH_KEYWORDS, BPy_PointerProperty_doc}, - {"CollectionProperty", (PyCFunction)BPy_CollectionProperty, METH_VARARGS | METH_KEYWORDS, BPy_CollectionProperty_doc}, - - {"RemoveProperty", (PyCFunction)BPy_RemoveProperty, METH_VARARGS | METH_KEYWORDS, BPy_RemoveProperty_doc}, - {NULL, NULL, 0, NULL}, + {"BoolProperty", + (PyCFunction)BPy_BoolProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_BoolProperty_doc}, + {"BoolVectorProperty", + (PyCFunction)BPy_BoolVectorProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_BoolVectorProperty_doc}, + {"IntProperty", + (PyCFunction)BPy_IntProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_IntProperty_doc}, + {"IntVectorProperty", + (PyCFunction)BPy_IntVectorProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_IntVectorProperty_doc}, + {"FloatProperty", + (PyCFunction)BPy_FloatProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_FloatProperty_doc}, + {"FloatVectorProperty", + (PyCFunction)BPy_FloatVectorProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_FloatVectorProperty_doc}, + {"StringProperty", + (PyCFunction)BPy_StringProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_StringProperty_doc}, + {"EnumProperty", + (PyCFunction)BPy_EnumProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_EnumProperty_doc}, + {"PointerProperty", + (PyCFunction)BPy_PointerProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_PointerProperty_doc}, + {"CollectionProperty", + (PyCFunction)BPy_CollectionProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_CollectionProperty_doc}, + + {"RemoveProperty", + (PyCFunction)BPy_RemoveProperty, + METH_VARARGS | METH_KEYWORDS, + BPy_RemoveProperty_doc}, + {NULL, NULL, 0, NULL}, }; static struct PyModuleDef props_module = { - PyModuleDef_HEAD_INIT, - "bpy.props", - "This module defines properties to extend Blender's internal data. The result of these functions" - " is used to assign properties to classes registered with Blender and can't be used directly.\n" - "\n" - ".. note:: All parameters to these functions must be passed as keywords.\n", - -1, /* multiple "initialization" just copies the module dict. */ - props_methods, - NULL, NULL, NULL, NULL, + PyModuleDef_HEAD_INIT, + "bpy.props", + "This module defines properties to extend Blender's internal data. The result of these " + "functions" + " is used to assign properties to classes registered with Blender and can't be used " + "directly.\n" + "\n" + ".. note:: All parameters to these functions must be passed as keywords.\n", + -1, /* multiple "initialization" just copies the module dict. */ + props_methods, + NULL, + NULL, + NULL, + NULL, }; PyObject *BPY_rna_props(void) { - PyObject *submodule; - PyObject *submodule_dict; + PyObject *submodule; + PyObject *submodule_dict; - submodule = PyModule_Create(&props_module); - PyDict_SetItemString(PyImport_GetModuleDict(), props_module.m_name, submodule); + submodule = PyModule_Create(&props_module); + PyDict_SetItemString(PyImport_GetModuleDict(), props_module.m_name, submodule); - /* api needs the PyObjects internally */ - submodule_dict = PyModule_GetDict(submodule); + /* api needs the PyObjects internally */ + submodule_dict = PyModule_GetDict(submodule); #define ASSIGN_STATIC(_name) pymeth_##_name = PyDict_GetItemString(submodule_dict, #_name) - ASSIGN_STATIC(BoolProperty); - ASSIGN_STATIC(BoolVectorProperty); - ASSIGN_STATIC(IntProperty); - ASSIGN_STATIC(IntVectorProperty); - ASSIGN_STATIC(FloatProperty); - ASSIGN_STATIC(FloatVectorProperty); - ASSIGN_STATIC(StringProperty); - ASSIGN_STATIC(EnumProperty); - ASSIGN_STATIC(PointerProperty); - ASSIGN_STATIC(CollectionProperty); - ASSIGN_STATIC(RemoveProperty); - - return submodule; + ASSIGN_STATIC(BoolProperty); + ASSIGN_STATIC(BoolVectorProperty); + ASSIGN_STATIC(IntProperty); + ASSIGN_STATIC(IntVectorProperty); + ASSIGN_STATIC(FloatProperty); + ASSIGN_STATIC(FloatVectorProperty); + ASSIGN_STATIC(StringProperty); + ASSIGN_STATIC(EnumProperty); + ASSIGN_STATIC(PointerProperty); + ASSIGN_STATIC(CollectionProperty); + ASSIGN_STATIC(RemoveProperty); + + return submodule; } diff --git a/source/blender/python/intern/bpy_props.h b/source/blender/python/intern/bpy_props.h index 4741239be52..d559a3493b4 100644 --- a/source/blender/python/intern/bpy_props.h +++ b/source/blender/python/intern/bpy_props.h @@ -18,7 +18,6 @@ * \ingroup pythonintern */ - #ifndef __BPY_PROPS_H__ #define __BPY_PROPS_H__ diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 71d46de1be8..cf45d6ca2d9 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -83,73 +83,71 @@ BPy_StructRNA *bpy_context_module = NULL; /* for fast access */ static PyObject *pyrna_struct_Subtype(PointerRNA *ptr); static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self); -#define BPY_DOC_ID_PROP_TYPE_NOTE \ -" .. note::\n" \ -"\n" \ -" Only :class:`bpy.types.ID`, :class:`bpy.types.Bone` and\n" \ -" :class:`bpy.types.PoseBone` classes support custom properties.\n" - +#define BPY_DOC_ID_PROP_TYPE_NOTE \ + " .. note::\n" \ + "\n" \ + " Only :class:`bpy.types.ID`, :class:`bpy.types.Bone` and\n" \ + " :class:`bpy.types.PoseBone` classes support custom properties.\n" int pyrna_struct_validity_check(BPy_StructRNA *pysrna) { - if (pysrna->ptr.type) { - return 0; - } - PyErr_Format(PyExc_ReferenceError, - "StructRNA of type %.200s has been removed", - Py_TYPE(pysrna)->tp_name); - return -1; + if (pysrna->ptr.type) { + return 0; + } + PyErr_Format( + PyExc_ReferenceError, "StructRNA of type %.200s has been removed", Py_TYPE(pysrna)->tp_name); + return -1; } int pyrna_prop_validity_check(BPy_PropertyRNA *self) { - if (self->ptr.type) { - return 0; - } - PyErr_Format(PyExc_ReferenceError, - "PropertyRNA of type %.200s.%.200s has been removed", - Py_TYPE(self)->tp_name, RNA_property_identifier(self->prop)); - return -1; + if (self->ptr.type) { + return 0; + } + PyErr_Format(PyExc_ReferenceError, + "PropertyRNA of type %.200s.%.200s has been removed", + Py_TYPE(self)->tp_name, + RNA_property_identifier(self->prop)); + return -1; } void pyrna_invalidate(BPy_DummyPointerRNA *self) { - RNA_POINTER_INVALIDATE(&self->ptr); + RNA_POINTER_INVALIDATE(&self->ptr); } #ifdef USE_PYRNA_INVALIDATE_GC -#define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g) + 1)) +# define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g) + 1)) /* only for sizeof() */ struct gc_generation { - PyGC_Head head; - int threshold; - int count; + PyGC_Head head; + int threshold; + int count; } gc_generation; static void id_release_gc(struct ID *id) { - unsigned int j; - // unsigned int i = 0; - for (j = 0; j < 3; j++) { - /* hack below to get the 2 other lists from _PyGC_generation0 that are normally not exposed */ - PyGC_Head *gen = (PyGC_Head *)(((char *)_PyGC_generation0) + (sizeof(gc_generation) * j)); - PyGC_Head *g = gen->gc.gc_next; - while ((g = g->gc.gc_next) != gen) { - PyObject *ob = FROM_GC(g); - if (PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) || - PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) - { - BPy_DummyPointerRNA *ob_ptr = (BPy_DummyPointerRNA *)ob; - if (ob_ptr->ptr.id.data == id) { - pyrna_invalidate(ob_ptr); - // printf("freeing: %p %s, %.200s\n", (void *)ob, id->name, Py_TYPE(ob)->tp_name); - // i++; - } - } - } - } - // printf("id_release_gc freed '%s': %d\n", id->name, i); + unsigned int j; + // unsigned int i = 0; + for (j = 0; j < 3; j++) { + /* hack below to get the 2 other lists from _PyGC_generation0 that are normally not exposed */ + PyGC_Head *gen = (PyGC_Head *)(((char *)_PyGC_generation0) + (sizeof(gc_generation) * j)); + PyGC_Head *g = gen->gc.gc_next; + while ((g = g->gc.gc_next) != gen) { + PyObject *ob = FROM_GC(g); + if (PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) || + PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) { + BPy_DummyPointerRNA *ob_ptr = (BPy_DummyPointerRNA *)ob; + if (ob_ptr->ptr.id.data == id) { + pyrna_invalidate(ob_ptr); + // printf("freeing: %p %s, %.200s\n", (void *)ob, id->name, Py_TYPE(ob)->tp_name); + // i++; + } + } + } + } + // printf("id_release_gc freed '%s': %d\n", id->name, i); } #endif @@ -158,128 +156,128 @@ static void id_release_gc(struct ID *id) struct GHash *id_weakref_pool = NULL; static PyObject *id_free_weakref_cb(PyObject *weakinfo_pair, PyObject *weakref); -static PyMethodDef id_free_weakref_cb_def = {"id_free_weakref_cb", (PyCFunction)id_free_weakref_cb, METH_O, NULL}; +static PyMethodDef id_free_weakref_cb_def = { + "id_free_weakref_cb", (PyCFunction)id_free_weakref_cb, METH_O, NULL}; /* adds a reference to the list, remember to decref */ static GHash *id_weakref_pool_get(ID *id) { - GHash *weakinfo_hash = NULL; + GHash *weakinfo_hash = NULL; - if (id_weakref_pool) { - weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id); - } - else { - /* first time, allocate pool */ - id_weakref_pool = BLI_ghash_ptr_new("rna_global_pool"); - weakinfo_hash = NULL; - } + if (id_weakref_pool) { + weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id); + } + else { + /* first time, allocate pool */ + id_weakref_pool = BLI_ghash_ptr_new("rna_global_pool"); + weakinfo_hash = NULL; + } - if (weakinfo_hash == NULL) { - /* we're using a ghash as a set, could use libHX's HXMAP_SINGULAR but would be an extra dep. */ - weakinfo_hash = BLI_ghash_ptr_new("rna_id"); - BLI_ghash_insert(id_weakref_pool, id, weakinfo_hash); - } + if (weakinfo_hash == NULL) { + /* we're using a ghash as a set, could use libHX's HXMAP_SINGULAR but would be an extra dep. */ + weakinfo_hash = BLI_ghash_ptr_new("rna_id"); + BLI_ghash_insert(id_weakref_pool, id, weakinfo_hash); + } - return weakinfo_hash; + return weakinfo_hash; } /* called from pyrna_struct_CreatePyObject() and pyrna_prop_CreatePyObject() */ static void id_weakref_pool_add(ID *id, BPy_DummyPointerRNA *pyrna) { - PyObject *weakref; - PyObject *weakref_capsule; - PyObject *weakref_cb_py; - - /* create a new function instance and insert the list as 'self' so we can remove ourself from it */ - GHash *weakinfo_hash = id_weakref_pool_get(id); /* new or existing */ + PyObject *weakref; + PyObject *weakref_capsule; + PyObject *weakref_cb_py; - weakref_capsule = PyCapsule_New(weakinfo_hash, NULL, NULL); - weakref_cb_py = PyCFunction_New(&id_free_weakref_cb_def, weakref_capsule); - Py_DECREF(weakref_capsule); + /* create a new function instance and insert the list as 'self' so we can remove ourself from it */ + GHash *weakinfo_hash = id_weakref_pool_get(id); /* new or existing */ - /* add weakref to weakinfo_hash list */ - weakref = PyWeakref_NewRef((PyObject *)pyrna, weakref_cb_py); + weakref_capsule = PyCapsule_New(weakinfo_hash, NULL, NULL); + weakref_cb_py = PyCFunction_New(&id_free_weakref_cb_def, weakref_capsule); + Py_DECREF(weakref_capsule); - Py_DECREF(weakref_cb_py); /* function owned by the weakref now */ + /* add weakref to weakinfo_hash list */ + weakref = PyWeakref_NewRef((PyObject *)pyrna, weakref_cb_py); - /* important to add at the end, since first removal looks at the end */ - BLI_ghash_insert(weakinfo_hash, weakref, id); /* using a hash table as a set, all 'id's are the same */ - /* weakinfo_hash owns the weakref */ + Py_DECREF(weakref_cb_py); /* function owned by the weakref now */ + /* important to add at the end, since first removal looks at the end */ + BLI_ghash_insert( + weakinfo_hash, weakref, id); /* using a hash table as a set, all 'id's are the same */ + /* weakinfo_hash owns the weakref */ } /* workaround to get the last id without a lookup */ static ID *_id_tmp_ptr; static void value_id_set(void *id) { - _id_tmp_ptr = (ID *)id; + _id_tmp_ptr = (ID *)id; } static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash); static PyObject *id_free_weakref_cb(PyObject *weakinfo_capsule, PyObject *weakref) { - /* important to search backwards */ - GHash *weakinfo_hash = PyCapsule_GetPointer(weakinfo_capsule, NULL); + /* important to search backwards */ + GHash *weakinfo_hash = PyCapsule_GetPointer(weakinfo_capsule, NULL); + if (BLI_ghash_len(weakinfo_hash) > 1) { + BLI_ghash_remove(weakinfo_hash, weakref, NULL, NULL); + } + else { /* get the last id and free it */ + BLI_ghash_remove(weakinfo_hash, weakref, NULL, value_id_set); + id_release_weakref_list(_id_tmp_ptr, weakinfo_hash); + } - if (BLI_ghash_len(weakinfo_hash) > 1) { - BLI_ghash_remove(weakinfo_hash, weakref, NULL, NULL); - } - else { /* get the last id and free it */ - BLI_ghash_remove(weakinfo_hash, weakref, NULL, value_id_set); - id_release_weakref_list(_id_tmp_ptr, weakinfo_hash); - } + Py_DECREF(weakref); - Py_DECREF(weakref); - - Py_RETURN_NONE; + Py_RETURN_NONE; } static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash) { - GHashIterator weakinfo_hash_iter; + GHashIterator weakinfo_hash_iter; - BLI_ghashIterator_init(&weakinfo_hash_iter, weakinfo_hash); + BLI_ghashIterator_init(&weakinfo_hash_iter, weakinfo_hash); -#ifdef DEBUG_RNA_WEAKREF - fprintf(stdout, "id_release_weakref: '%s', %d items\n", id->name, BLI_ghash_len(weakinfo_hash)); -#endif +# ifdef DEBUG_RNA_WEAKREF + fprintf(stdout, "id_release_weakref: '%s', %d items\n", id->name, BLI_ghash_len(weakinfo_hash)); +# endif - while (!BLI_ghashIterator_done(&weakinfo_hash_iter)) { - PyObject *weakref = (PyObject *)BLI_ghashIterator_getKey(&weakinfo_hash_iter); - PyObject *item = PyWeakref_GET_OBJECT(weakref); - if (item != Py_None) { + while (!BLI_ghashIterator_done(&weakinfo_hash_iter)) { + PyObject *weakref = (PyObject *)BLI_ghashIterator_getKey(&weakinfo_hash_iter); + PyObject *item = PyWeakref_GET_OBJECT(weakref); + if (item != Py_None) { -#ifdef DEBUG_RNA_WEAKREF - PyC_ObSpit("id_release_weakref item ", item); -#endif +# ifdef DEBUG_RNA_WEAKREF + PyC_ObSpit("id_release_weakref item ", item); +# endif - pyrna_invalidate((BPy_DummyPointerRNA *)item); - } + pyrna_invalidate((BPy_DummyPointerRNA *)item); + } - Py_DECREF(weakref); + Py_DECREF(weakref); - BLI_ghashIterator_step(&weakinfo_hash_iter); - } + BLI_ghashIterator_step(&weakinfo_hash_iter); + } - BLI_ghash_remove(id_weakref_pool, (void *)id, NULL, NULL); - BLI_ghash_free(weakinfo_hash, NULL, NULL); + BLI_ghash_remove(id_weakref_pool, (void *)id, NULL, NULL); + BLI_ghash_free(weakinfo_hash, NULL, NULL); - if (BLI_ghash_len(id_weakref_pool) == 0) { - BLI_ghash_free(id_weakref_pool, NULL, NULL); - id_weakref_pool = NULL; -#ifdef DEBUG_RNA_WEAKREF - printf("id_release_weakref freeing pool\n"); -#endif - } + if (BLI_ghash_len(id_weakref_pool) == 0) { + BLI_ghash_free(id_weakref_pool, NULL, NULL); + id_weakref_pool = NULL; +# ifdef DEBUG_RNA_WEAKREF + printf("id_release_weakref freeing pool\n"); +# endif + } } static void id_release_weakref(struct ID *id) { - GHash *weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id); - if (weakinfo_hash) { - id_release_weakref_list(id, weakinfo_hash); - } + GHash *weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id); + if (weakinfo_hash) { + id_release_weakref_list(id, weakinfo_hash); + } } #endif /* USE_PYRNA_INVALIDATE_WEAKREF */ @@ -287,20 +285,20 @@ static void id_release_weakref(struct ID *id) void BPY_id_release(struct ID *id) { #ifdef USE_PYRNA_INVALIDATE_GC - id_release_gc(id); + id_release_gc(id); #endif #ifdef USE_PYRNA_INVALIDATE_WEAKREF - if (id_weakref_pool) { - PyGILState_STATE gilstate = PyGILState_Ensure(); + if (id_weakref_pool) { + PyGILState_STATE gilstate = PyGILState_Ensure(); - id_release_weakref(id); + id_release_weakref(id); - PyGILState_Release(gilstate); - } + PyGILState_Release(gilstate); + } #endif /* USE_PYRNA_INVALIDATE_WEAKREF */ - (void)id; + (void)id; } #ifdef USE_PEDANTIC_WRITE @@ -308,480 +306,487 @@ static bool rna_disallow_writes = false; static bool rna_id_write_error(PointerRNA *ptr, PyObject *key) { - ID *id = ptr->id.data; - if (id) { - const short idcode = GS(id->name); - if (!ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { /* may need more added here */ - const char *idtype = BKE_idcode_to_name(idcode); - const char *pyname; - if (key && PyUnicode_Check(key)) { - pyname = _PyUnicode_AsString(key); - } - else { - pyname = "<UNKNOWN>"; - } - - /* make a nice string error */ - BLI_assert(idtype != NULL); - PyErr_Format(PyExc_AttributeError, - "Writing to ID classes in this context is not allowed: " - "%.200s, %.200s datablock, error setting %.200s.%.200s", - id->name + 2, idtype, RNA_struct_identifier(ptr->type), pyname); - - return true; - } - } - return false; -} -#endif /* USE_PEDANTIC_WRITE */ - + ID *id = ptr->id.data; + if (id) { + const short idcode = GS(id->name); + if (!ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { /* may need more added here */ + const char *idtype = BKE_idcode_to_name(idcode); + const char *pyname; + if (key && PyUnicode_Check(key)) { + pyname = _PyUnicode_AsString(key); + } + else { + pyname = "<UNKNOWN>"; + } + + /* make a nice string error */ + BLI_assert(idtype != NULL); + PyErr_Format(PyExc_AttributeError, + "Writing to ID classes in this context is not allowed: " + "%.200s, %.200s datablock, error setting %.200s.%.200s", + id->name + 2, + idtype, + RNA_struct_identifier(ptr->type), + pyname); + + return true; + } + } + return false; +} +#endif /* USE_PEDANTIC_WRITE */ #ifdef USE_PEDANTIC_WRITE bool pyrna_write_check(void) { - return !rna_disallow_writes; + return !rna_disallow_writes; } void pyrna_write_set(bool val) { - rna_disallow_writes = !val; + rna_disallow_writes = !val; } #else /* USE_PEDANTIC_WRITE */ bool pyrna_write_check(void) { - return true; + return true; } void pyrna_write_set(bool UNUSED(val)) { - /* nothing */ + /* nothing */ } -#endif /* USE_PEDANTIC_WRITE */ +#endif /* USE_PEDANTIC_WRITE */ static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self); static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self); -static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix); +static int pyrna_py_to_prop( + PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix); static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item); #ifdef USE_MATHUTILS -#include "../mathutils/mathutils.h" /* so we can have mathutils callbacks */ - -static PyObject *pyrna_prop_array_subscript_slice( - BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, - Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length); -static short pyrna_rotation_euler_order_get( - PointerRNA *ptr, const short order_fallback, - PropertyRNA **r_prop_eul_order); +# include "../mathutils/mathutils.h" /* so we can have mathutils callbacks */ + +static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, + PointerRNA *ptr, + PropertyRNA *prop, + Py_ssize_t start, + Py_ssize_t stop, + Py_ssize_t length); +static short pyrna_rotation_euler_order_get(PointerRNA *ptr, + const short order_fallback, + PropertyRNA **r_prop_eul_order); /* bpyrna vector/euler/quat callbacks */ static unsigned char mathutils_rna_array_cb_index = -1; /* index for our callbacks */ /* subtype not used much yet */ -#define MATHUTILS_CB_SUBTYPE_EUL 0 -#define MATHUTILS_CB_SUBTYPE_VEC 1 -#define MATHUTILS_CB_SUBTYPE_QUAT 2 -#define MATHUTILS_CB_SUBTYPE_COLOR 3 +# define MATHUTILS_CB_SUBTYPE_EUL 0 +# define MATHUTILS_CB_SUBTYPE_VEC 1 +# define MATHUTILS_CB_SUBTYPE_QUAT 2 +# define MATHUTILS_CB_SUBTYPE_COLOR 3 static int mathutils_rna_generic_check(BaseMathObject *bmo) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - return self->prop ? 0 : -1; + return self->prop ? 0 : -1; } static int mathutils_rna_vector_get(BaseMathObject *bmo, int subtype) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - if (self->prop == NULL) { - return -1; - } + if (self->prop == NULL) { + return -1; + } - RNA_property_float_get_array(&self->ptr, self->prop, bmo->data); + RNA_property_float_get_array(&self->ptr, self->prop, bmo->data); - /* Euler order exception */ - if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { - EulerObject *eul = (EulerObject *)bmo; - PropertyRNA *prop_eul_order = NULL; - eul->order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); - } + /* Euler order exception */ + if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { + EulerObject *eul = (EulerObject *)bmo; + PropertyRNA *prop_eul_order = NULL; + eul->order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); + } - return 0; + return 0; } static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - float min, max; - - PYRNA_PROP_CHECK_INT(self); - - if (self->prop == NULL) { - return -1; - } - -#ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ - - if (!RNA_property_editable_flag(&self->ptr, self->prop)) { - PyErr_Format(PyExc_AttributeError, - "bpy_prop \"%.200s.%.200s\" is read-only", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop)); - return -1; - } - - RNA_property_float_range(&self->ptr, self->prop, &min, &max); - - if (min != -FLT_MAX || max != FLT_MAX) { - int i, len = RNA_property_array_length(&self->ptr, self->prop); - for (i = 0; i < len; i++) { - CLAMP(bmo->data[i], min, max); - } - } - - RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); - if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); - } - - /* Euler order exception */ - if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { - EulerObject *eul = (EulerObject *)bmo; - PropertyRNA *prop_eul_order = NULL; - short order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); - if (order != eul->order) { - RNA_property_enum_set(&self->ptr, prop_eul_order, eul->order); - if (RNA_property_update_check(prop_eul_order)) { - RNA_property_update(BPy_GetContext(), &self->ptr, prop_eul_order); - } - } - } - return 0; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + float min, max; + + PYRNA_PROP_CHECK_INT(self); + + if (self->prop == NULL) { + return -1; + } + +# ifdef USE_PEDANTIC_WRITE + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return -1; + } +# endif /* USE_PEDANTIC_WRITE */ + + if (!RNA_property_editable_flag(&self->ptr, self->prop)) { + PyErr_Format(PyExc_AttributeError, + "bpy_prop \"%.200s.%.200s\" is read-only", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); + return -1; + } + + RNA_property_float_range(&self->ptr, self->prop, &min, &max); + + if (min != -FLT_MAX || max != FLT_MAX) { + int i, len = RNA_property_array_length(&self->ptr, self->prop); + for (i = 0; i < len; i++) { + CLAMP(bmo->data[i], min, max); + } + } + + RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); + if (RNA_property_update_check(self->prop)) { + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + } + + /* Euler order exception */ + if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { + EulerObject *eul = (EulerObject *)bmo; + PropertyRNA *prop_eul_order = NULL; + short order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); + if (order != eul->order) { + RNA_property_enum_set(&self->ptr, prop_eul_order, eul->order); + if (RNA_property_update_check(prop_eul_order)) { + RNA_property_update(BPy_GetContext(), &self->ptr, prop_eul_order); + } + } + } + return 0; } static int mathutils_rna_vector_get_index(BaseMathObject *bmo, int UNUSED(subtype), int index) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - if (self->prop == NULL) { - return -1; - } + if (self->prop == NULL) { + return -1; + } - bmo->data[index] = RNA_property_float_get_index(&self->ptr, self->prop, index); - return 0; + bmo->data[index] = RNA_property_float_get_index(&self->ptr, self->prop, index); + return 0; } static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int UNUSED(subtype), int index) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - if (self->prop == NULL) { - return -1; - } + if (self->prop == NULL) { + return -1; + } -#ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ +# ifdef USE_PEDANTIC_WRITE + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return -1; + } +# endif /* USE_PEDANTIC_WRITE */ - if (!RNA_property_editable_flag(&self->ptr, self->prop)) { - PyErr_Format(PyExc_AttributeError, - "bpy_prop \"%.200s.%.200s\" is read-only", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop)); - return -1; - } + if (!RNA_property_editable_flag(&self->ptr, self->prop)) { + PyErr_Format(PyExc_AttributeError, + "bpy_prop \"%.200s.%.200s\" is read-only", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); + return -1; + } - RNA_property_float_clamp(&self->ptr, self->prop, &bmo->data[index]); - RNA_property_float_set_index(&self->ptr, self->prop, index, bmo->data[index]); + RNA_property_float_clamp(&self->ptr, self->prop, &bmo->data[index]); + RNA_property_float_set_index(&self->ptr, self->prop, index, bmo->data[index]); - if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); - } + if (RNA_property_update_check(self->prop)) { + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + } - return 0; + return 0; } static Mathutils_Callback mathutils_rna_array_cb = { - (BaseMathCheckFunc) mathutils_rna_generic_check, - (BaseMathGetFunc) mathutils_rna_vector_get, - (BaseMathSetFunc) mathutils_rna_vector_set, - (BaseMathGetIndexFunc) mathutils_rna_vector_get_index, - (BaseMathSetIndexFunc) mathutils_rna_vector_set_index, + (BaseMathCheckFunc)mathutils_rna_generic_check, + (BaseMathGetFunc)mathutils_rna_vector_get, + (BaseMathSetFunc)mathutils_rna_vector_set, + (BaseMathGetIndexFunc)mathutils_rna_vector_get_index, + (BaseMathSetIndexFunc)mathutils_rna_vector_set_index, }; - /* bpyrna matrix callbacks */ static unsigned char mathutils_rna_matrix_cb_index = -1; /* index for our callbacks */ static int mathutils_rna_matrix_get(BaseMathObject *bmo, int UNUSED(subtype)) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - if (self->prop == NULL) { - return -1; - } + if (self->prop == NULL) { + return -1; + } - RNA_property_float_get_array(&self->ptr, self->prop, bmo->data); - return 0; + RNA_property_float_get_array(&self->ptr, self->prop, bmo->data); + return 0; } static int mathutils_rna_matrix_set(BaseMathObject *bmo, int UNUSED(subtype)) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - if (self->prop == NULL) { - return -1; - } + if (self->prop == NULL) { + return -1; + } -#ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ +# ifdef USE_PEDANTIC_WRITE + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return -1; + } +# endif /* USE_PEDANTIC_WRITE */ - if (!RNA_property_editable_flag(&self->ptr, self->prop)) { - PyErr_Format(PyExc_AttributeError, - "bpy_prop \"%.200s.%.200s\" is read-only", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop)); - return -1; - } + if (!RNA_property_editable_flag(&self->ptr, self->prop)) { + PyErr_Format(PyExc_AttributeError, + "bpy_prop \"%.200s.%.200s\" is read-only", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); + return -1; + } - /* can ignore clamping here */ - RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); + /* can ignore clamping here */ + RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); - if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); - } - return 0; + if (RNA_property_update_check(self->prop)) { + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + } + return 0; } static Mathutils_Callback mathutils_rna_matrix_cb = { - mathutils_rna_generic_check, - mathutils_rna_matrix_get, - mathutils_rna_matrix_set, - NULL, - NULL, + mathutils_rna_generic_check, + mathutils_rna_matrix_get, + mathutils_rna_matrix_set, + NULL, + NULL, }; -static short pyrna_rotation_euler_order_get( - PointerRNA *ptr, const short order_fallback, - PropertyRNA **r_prop_eul_order) +static short pyrna_rotation_euler_order_get(PointerRNA *ptr, + const short order_fallback, + PropertyRNA **r_prop_eul_order) { - /* attempt to get order */ - if (*r_prop_eul_order == NULL) { - *r_prop_eul_order = RNA_struct_find_property(ptr, "rotation_mode"); - } + /* attempt to get order */ + if (*r_prop_eul_order == NULL) { + *r_prop_eul_order = RNA_struct_find_property(ptr, "rotation_mode"); + } - if (*r_prop_eul_order) { - short order = RNA_property_enum_get(ptr, *r_prop_eul_order); - /* could be quat or axisangle */ - if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) { - return order; - } - } + if (*r_prop_eul_order) { + short order = RNA_property_enum_get(ptr, *r_prop_eul_order); + /* could be quat or axisangle */ + if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) { + return order; + } + } - return order_fallback; + return order_fallback; } -#endif /* USE_MATHUTILS */ +#endif /* USE_MATHUTILS */ /* note that PROP_NONE is included as a vector subtype. this is because its handy to * have x/y access to fcurve keyframes and other fixed size float arrays of length 2-4. */ -#define PROP_ALL_VECTOR_SUBTYPES \ - PROP_COORDS: \ - case PROP_TRANSLATION: \ - case PROP_DIRECTION: \ - case PROP_VELOCITY: \ - case PROP_ACCELERATION: \ - case PROP_XYZ: \ - case PROP_XYZ_LENGTH \ - +#define PROP_ALL_VECTOR_SUBTYPES \ + PROP_COORDS: \ + case PROP_TRANSLATION: \ + case PROP_DIRECTION: \ + case PROP_VELOCITY: \ + case PROP_ACCELERATION: \ + case PROP_XYZ: \ + case PROP_XYZ_LENGTH PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) { - PyObject *ret = NULL; + PyObject *ret = NULL; #ifdef USE_MATHUTILS - int subtype, totdim; - int len; - const int flag = RNA_property_flag(prop); - const int type = RNA_property_type(prop); - const bool is_thick = (flag & PROP_THICK_WRAP) != 0; - - /* disallow dynamic sized arrays to be wrapped since the size could change - * to a size mathutils does not support */ - if (flag & PROP_DYNAMIC) { - return NULL; - } - - len = RNA_property_array_length(ptr, prop); - if (type == PROP_FLOAT) { - /* pass */ - } - else if (type == PROP_INT) { - if (is_thick) { - goto thick_wrap_slice; - } - else { - return NULL; - } - } - else { - return NULL; - } - - subtype = RNA_property_subtype(prop); - totdim = RNA_property_array_dimension(ptr, prop, NULL); - - if (totdim == 1 || (totdim == 2 && subtype == PROP_MATRIX)) { - if (!is_thick) { - /* owned by the mathutils PyObject */ - ret = pyrna_prop_CreatePyObject(ptr, prop); - } - - switch (subtype) { - case PROP_ALL_VECTOR_SUBTYPES: - if (len >= 2 && len <= 4) { - if (is_thick) { - ret = Vector_CreatePyObject(NULL, len, NULL); - RNA_property_float_get_array(ptr, prop, ((VectorObject *)ret)->vec); - } - else { - PyObject *vec_cb = Vector_CreatePyObject_cb( - ret, len, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_VEC); - Py_DECREF(ret); /* the vector owns now */ - ret = vec_cb; /* return the vector instead */ - } - } - break; - case PROP_MATRIX: - if (len == 16) { - if (is_thick) { - ret = Matrix_CreatePyObject(NULL, 4, 4, NULL); - RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix); - } - else { - PyObject *mat_cb = Matrix_CreatePyObject_cb( - ret, 4, 4, mathutils_rna_matrix_cb_index, 0); - Py_DECREF(ret); /* the matrix owns now */ - ret = mat_cb; /* return the matrix instead */ - } - } - else if (len == 9) { - if (is_thick) { - ret = Matrix_CreatePyObject(NULL, 3, 3, NULL); - RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix); - } - else { - PyObject *mat_cb = Matrix_CreatePyObject_cb( - ret, 3, 3, mathutils_rna_matrix_cb_index, 0); - Py_DECREF(ret); /* the matrix owns now */ - ret = mat_cb; /* return the matrix instead */ - } - } - break; - case PROP_EULER: - case PROP_QUATERNION: - if (len == 3) { /* euler */ - if (is_thick) { - /* attempt to get order, only needed for thick types since wrapped with update via callbacks */ - PropertyRNA *prop_eul_order = NULL; - short order = pyrna_rotation_euler_order_get(ptr, EULER_ORDER_XYZ, &prop_eul_order); - - ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA */ - RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul); - } - else { - /* order will be updated from callback on use */ - // TODO, get order from RNA - PyObject *eul_cb = Euler_CreatePyObject_cb( - ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); - Py_DECREF(ret); /* the euler owns now */ - ret = eul_cb; /* return the euler instead */ - } - } - else if (len == 4) { - if (is_thick) { - ret = Quaternion_CreatePyObject(NULL, NULL); - RNA_property_float_get_array(ptr, prop, ((QuaternionObject *)ret)->quat); - } - else { - PyObject *quat_cb = Quaternion_CreatePyObject_cb( - ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_QUAT); - Py_DECREF(ret); /* the quat owns now */ - ret = quat_cb; /* return the quat instead */ - } - } - break; - case PROP_COLOR: - case PROP_COLOR_GAMMA: - if (len == 3) { /* color */ - if (is_thick) { - ret = Color_CreatePyObject(NULL, NULL); - RNA_property_float_get_array(ptr, prop, ((ColorObject *)ret)->col); - } - else { - PyObject *col_cb = Color_CreatePyObject_cb( - ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_COLOR); - Py_DECREF(ret); /* the color owns now */ - ret = col_cb; /* return the color instead */ - } - } - break; - default: - break; - } - } - - if (ret == NULL) { - if (is_thick) { - /* this is an array we cant reference (since its not thin wrappable) - * and cannot be coerced into a mathutils type, so return as a list */ -thick_wrap_slice: - ret = pyrna_prop_array_subscript_slice(NULL, ptr, prop, 0, len, len); - } - else { - ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the mathutils PyObject */ - } - } + int subtype, totdim; + int len; + const int flag = RNA_property_flag(prop); + const int type = RNA_property_type(prop); + const bool is_thick = (flag & PROP_THICK_WRAP) != 0; + + /* disallow dynamic sized arrays to be wrapped since the size could change + * to a size mathutils does not support */ + if (flag & PROP_DYNAMIC) { + return NULL; + } + + len = RNA_property_array_length(ptr, prop); + if (type == PROP_FLOAT) { + /* pass */ + } + else if (type == PROP_INT) { + if (is_thick) { + goto thick_wrap_slice; + } + else { + return NULL; + } + } + else { + return NULL; + } + + subtype = RNA_property_subtype(prop); + totdim = RNA_property_array_dimension(ptr, prop, NULL); + + if (totdim == 1 || (totdim == 2 && subtype == PROP_MATRIX)) { + if (!is_thick) { + /* owned by the mathutils PyObject */ + ret = pyrna_prop_CreatePyObject(ptr, prop); + } + + switch (subtype) { + case PROP_ALL_VECTOR_SUBTYPES: + if (len >= 2 && len <= 4) { + if (is_thick) { + ret = Vector_CreatePyObject(NULL, len, NULL); + RNA_property_float_get_array(ptr, prop, ((VectorObject *)ret)->vec); + } + else { + PyObject *vec_cb = Vector_CreatePyObject_cb( + ret, len, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_VEC); + Py_DECREF(ret); /* the vector owns now */ + ret = vec_cb; /* return the vector instead */ + } + } + break; + case PROP_MATRIX: + if (len == 16) { + if (is_thick) { + ret = Matrix_CreatePyObject(NULL, 4, 4, NULL); + RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix); + } + else { + PyObject *mat_cb = Matrix_CreatePyObject_cb( + ret, 4, 4, mathutils_rna_matrix_cb_index, 0); + Py_DECREF(ret); /* the matrix owns now */ + ret = mat_cb; /* return the matrix instead */ + } + } + else if (len == 9) { + if (is_thick) { + ret = Matrix_CreatePyObject(NULL, 3, 3, NULL); + RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix); + } + else { + PyObject *mat_cb = Matrix_CreatePyObject_cb( + ret, 3, 3, mathutils_rna_matrix_cb_index, 0); + Py_DECREF(ret); /* the matrix owns now */ + ret = mat_cb; /* return the matrix instead */ + } + } + break; + case PROP_EULER: + case PROP_QUATERNION: + if (len == 3) { /* euler */ + if (is_thick) { + /* attempt to get order, only needed for thick types since wrapped with update via callbacks */ + PropertyRNA *prop_eul_order = NULL; + short order = pyrna_rotation_euler_order_get(ptr, EULER_ORDER_XYZ, &prop_eul_order); + + ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA */ + RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul); + } + else { + /* order will be updated from callback on use */ + // TODO, get order from RNA + PyObject *eul_cb = Euler_CreatePyObject_cb( + ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); + Py_DECREF(ret); /* the euler owns now */ + ret = eul_cb; /* return the euler instead */ + } + } + else if (len == 4) { + if (is_thick) { + ret = Quaternion_CreatePyObject(NULL, NULL); + RNA_property_float_get_array(ptr, prop, ((QuaternionObject *)ret)->quat); + } + else { + PyObject *quat_cb = Quaternion_CreatePyObject_cb( + ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_QUAT); + Py_DECREF(ret); /* the quat owns now */ + ret = quat_cb; /* return the quat instead */ + } + } + break; + case PROP_COLOR: + case PROP_COLOR_GAMMA: + if (len == 3) { /* color */ + if (is_thick) { + ret = Color_CreatePyObject(NULL, NULL); + RNA_property_float_get_array(ptr, prop, ((ColorObject *)ret)->col); + } + else { + PyObject *col_cb = Color_CreatePyObject_cb( + ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_COLOR); + Py_DECREF(ret); /* the color owns now */ + ret = col_cb; /* return the color instead */ + } + } + break; + default: + break; + } + } + + if (ret == NULL) { + if (is_thick) { + /* this is an array we cant reference (since its not thin wrappable) + * and cannot be coerced into a mathutils type, so return as a list */ + thick_wrap_slice: + ret = pyrna_prop_array_subscript_slice(NULL, ptr, prop, 0, len, len); + } + else { + ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the mathutils PyObject */ + } + } #else /* USE_MATHUTILS */ - (void)ptr; - (void)prop; -#endif /* USE_MATHUTILS */ + (void)ptr; + (void)prop; +#endif /* USE_MATHUTILS */ - return ret; + return ret; } /* same as RNA_enum_value_from_id but raises an exception */ -int pyrna_enum_value_from_id( - const EnumPropertyItem *item, const char *identifier, int *r_value, - const char *error_prefix) +int pyrna_enum_value_from_id(const EnumPropertyItem *item, + const char *identifier, + int *r_value, + const char *error_prefix) { - if (RNA_enum_value_from_id(item, identifier, r_value) == 0) { - const char *enum_str = BPy_enum_as_string(item); - PyErr_Format(PyExc_ValueError, - "%s: '%.200s' not found in (%s)", - error_prefix, identifier, enum_str); - MEM_freeN((void *)enum_str); - return -1; - } + if (RNA_enum_value_from_id(item, identifier, r_value) == 0) { + const char *enum_str = BPy_enum_as_string(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; + return 0; } /* note on __cmp__: @@ -797,325 +802,315 @@ int pyrna_enum_value_from_id( static int pyrna_struct_compare(BPy_StructRNA *a, BPy_StructRNA *b) { - return (((a->ptr.data == b->ptr.data) && - (a->ptr.type == b->ptr.type)) ? 0 : -1); + return (((a->ptr.data == b->ptr.data) && (a->ptr.type == b->ptr.type)) ? 0 : -1); } static int pyrna_prop_compare(BPy_PropertyRNA *a, BPy_PropertyRNA *b) { - return (((a->prop == b->prop) && - (a->ptr.data == b->ptr.data) && - (a->ptr.type == b->ptr.type)) ? 0 : -1); + return (((a->prop == b->prop) && (a->ptr.data == b->ptr.data) && (a->ptr.type == b->ptr.type)) ? + 0 : + -1); } static PyObject *pyrna_struct_richcmp(PyObject *a, PyObject *b, int op) { - PyObject *res; - int ok = -1; /* zero is true */ + PyObject *res; + int ok = -1; /* zero is true */ - if (BPy_StructRNA_Check(a) && BPy_StructRNA_Check(b)) { - ok = pyrna_struct_compare((BPy_StructRNA *)a, (BPy_StructRNA *)b); - } + if (BPy_StructRNA_Check(a) && BPy_StructRNA_Check(b)) { + ok = pyrna_struct_compare((BPy_StructRNA *)a, (BPy_StructRNA *)b); + } - switch (op) { - case Py_NE: - ok = !ok; - ATTR_FALLTHROUGH; - case Py_EQ: - res = ok ? Py_False : Py_True; - break; + switch (op) { + case Py_NE: + ok = !ok; + ATTR_FALLTHROUGH; + case Py_EQ: + res = ok ? Py_False : Py_True; + break; - case Py_LT: - case Py_LE: - case Py_GT: - case Py_GE: - res = Py_NotImplemented; - break; - default: - PyErr_BadArgument(); - return NULL; - } + case Py_LT: + case Py_LE: + case Py_GT: + case Py_GE: + res = Py_NotImplemented; + break; + default: + PyErr_BadArgument(); + return NULL; + } - return Py_INCREF_RET(res); + return Py_INCREF_RET(res); } static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op) { - PyObject *res; - int ok = -1; /* zero is true */ + PyObject *res; + int ok = -1; /* zero is true */ - if (BPy_PropertyRNA_Check(a) && BPy_PropertyRNA_Check(b)) { - ok = pyrna_prop_compare((BPy_PropertyRNA *)a, (BPy_PropertyRNA *)b); - } + if (BPy_PropertyRNA_Check(a) && BPy_PropertyRNA_Check(b)) { + ok = pyrna_prop_compare((BPy_PropertyRNA *)a, (BPy_PropertyRNA *)b); + } - switch (op) { - case Py_NE: - ok = !ok; - ATTR_FALLTHROUGH; - case Py_EQ: - res = ok ? Py_False : Py_True; - break; + switch (op) { + case Py_NE: + ok = !ok; + ATTR_FALLTHROUGH; + case Py_EQ: + res = ok ? Py_False : Py_True; + break; - case Py_LT: - case Py_LE: - case Py_GT: - case Py_GE: - res = Py_NotImplemented; - break; - default: - PyErr_BadArgument(); - return NULL; - } + case Py_LT: + case Py_LE: + case Py_GT: + case Py_GE: + res = Py_NotImplemented; + break; + default: + PyErr_BadArgument(); + return NULL; + } - return Py_INCREF_RET(res); + return Py_INCREF_RET(res); } /*----------------------repr--------------------------------------------*/ static PyObject *pyrna_struct_str(BPy_StructRNA *self) { - PyObject *ret; - const char *name; + PyObject *ret; + const char *name; - if (!PYRNA_STRUCT_IS_VALID(self)) { - return PyUnicode_FromFormat("<bpy_struct, %.200s invalid>", - Py_TYPE(self)->tp_name); - } + if (!PYRNA_STRUCT_IS_VALID(self)) { + return PyUnicode_FromFormat("<bpy_struct, %.200s invalid>", Py_TYPE(self)->tp_name); + } - /* print name if available */ - name = RNA_struct_name_get_alloc(&self->ptr, NULL, 0, NULL); - if (name) { - ret = PyUnicode_FromFormat("<bpy_struct, %.200s(\"%.200s\")>", - RNA_struct_identifier(self->ptr.type), - name); - MEM_freeN((void *)name); - return ret; - } + /* print name if available */ + name = RNA_struct_name_get_alloc(&self->ptr, NULL, 0, NULL); + if (name) { + ret = PyUnicode_FromFormat( + "<bpy_struct, %.200s(\"%.200s\")>", RNA_struct_identifier(self->ptr.type), name); + MEM_freeN((void *)name); + return ret; + } - return PyUnicode_FromFormat("<bpy_struct, %.200s at %p>", - RNA_struct_identifier(self->ptr.type), - self->ptr.data); + return PyUnicode_FromFormat( + "<bpy_struct, %.200s at %p>", RNA_struct_identifier(self->ptr.type), self->ptr.data); } static PyObject *pyrna_struct_repr(BPy_StructRNA *self) { - ID *id = self->ptr.id.data; - PyObject *tmp_str; - PyObject *ret; - - if (id == NULL || !PYRNA_STRUCT_IS_VALID(self)) { - /* fallback */ - return pyrna_struct_str(self); - } - - tmp_str = PyUnicode_FromString(id->name + 2); - - if (RNA_struct_is_ID(self->ptr.type)) { - ret = PyUnicode_FromFormat("bpy.data.%s[%R]", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str); - } - else { - const char *path; - path = RNA_path_from_ID_to_struct(&self->ptr); - if (path) { - if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */ - ret = PyUnicode_FromFormat("bpy.data...%s", - path); - } - else { - ret = PyUnicode_FromFormat("bpy.data.%s[%R].%s", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str, - path); - } - - MEM_freeN((void *)path); - } - else { /* cant find, print something sane */ - ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str, - RNA_struct_identifier(self->ptr.type)); - } - } - - Py_DECREF(tmp_str); - - return ret; + ID *id = self->ptr.id.data; + PyObject *tmp_str; + PyObject *ret; + + if (id == NULL || !PYRNA_STRUCT_IS_VALID(self)) { + /* fallback */ + return pyrna_struct_str(self); + } + + tmp_str = PyUnicode_FromString(id->name + 2); + + if (RNA_struct_is_ID(self->ptr.type)) { + ret = PyUnicode_FromFormat( + "bpy.data.%s[%R]", BKE_idcode_to_name_plural(GS(id->name)), tmp_str); + } + else { + const char *path; + path = RNA_path_from_ID_to_struct(&self->ptr); + if (path) { + if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */ + ret = PyUnicode_FromFormat("bpy.data...%s", path); + } + else { + ret = PyUnicode_FromFormat( + "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(id->name)), tmp_str, path); + } + + MEM_freeN((void *)path); + } + else { /* cant find, print something sane */ + ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str, + RNA_struct_identifier(self->ptr.type)); + } + } + + Py_DECREF(tmp_str); + + return ret; } static PyObject *pyrna_prop_str(BPy_PropertyRNA *self) { - PyObject *ret; - PointerRNA ptr; - const char *name; - const char *type_id = NULL; - char type_fmt[64] = ""; - int type; - - PYRNA_PROP_CHECK_OBJ(self); - - type = RNA_property_type(self->prop); - - if (RNA_enum_id_from_value(rna_enum_property_type_items, type, &type_id) == 0) { - PyErr_SetString(PyExc_RuntimeError, "could not use property type, internal error"); /* should never happen */ - return NULL; - } - else { - /* this should never fail */ - int len = -1; - char *c = type_fmt; - - while ((*c++ = tolower(*type_id++))) {} - - if (type == PROP_COLLECTION) { - len = pyrna_prop_collection_length(self); - } - else if (RNA_property_array_check(self->prop)) { - len = pyrna_prop_array_length((BPy_PropertyArrayRNA *)self); - } - - if (len != -1) { - sprintf(--c, "[%d]", len); - } - } - - /* if a pointer, try to print name of pointer target too */ - if (type == PROP_POINTER) { - ptr = RNA_property_pointer_get(&self->ptr, self->prop); - name = RNA_struct_name_get_alloc(&ptr, NULL, 0, NULL); - - if (name) { - ret = PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s(\"%.200s\")>", - type_fmt, - RNA_struct_identifier(self->ptr.type), - RNA_property_identifier(self->prop), - name); - MEM_freeN((void *)name); - return ret; - } - } - if (type == PROP_COLLECTION) { - PointerRNA r_ptr; - if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - return PyUnicode_FromFormat("<bpy_%.200s, %.200s>", - type_fmt, - RNA_struct_identifier(r_ptr.type)); - } - } - - return PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s>", - type_fmt, - RNA_struct_identifier(self->ptr.type), - RNA_property_identifier(self->prop)); -} - -static PyObject *pyrna_prop_repr_ex( - BPy_PropertyRNA *self, - const int index_dim, const int index) -{ - ID *id = self->ptr.id.data; - PyObject *tmp_str; - PyObject *ret; - const char *path; - - PYRNA_PROP_CHECK_OBJ(self); - - if (id == NULL) { - /* fallback */ - return pyrna_prop_str(self); - } - - tmp_str = PyUnicode_FromString(id->name + 2); - - path = RNA_path_from_ID_to_property_index(&self->ptr, self->prop, index_dim, index); - - if (path) { - const char *data_delim = (path[0] == '[') ? "" : "."; - if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */ - ret = PyUnicode_FromFormat("bpy.data...%s", - path); - } - else { - ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str, - data_delim, path); - } - - MEM_freeN((void *)path); - } - else { /* cant find, print something sane */ - ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str, - RNA_property_identifier(self->prop)); - } - - Py_DECREF(tmp_str); - - return ret; + PyObject *ret; + PointerRNA ptr; + const char *name; + const char *type_id = NULL; + char type_fmt[64] = ""; + int type; + + PYRNA_PROP_CHECK_OBJ(self); + + type = RNA_property_type(self->prop); + + if (RNA_enum_id_from_value(rna_enum_property_type_items, type, &type_id) == 0) { + PyErr_SetString(PyExc_RuntimeError, + "could not use property type, internal error"); /* should never happen */ + return NULL; + } + else { + /* this should never fail */ + int len = -1; + char *c = type_fmt; + + while ((*c++ = tolower(*type_id++))) { + } + + if (type == PROP_COLLECTION) { + len = pyrna_prop_collection_length(self); + } + else if (RNA_property_array_check(self->prop)) { + len = pyrna_prop_array_length((BPy_PropertyArrayRNA *)self); + } + + if (len != -1) { + sprintf(--c, "[%d]", len); + } + } + + /* if a pointer, try to print name of pointer target too */ + if (type == PROP_POINTER) { + ptr = RNA_property_pointer_get(&self->ptr, self->prop); + name = RNA_struct_name_get_alloc(&ptr, NULL, 0, NULL); + + if (name) { + ret = PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s(\"%.200s\")>", + type_fmt, + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop), + name); + MEM_freeN((void *)name); + return ret; + } + } + if (type == PROP_COLLECTION) { + PointerRNA r_ptr; + if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + return PyUnicode_FromFormat( + "<bpy_%.200s, %.200s>", type_fmt, RNA_struct_identifier(r_ptr.type)); + } + } + + return PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s>", + type_fmt, + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); +} + +static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, const int index) +{ + ID *id = self->ptr.id.data; + PyObject *tmp_str; + PyObject *ret; + const char *path; + + PYRNA_PROP_CHECK_OBJ(self); + + if (id == NULL) { + /* fallback */ + return pyrna_prop_str(self); + } + + tmp_str = PyUnicode_FromString(id->name + 2); + + path = RNA_path_from_ID_to_property_index(&self->ptr, self->prop, index_dim, index); + + if (path) { + const char *data_delim = (path[0] == '[') ? "" : "."; + if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */ + ret = PyUnicode_FromFormat("bpy.data...%s", path); + } + else { + ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str, + data_delim, + path); + } + + MEM_freeN((void *)path); + } + else { /* cant find, print something sane */ + ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str, + RNA_property_identifier(self->prop)); + } + + Py_DECREF(tmp_str); + + return ret; } static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self) { - return pyrna_prop_repr_ex(self, 0, -1); + return pyrna_prop_repr_ex(self, 0, -1); } static PyObject *pyrna_prop_array_repr(BPy_PropertyArrayRNA *self) { - return pyrna_prop_repr_ex((BPy_PropertyRNA *)self, self->arraydim, self->arrayoffset); + return pyrna_prop_repr_ex((BPy_PropertyRNA *)self, self->arraydim, self->arrayoffset); } static PyObject *pyrna_func_repr(BPy_FunctionRNA *self) { - return PyUnicode_FromFormat("<%.200s %.200s.%.200s()>", - Py_TYPE(self)->tp_name, - RNA_struct_identifier(self->ptr.type), - RNA_function_identifier(self->func)); + return PyUnicode_FromFormat("<%.200s %.200s.%.200s()>", + Py_TYPE(self)->tp_name, + RNA_struct_identifier(self->ptr.type), + RNA_function_identifier(self->func)); } - static Py_hash_t pyrna_struct_hash(BPy_StructRNA *self) { - return _Py_HashPointer(self->ptr.data); + return _Py_HashPointer(self->ptr.data); } /* from python's meth_hash v3.1.2 */ static long pyrna_prop_hash(BPy_PropertyRNA *self) { - long x, y; - if (self->ptr.data == NULL) { - x = 0; - } - else { - x = _Py_HashPointer(self->ptr.data); - if (x == -1) { - return -1; - } - } - y = _Py_HashPointer((void *)(self->prop)); - if (y == -1) { - return -1; - } - x ^= y; - if (x == -1) { - x = -2; - } - return x; + long x, y; + if (self->ptr.data == NULL) { + x = 0; + } + else { + x = _Py_HashPointer(self->ptr.data); + if (x == -1) { + return -1; + } + } + y = _Py_HashPointer((void *)(self->prop)); + if (y == -1) { + return -1; + } + x ^= y; + if (x == -1) { + x = -2; + } + return x; } #ifdef USE_PYRNA_STRUCT_REFERENCE static int pyrna_struct_traverse(BPy_StructRNA *self, visitproc visit, void *arg) { - Py_VISIT(self->reference); - return 0; + Py_VISIT(self->reference); + return 0; } static int pyrna_struct_clear(BPy_StructRNA *self) { - Py_CLEAR(self->reference); - return 0; + Py_CLEAR(self->reference); + return 0; } #endif /* !USE_PYRNA_STRUCT_REFERENCE */ @@ -1123,44 +1118,44 @@ static int pyrna_struct_clear(BPy_StructRNA *self) static void pyrna_struct_dealloc(BPy_StructRNA *self) { #ifdef PYRNA_FREE_SUPPORT - if (self->freeptr && self->ptr.data) { - IDP_FreeProperty(self->ptr.data); - MEM_freeN(self->ptr.data); - self->ptr.data = NULL; - } + if (self->freeptr && self->ptr.data) { + IDP_FreeProperty(self->ptr.data); + MEM_freeN(self->ptr.data); + self->ptr.data = NULL; + } #endif /* PYRNA_FREE_SUPPORT */ #ifdef USE_WEAKREFS - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *)self); - } + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject *)self); + } #endif #ifdef USE_PYRNA_STRUCT_REFERENCE - if (self->reference) { - PyObject_GC_UnTrack(self); - pyrna_struct_clear(self); - } + if (self->reference) { + PyObject_GC_UnTrack(self); + pyrna_struct_clear(self); + } #endif /* !USE_PYRNA_STRUCT_REFERENCE */ - /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ - Py_TYPE(self)->tp_free(self); + /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ + Py_TYPE(self)->tp_free(self); } #ifdef USE_PYRNA_STRUCT_REFERENCE static void pyrna_struct_reference_set(BPy_StructRNA *self, PyObject *reference) { - if (self->reference) { -// PyObject_GC_UnTrack(self); /* INITIALIZED TRACKED ? */ - pyrna_struct_clear(self); - } - /* reference is now NULL */ + if (self->reference) { + // PyObject_GC_UnTrack(self); /* INITIALIZED TRACKED ? */ + pyrna_struct_clear(self); + } + /* reference is now NULL */ - if (reference) { - self->reference = reference; - Py_INCREF(reference); -// PyObject_GC_Track(self); /* INITIALIZED TRACKED ? */ - } + if (reference) { + self->reference = reference; + Py_INCREF(reference); + // PyObject_GC_Track(self); /* INITIALIZED TRACKED ? */ + } } #endif /* !USE_PYRNA_STRUCT_REFERENCE */ @@ -1168,71 +1163,72 @@ static void pyrna_struct_reference_set(BPy_StructRNA *self, PyObject *reference) static void pyrna_prop_dealloc(BPy_PropertyRNA *self) { #ifdef USE_WEAKREFS - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *)self); - } + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject *)self); + } #endif - /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ - Py_TYPE(self)->tp_free(self); + /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ + Py_TYPE(self)->tp_free(self); } static void pyrna_prop_array_dealloc(BPy_PropertyRNA *self) { #ifdef USE_WEAKREFS - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *)self); - } + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject *)self); + } #endif - /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ - Py_TYPE(self)->tp_free(self); + /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ + Py_TYPE(self)->tp_free(self); } static const char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) { - const EnumPropertyItem *item; - const char *result; - bool free = false; + const EnumPropertyItem *item; + const char *result; + bool free = false; - RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); - if (item) { - result = BPy_enum_as_string(item); - } - else { - result = ""; - } + RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); + if (item) { + result = BPy_enum_as_string(item); + } + else { + result = ""; + } - if (free) { - MEM_freeN((void *)item); - } + if (free) { + MEM_freeN((void *)item); + } - return result; + return result; } - static int pyrna_string_to_enum( - PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *r_value, - const char *error_prefix) -{ - const char *param = _PyUnicode_AsString(item); - - if (param == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s expected a string enum, not %.200s", - error_prefix, Py_TYPE(item)->tp_name); - return -1; - } - else { - if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, r_value)) { - const char *enum_str = pyrna_enum_as_string(ptr, prop); - PyErr_Format(PyExc_TypeError, - "%.200s enum \"%.200s\" not found in (%s)", - error_prefix, param, enum_str); - MEM_freeN((void *)enum_str); - return -1; - } - } - - return 0; + PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *r_value, const char *error_prefix) +{ + const char *param = _PyUnicode_AsString(item); + + if (param == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s expected a string enum, not %.200s", + error_prefix, + Py_TYPE(item)->tp_name); + return -1; + } + else { + if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, r_value)) { + const char *enum_str = pyrna_enum_as_string(ptr, prop); + PyErr_Format(PyExc_TypeError, + "%.200s enum \"%.200s\" not found in (%s)", + error_prefix, + param, + enum_str); + MEM_freeN((void *)enum_str); + return -1; + } + } + + return 0; } /** @@ -1243,1112 +1239,1150 @@ static int pyrna_string_to_enum( * \param type_convert_sign: Maps signed to unsigned range, * needed when we want to use the full range of a signed short/char. */ -BLI_bitmap *pyrna_set_to_enum_bitmap( - const EnumPropertyItem *items, PyObject *value, - int type_size, bool type_convert_sign, - int bitmap_size, - const char *error_prefix) -{ - /* set looping */ - Py_ssize_t pos = 0; - Py_ssize_t hash = 0; - PyObject *key; - - BLI_bitmap *bitmap = BLI_BITMAP_NEW(bitmap_size, __func__); - - while (_PySet_NextEntry(value, &pos, &key, &hash)) { - const char *param = _PyUnicode_AsString(key); - if (param == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s expected a string, not %.200s", - error_prefix, Py_TYPE(key)->tp_name); - goto error; - } - - int ret; - if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) { - goto error; - } - - int index = ret; - - if (type_convert_sign) { - if (type_size == 2) { - union { signed short as_signed; unsigned short as_unsigned; } ret_convert; - ret_convert.as_signed = (signed short)ret; - index = (int)ret_convert.as_unsigned; - } - else if (type_size == 1) { - union { signed char as_signed; unsigned char as_unsigned; } ret_convert; - ret_convert.as_signed = (signed char)ret; - index = (int)ret_convert.as_unsigned; - } - else { - BLI_assert(0); - } - } - BLI_assert(index < bitmap_size); - BLI_BITMAP_ENABLE(bitmap, index); - } - - return bitmap; +BLI_bitmap *pyrna_set_to_enum_bitmap(const EnumPropertyItem *items, + PyObject *value, + int type_size, + bool type_convert_sign, + int bitmap_size, + const char *error_prefix) +{ + /* set looping */ + Py_ssize_t pos = 0; + Py_ssize_t hash = 0; + PyObject *key; + + BLI_bitmap *bitmap = BLI_BITMAP_NEW(bitmap_size, __func__); + + while (_PySet_NextEntry(value, &pos, &key, &hash)) { + const char *param = _PyUnicode_AsString(key); + if (param == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s expected a string, not %.200s", + error_prefix, + Py_TYPE(key)->tp_name); + goto error; + } + + int ret; + if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) { + goto error; + } + + int index = ret; + + if (type_convert_sign) { + if (type_size == 2) { + union { + signed short as_signed; + unsigned short as_unsigned; + } ret_convert; + ret_convert.as_signed = (signed short)ret; + index = (int)ret_convert.as_unsigned; + } + else if (type_size == 1) { + union { + signed char as_signed; + unsigned char as_unsigned; + } ret_convert; + ret_convert.as_signed = (signed char)ret; + index = (int)ret_convert.as_unsigned; + } + else { + BLI_assert(0); + } + } + BLI_assert(index < bitmap_size); + BLI_BITMAP_ENABLE(bitmap, index); + } + + return bitmap; error: - MEM_freeN(bitmap); - return NULL; + MEM_freeN(bitmap); + return NULL; } /* 'value' _must_ be a set type, error check before calling */ -int pyrna_set_to_enum_bitfield( - const EnumPropertyItem *items, PyObject *value, int *r_value, - const char *error_prefix) +int pyrna_set_to_enum_bitfield(const EnumPropertyItem *items, + PyObject *value, + int *r_value, + const char *error_prefix) { - /* set of enum items, concatenate all values with OR */ - int ret, flag = 0; + /* 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; + /* set looping */ + Py_ssize_t pos = 0; + Py_ssize_t hash = 0; + PyObject *key; - *r_value = 0; + *r_value = 0; - while (_PySet_NextEntry(value, &pos, &key, &hash)) { - const char *param = _PyUnicode_AsString(key); + while (_PySet_NextEntry(value, &pos, &key, &hash)) { + const char *param = _PyUnicode_AsString(key); - if (param == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s expected a string, not %.200s", - error_prefix, Py_TYPE(key)->tp_name); - return -1; - } + if (param == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s expected a string, not %.200s", + error_prefix, + Py_TYPE(key)->tp_name); + return -1; + } - if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) { - return -1; - } + if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) { + return -1; + } - flag |= ret; - } + flag |= ret; + } - *r_value = flag; - return 0; + *r_value = flag; + return 0; } static int pyrna_prop_to_enum_bitfield( - PointerRNA *ptr, PropertyRNA *prop, PyObject *value, int *r_value, - const char *error_prefix) -{ - const EnumPropertyItem *item; - int ret; - bool free = false; - - *r_value = 0; - - if (!PyAnySet_Check(value)) { - PyErr_Format(PyExc_TypeError, - "%.200s, %.200s.%.200s expected a set, not a %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - return -1; - } - - RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); - - if (item) { - ret = pyrna_set_to_enum_bitfield(item, value, r_value, error_prefix); - } - else { - if (PySet_GET_SIZE(value)) { - PyErr_Format(PyExc_TypeError, - "%.200s: empty enum \"%.200s\" could not have any values assigned", - error_prefix, RNA_property_identifier(prop)); - ret = -1; - } - else { - ret = 0; - } - } - - if (free) { - MEM_freeN((void *)item); - } - - return ret; + PointerRNA *ptr, PropertyRNA *prop, PyObject *value, int *r_value, const char *error_prefix) +{ + const EnumPropertyItem *item; + int ret; + bool free = false; + + *r_value = 0; + + if (!PyAnySet_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s, %.200s.%.200s expected a set, not a %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + return -1; + } + + RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); + + if (item) { + ret = pyrna_set_to_enum_bitfield(item, value, r_value, error_prefix); + } + else { + if (PySet_GET_SIZE(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: empty enum \"%.200s\" could not have any values assigned", + error_prefix, + RNA_property_identifier(prop)); + ret = -1; + } + else { + ret = 0; + } + } + + if (free) { + MEM_freeN((void *)item); + } + + return ret; } PyObject *pyrna_enum_bitfield_to_py(const EnumPropertyItem *items, int value) { - PyObject *ret = PySet_New(NULL); - const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1]; + PyObject *ret = PySet_New(NULL); + const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1]; - if (RNA_enum_bitflag_identifiers(items, value, identifier)) { - PyObject *item; - int index; - for (index = 0; identifier[index]; index++) { - item = PyUnicode_FromString(identifier[index]); - PySet_Add(ret, item); - Py_DECREF(item); - } - } + if (RNA_enum_bitflag_identifiers(items, value, identifier)) { + PyObject *item; + int index; + for (index = 0; identifier[index]; index++) { + item = PyUnicode_FromString(identifier[index]); + PySet_Add(ret, item); + Py_DECREF(item); + } + } - return ret; + return ret; } static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val) { - PyObject *item, *ret = NULL; - - if (RNA_property_flag(prop) & PROP_ENUM_FLAG) { - const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1]; - - ret = PySet_New(NULL); - - if (RNA_property_enum_bitflag_identifiers(BPy_GetContext(), ptr, prop, val, identifier)) { - int index; - - for (index = 0; identifier[index]; index++) { - item = PyUnicode_FromString(identifier[index]); - PySet_Add(ret, item); - Py_DECREF(item); - } - - } - } - else { - const char *identifier; - if (RNA_property_enum_identifier(BPy_GetContext(), ptr, prop, val, &identifier)) { - ret = PyUnicode_FromString(identifier); - } - else { - /* Static, no need to free. */ - const EnumPropertyItem *enum_item; - bool free_dummy; - RNA_property_enum_items_ex(NULL, ptr, prop, true, &enum_item, NULL, &free_dummy); - BLI_assert(!free_dummy); - - /* Do not print warning in case of DummyRNA_NULL_items, this one will never match any value... */ - if (enum_item != DummyRNA_NULL_items) { - const char *ptr_name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL); - - /* prefer not fail silently in case of api errors, maybe disable it later */ - CLOG_WARN(BPY_LOG_RNA, - "current value '%d' " - "matches no enum in '%s', '%s', '%s'", - val, RNA_struct_identifier(ptr->type), - ptr_name, RNA_property_identifier(prop)); - -#if 0 /* gives python decoding errors while generating docs :( */ - char error_str[256]; - BLI_snprintf(error_str, sizeof(error_str), - "RNA Warning: Current value \"%d\" " - "matches no enum in '%s', '%s', '%s'", - val, RNA_struct_identifier(ptr->type), - ptr_name, RNA_property_identifier(prop)); - - PyErr_Warn(PyExc_RuntimeWarning, error_str); + PyObject *item, *ret = NULL; + + if (RNA_property_flag(prop) & PROP_ENUM_FLAG) { + const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1]; + + ret = PySet_New(NULL); + + if (RNA_property_enum_bitflag_identifiers(BPy_GetContext(), ptr, prop, val, identifier)) { + int index; + + for (index = 0; identifier[index]; index++) { + item = PyUnicode_FromString(identifier[index]); + PySet_Add(ret, item); + Py_DECREF(item); + } + } + } + else { + const char *identifier; + if (RNA_property_enum_identifier(BPy_GetContext(), ptr, prop, val, &identifier)) { + ret = PyUnicode_FromString(identifier); + } + else { + /* Static, no need to free. */ + const EnumPropertyItem *enum_item; + bool free_dummy; + RNA_property_enum_items_ex(NULL, ptr, prop, true, &enum_item, NULL, &free_dummy); + BLI_assert(!free_dummy); + + /* Do not print warning in case of DummyRNA_NULL_items, this one will never match any value... */ + if (enum_item != DummyRNA_NULL_items) { + const char *ptr_name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL); + + /* prefer not fail silently in case of api errors, maybe disable it later */ + CLOG_WARN(BPY_LOG_RNA, + "current value '%d' " + "matches no enum in '%s', '%s', '%s'", + val, + RNA_struct_identifier(ptr->type), + ptr_name, + RNA_property_identifier(prop)); + +#if 0 /* gives python decoding errors while generating docs :( */ + char error_str[256]; + BLI_snprintf(error_str, sizeof(error_str), + "RNA Warning: Current value \"%d\" " + "matches no enum in '%s', '%s', '%s'", + val, RNA_struct_identifier(ptr->type), + ptr_name, RNA_property_identifier(prop)); + + PyErr_Warn(PyExc_RuntimeWarning, error_str); #endif - if (ptr_name) { - MEM_freeN((void *)ptr_name); - } - } + if (ptr_name) { + MEM_freeN((void *)ptr_name); + } + } - ret = PyUnicode_FromString(""); + ret = PyUnicode_FromString(""); #if 0 - PyErr_Format(PyExc_AttributeError, - "RNA Error: Current value \"%d\" matches no enum", val); - ret = NULL; + PyErr_Format(PyExc_AttributeError, + "RNA Error: Current value \"%d\" matches no enum", val); + ret = NULL; #endif - } - } + } + } - return ret; + return ret; } PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) { - PyObject *ret; - const int type = RNA_property_type(prop); - - if (RNA_property_array_check(prop)) { - return pyrna_py_from_array(ptr, prop); - } - - /* see if we can coerce into a python type - PropertyType */ - switch (type) { - case PROP_BOOLEAN: - ret = PyBool_FromLong(RNA_property_boolean_get(ptr, prop)); - break; - case PROP_INT: - ret = PyLong_FromLong(RNA_property_int_get(ptr, prop)); - break; - case PROP_FLOAT: - ret = PyFloat_FromDouble(RNA_property_float_get(ptr, prop)); - break; - case PROP_STRING: - { - const int subtype = RNA_property_subtype(prop); - const char *buf; - int buf_len; - char buf_fixed[32]; - - buf = RNA_property_string_get_alloc(ptr, prop, buf_fixed, sizeof(buf_fixed), &buf_len); + PyObject *ret; + const int type = RNA_property_type(prop); + + if (RNA_property_array_check(prop)) { + return pyrna_py_from_array(ptr, prop); + } + + /* see if we can coerce into a python type - PropertyType */ + switch (type) { + case PROP_BOOLEAN: + ret = PyBool_FromLong(RNA_property_boolean_get(ptr, prop)); + break; + case PROP_INT: + ret = PyLong_FromLong(RNA_property_int_get(ptr, prop)); + break; + case PROP_FLOAT: + ret = PyFloat_FromDouble(RNA_property_float_get(ptr, prop)); + break; + case PROP_STRING: { + const int subtype = RNA_property_subtype(prop); + const char *buf; + int buf_len; + char buf_fixed[32]; + + buf = RNA_property_string_get_alloc(ptr, prop, buf_fixed, sizeof(buf_fixed), &buf_len); #ifdef USE_STRING_COERCE - /* only file paths get special treatment, they may contain non utf-8 chars */ - if (subtype == PROP_BYTESTRING) { - ret = PyBytes_FromStringAndSize(buf, buf_len); - } - else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - ret = PyC_UnicodeFromByteAndSize(buf, buf_len); - } - else { - ret = PyUnicode_FromStringAndSize(buf, buf_len); - } + /* only file paths get special treatment, they may contain non utf-8 chars */ + if (subtype == PROP_BYTESTRING) { + ret = PyBytes_FromStringAndSize(buf, buf_len); + } + else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { + ret = PyC_UnicodeFromByteAndSize(buf, buf_len); + } + else { + ret = PyUnicode_FromStringAndSize(buf, buf_len); + } #else /* USE_STRING_COERCE */ - if (subtype == PROP_BYTESTRING) { - ret = PyBytes_FromStringAndSize(buf, buf_len); - } - else { - ret = PyUnicode_FromStringAndSize(buf, buf_len); - } -#endif /* USE_STRING_COERCE */ - if (buf_fixed != buf) { - MEM_freeN((void *)buf); - } - break; - } - case PROP_ENUM: - { - ret = pyrna_enum_to_py(ptr, prop, RNA_property_enum_get(ptr, prop)); - break; - } - case PROP_POINTER: - { - PointerRNA newptr; - newptr = RNA_property_pointer_get(ptr, prop); - if (newptr.data) { - ret = pyrna_struct_CreatePyObject(&newptr); - } - else { - ret = Py_None; - Py_INCREF(ret); - } - break; - } - case PROP_COLLECTION: - ret = pyrna_prop_CreatePyObject(ptr, prop); - break; - default: - PyErr_Format(PyExc_TypeError, - "bpy_struct internal error: unknown type '%d' (pyrna_prop_to_py)", type); - ret = NULL; - break; - } - - return ret; + if (subtype == PROP_BYTESTRING) { + ret = PyBytes_FromStringAndSize(buf, buf_len); + } + else { + ret = PyUnicode_FromStringAndSize(buf, buf_len); + } +#endif /* USE_STRING_COERCE */ + if (buf_fixed != buf) { + MEM_freeN((void *)buf); + } + break; + } + case PROP_ENUM: { + ret = pyrna_enum_to_py(ptr, prop, RNA_property_enum_get(ptr, prop)); + break; + } + case PROP_POINTER: { + PointerRNA newptr; + newptr = RNA_property_pointer_get(ptr, prop); + if (newptr.data) { + ret = pyrna_struct_CreatePyObject(&newptr); + } + else { + ret = Py_None; + Py_INCREF(ret); + } + break; + } + case PROP_COLLECTION: + ret = pyrna_prop_CreatePyObject(ptr, prop); + break; + default: + PyErr_Format(PyExc_TypeError, + "bpy_struct internal error: unknown type '%d' (pyrna_prop_to_py)", + type); + ret = NULL; + break; + } + + return ret; } /** * This function is used by operators and converting dicts into collections. * Its takes keyword args and fills them with property values */ -int pyrna_pydict_to_props( - PointerRNA *ptr, PyObject *kw, const bool all_args, - const char *error_prefix) -{ - int error_val = 0; - int totkw; - const char *arg_name = NULL; - PyObject *item; - - totkw = kw ? PyDict_Size(kw) : 0; - - RNA_STRUCT_BEGIN (ptr, prop) - { - arg_name = RNA_property_identifier(prop); - - if (STREQ(arg_name, "rna_type")) { - continue; - } - - if (kw == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s: no keywords, expected \"%.200s\"", - error_prefix, arg_name ? arg_name : "<UNKNOWN>"); - error_val = -1; - break; - } - - item = PyDict_GetItemString(kw, arg_name); /* wont set an error */ - - if (item == NULL) { - if (all_args) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" missing", - error_prefix, arg_name ? arg_name : "<UNKNOWN>"); - error_val = -1; /* pyrna_py_to_prop sets the error */ - break; - } - } - else { - if (pyrna_py_to_prop(ptr, prop, NULL, item, error_prefix)) { - error_val = -1; - break; - } - totkw--; - } - } - RNA_STRUCT_END; - - if (error_val == 0 && totkw > 0) { /* some keywords were given that were not used :/ */ - PyObject *key, *value; - Py_ssize_t pos = 0; - - while (PyDict_Next(kw, &pos, &key, &value)) { - arg_name = _PyUnicode_AsString(key); - if (RNA_struct_find_property(ptr, arg_name) == NULL) { - break; - } - arg_name = NULL; - } - - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" unrecognized", - error_prefix, arg_name ? arg_name : "<UNKNOWN>"); - error_val = -1; - } - - return error_val; +int pyrna_pydict_to_props(PointerRNA *ptr, + PyObject *kw, + const bool all_args, + const char *error_prefix) +{ + int error_val = 0; + int totkw; + const char *arg_name = NULL; + PyObject *item; + + totkw = kw ? PyDict_Size(kw) : 0; + + RNA_STRUCT_BEGIN (ptr, prop) { + arg_name = RNA_property_identifier(prop); + + if (STREQ(arg_name, "rna_type")) { + continue; + } + + if (kw == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s: no keywords, expected \"%.200s\"", + error_prefix, + arg_name ? arg_name : "<UNKNOWN>"); + error_val = -1; + break; + } + + item = PyDict_GetItemString(kw, arg_name); /* wont set an error */ + + if (item == NULL) { + if (all_args) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" missing", + error_prefix, + arg_name ? arg_name : "<UNKNOWN>"); + error_val = -1; /* pyrna_py_to_prop sets the error */ + break; + } + } + else { + if (pyrna_py_to_prop(ptr, prop, NULL, item, error_prefix)) { + error_val = -1; + break; + } + totkw--; + } + } + RNA_STRUCT_END; + + if (error_val == 0 && totkw > 0) { /* some keywords were given that were not used :/ */ + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(kw, &pos, &key, &value)) { + arg_name = _PyUnicode_AsString(key); + if (RNA_struct_find_property(ptr, arg_name) == NULL) { + break; + } + arg_name = NULL; + } + + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" unrecognized", + error_prefix, + arg_name ? arg_name : "<UNKNOWN>"); + error_val = -1; + } + + return error_val; } - static PyObject *pyrna_func_to_py(const PointerRNA *ptr, FunctionRNA *func) { - BPy_FunctionRNA *pyfunc = (BPy_FunctionRNA *) PyObject_NEW(BPy_FunctionRNA, &pyrna_func_Type); - pyfunc->ptr = *ptr; - pyfunc->func = func; - return (PyObject *)pyfunc; + BPy_FunctionRNA *pyfunc = (BPy_FunctionRNA *)PyObject_NEW(BPy_FunctionRNA, &pyrna_func_Type); + pyfunc->ptr = *ptr; + pyfunc->func = func; + return (PyObject *)pyfunc; } - static int pyrna_py_to_prop( - PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, - const char *error_prefix) -{ - /* XXX hard limits should be checked here */ - const int type = RNA_property_type(prop); - - - if (RNA_property_array_check(prop)) { - /* done getting the length */ - if (pyrna_py_to_array(ptr, prop, data, value, error_prefix) == -1) { - return -1; - } - } - else { - /* Normal Property (not an array) */ - - /* see if we can coerce into a python type - PropertyType */ - switch (type) { - case PROP_BOOLEAN: - { - int param; - /* prefer not to have an exception here - * however so many poll functions return None or a valid Object. - * its a hassle to convert these into a bool before returning, */ - if (RNA_parameter_flag(prop) & PARM_OUTPUT) { - param = PyObject_IsTrue(value); - } - else { - param = PyC_Long_AsI32(value); - - if (UNLIKELY(param & ~1)) { /* only accept 0/1 */ - param = -1; /* error out below */ - } - } - - if (param == -1) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected True/False or 0/1, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - return -1; - } - else { - if (data) { - *((bool *)data) = param; - } - else { - RNA_property_boolean_set(ptr, prop, param); - } - } - break; - } - case PROP_INT: - { - int overflow; - long param = PyLong_AsLongAndOverflow(value, &overflow); - if (overflow || (param > INT_MAX) || (param < INT_MIN)) { - PyErr_Format(PyExc_ValueError, - "%.200s %.200s.%.200s value not in 'int' range " - "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - return -1; - } - else if (param == -1 && PyErr_Occurred()) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected an int type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - return -1; - } - else { - int param_i = (int)param; - if (data) { - RNA_property_int_clamp(ptr, prop, ¶m_i); - *((int *)data) = param_i; - } - else { - RNA_property_int_set(ptr, prop, param_i); - } - } - break; - } - case PROP_FLOAT: - { - float param = PyFloat_AsDouble(value); - if (PyErr_Occurred()) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a float type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - return -1; - } - else { - if (data) { - RNA_property_float_clamp(ptr, prop, (float *)¶m); - *((float *)data) = param; - } - else { - RNA_property_float_set(ptr, prop, param); - } - } - break; - } - case PROP_STRING: - { - const int subtype = RNA_property_subtype(prop); - const char *param; - - if (value == Py_None) { - if ((RNA_property_flag(prop) & PROP_NEVER_NULL) == 0) { - if (data) { - *((char **)data) = (char *)NULL; - } - else { - RNA_property_string_set(ptr, prop, NULL); - } - } - else { - PyC_Err_Format_Prefix( - PyExc_TypeError, - "%.200s %.200s.%.200s doesn't support None from string types", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - return -1; - } - } - else if (subtype == PROP_BYTESTRING) { - - /* Byte String */ - - param = PyBytes_AsString(value); - - if (param == NULL) { - if (PyBytes_Check(value)) { - /* there was an error assigning a string type, - * rather than setting a new error, prefix the existing one - */ - PyC_Err_Format_Prefix(PyExc_TypeError, - "%.200s %.200s.%.200s error assigning bytes", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a bytes type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - } - - return -1; - } - else { - if (data) { - *((char **)data) = (char *)param; - } - else { - RNA_property_string_set_bytes(ptr, prop, param, PyBytes_Size(value)); - } - } - } - else { - /* Unicode String */ + PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix) +{ + /* XXX hard limits should be checked here */ + const int type = RNA_property_type(prop); + + if (RNA_property_array_check(prop)) { + /* done getting the length */ + if (pyrna_py_to_array(ptr, prop, data, value, error_prefix) == -1) { + return -1; + } + } + else { + /* Normal Property (not an array) */ + + /* see if we can coerce into a python type - PropertyType */ + switch (type) { + case PROP_BOOLEAN: { + int param; + /* prefer not to have an exception here + * however so many poll functions return None or a valid Object. + * its a hassle to convert these into a bool before returning, */ + if (RNA_parameter_flag(prop) & PARM_OUTPUT) { + param = PyObject_IsTrue(value); + } + else { + param = PyC_Long_AsI32(value); + + if (UNLIKELY(param & ~1)) { /* only accept 0/1 */ + param = -1; /* error out below */ + } + } + + if (param == -1) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected True/False or 0/1, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + return -1; + } + else { + if (data) { + *((bool *)data) = param; + } + else { + RNA_property_boolean_set(ptr, prop, param); + } + } + break; + } + case PROP_INT: { + int overflow; + long param = PyLong_AsLongAndOverflow(value, &overflow); + if (overflow || (param > INT_MAX) || (param < INT_MIN)) { + PyErr_Format(PyExc_ValueError, + "%.200s %.200s.%.200s value not in 'int' range " + "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + return -1; + } + else if (param == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected an int type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + return -1; + } + else { + int param_i = (int)param; + if (data) { + RNA_property_int_clamp(ptr, prop, ¶m_i); + *((int *)data) = param_i; + } + else { + RNA_property_int_set(ptr, prop, param_i); + } + } + break; + } + case PROP_FLOAT: { + float param = PyFloat_AsDouble(value); + if (PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a float type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + return -1; + } + else { + if (data) { + RNA_property_float_clamp(ptr, prop, (float *)¶m); + *((float *)data) = param; + } + else { + RNA_property_float_set(ptr, prop, param); + } + } + break; + } + case PROP_STRING: { + const int subtype = RNA_property_subtype(prop); + const char *param; + + if (value == Py_None) { + if ((RNA_property_flag(prop) & PROP_NEVER_NULL) == 0) { + if (data) { + *((char **)data) = (char *)NULL; + } + else { + RNA_property_string_set(ptr, prop, NULL); + } + } + else { + PyC_Err_Format_Prefix(PyExc_TypeError, + "%.200s %.200s.%.200s doesn't support None from string types", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + return -1; + } + } + else if (subtype == PROP_BYTESTRING) { + + /* Byte String */ + + param = PyBytes_AsString(value); + + if (param == NULL) { + if (PyBytes_Check(value)) { + /* there was an error assigning a string type, + * rather than setting a new error, prefix the existing one + */ + PyC_Err_Format_Prefix(PyExc_TypeError, + "%.200s %.200s.%.200s error assigning bytes", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a bytes type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + } + + return -1; + } + else { + if (data) { + *((char **)data) = (char *)param; + } + else { + RNA_property_string_set_bytes(ptr, prop, param, PyBytes_Size(value)); + } + } + } + else { + /* Unicode String */ #ifdef USE_STRING_COERCE - PyObject *value_coerce = NULL; - if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - /* TODO, get size */ - param = PyC_UnicodeAsByte(value, &value_coerce); - } - else { - param = _PyUnicode_AsString(value); - } + PyObject *value_coerce = NULL; + if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { + /* TODO, get size */ + param = PyC_UnicodeAsByte(value, &value_coerce); + } + else { + param = _PyUnicode_AsString(value); + } #else /* USE_STRING_COERCE */ - param = _PyUnicode_AsString(value); -#endif /* USE_STRING_COERCE */ - - if (param == NULL) { - if (PyUnicode_Check(value)) { - /* there was an error assigning a string type, - * rather than setting a new error, prefix the existing one - */ - PyC_Err_Format_Prefix(PyExc_TypeError, - "%.200s %.200s.%.200s error assigning string", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a string type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - } - - return -1; - } - else { - /* same as bytes */ - /* XXX, this is suspect but needed for function calls, need to see if theres a better way */ - if (data) { - *((char **)data) = (char *)param; - } - else { - RNA_property_string_set(ptr, prop, param); - } - } + param = _PyUnicode_AsString(value); +#endif /* USE_STRING_COERCE */ + + if (param == NULL) { + if (PyUnicode_Check(value)) { + /* there was an error assigning a string type, + * rather than setting a new error, prefix the existing one + */ + PyC_Err_Format_Prefix(PyExc_TypeError, + "%.200s %.200s.%.200s error assigning string", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a string type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + } + + return -1; + } + else { + /* same as bytes */ + /* XXX, this is suspect but needed for function calls, need to see if theres a better way */ + if (data) { + *((char **)data) = (char *)param; + } + else { + RNA_property_string_set(ptr, prop, param); + } + } #ifdef USE_STRING_COERCE - Py_XDECREF(value_coerce); -#endif /* USE_STRING_COERCE */ - } - break; - } - case PROP_ENUM: - { - int val = 0; - - /* type checkins is done by each function */ - if (RNA_property_flag(prop) & PROP_ENUM_FLAG) { - /* set of enum items, concatenate all values with OR */ - if (pyrna_prop_to_enum_bitfield(ptr, prop, value, &val, error_prefix) == -1) { - return -1; - } - } - else { - /* simple enum string */ - if (pyrna_string_to_enum(value, ptr, prop, &val, error_prefix) == -1) { - return -1; - } - } - - if (data) { - *((int *)data) = val; - } - else { - RNA_property_enum_set(ptr, prop, val); - } - - break; - } - case PROP_POINTER: - { - PyObject *value_new = NULL; - - StructRNA *ptr_type = RNA_property_pointer_type(ptr, prop); - int flag = RNA_property_flag(prop); - int flag_parameter = RNA_parameter_flag(prop); - - /* this is really nasty!, so we can fake the operator having direct properties eg: - * layout.prop(self, "filepath") - * ... which in fact should be - * layout.prop(self.properties, "filepath") - * - * we need to do this trick. - * if the prop is not an operator type and the pyobject is an operator, - * use its properties in place of its self. - * - * this is so bad that its almost a good reason to do away with fake 'self.properties -> self' - * class mixing if this causes problems in the future it should be removed. - */ - if ((ptr_type == &RNA_AnyType) && - (BPy_StructRNA_Check(value))) - { - const StructRNA *base_type = - RNA_struct_base_child_of(((const BPy_StructRNA *)value)->ptr.type, NULL); - if (ELEM(base_type, &RNA_Operator, &RNA_Gizmo)) { - value = PyObject_GetAttr(value, bpy_intern_str_properties); - value_new = value; - } - } - - /* if property is an OperatorProperties/GizmoProperties pointer and value is a map, - * forward back to pyrna_pydict_to_props */ - if (PyDict_Check(value)) { - const StructRNA *base_type = RNA_struct_base_child_of(ptr_type, NULL); - if (base_type == &RNA_OperatorProperties) { - PointerRNA opptr = RNA_property_pointer_get(ptr, prop); - return pyrna_pydict_to_props(&opptr, value, false, error_prefix); - } - else if (base_type == &RNA_GizmoProperties) { - PointerRNA opptr = RNA_property_pointer_get(ptr, prop); - return pyrna_pydict_to_props(&opptr, value, false, error_prefix); - } - } - - /* another exception, allow to pass a collection as an RNA property */ - if (Py_TYPE(value) == &pyrna_prop_collection_Type) { /* ok to ignore idprop collections */ - PointerRNA c_ptr; - BPy_PropertyRNA *value_prop = (BPy_PropertyRNA *)value; - if (RNA_property_collection_type_get(&value_prop->ptr, value_prop->prop, &c_ptr)) { - value = pyrna_struct_CreatePyObject(&c_ptr); - value_new = value; - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s collection has no type, " - "cant be used as a %.200s type", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), RNA_struct_identifier(ptr_type)); - return -1; - } - } - - if (!BPy_StructRNA_Check(value) && value != Py_None) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a %.200s type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), RNA_struct_identifier(ptr_type), - Py_TYPE(value)->tp_name); - Py_XDECREF(value_new); return -1; - } - else if ((flag & PROP_NEVER_NULL) && value == Py_None) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s does not support a 'None' assignment %.200s type", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), RNA_struct_identifier(ptr_type)); - Py_XDECREF(value_new); return -1; - } - else if ((value != Py_None) && - ((flag & PROP_ID_SELF_CHECK) && ptr->id.data == ((BPy_StructRNA *)value)->ptr.id.data)) - { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s ID type does not support assignment to its self", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - Py_XDECREF(value_new); return -1; - } - else { - BPy_StructRNA *param = (BPy_StructRNA *)value; - bool raise_error = false; - if (data) { - - if (flag_parameter & PARM_RNAPTR) { - if (flag & PROP_THICK_WRAP) { - if (value == Py_None) { - memset(data, 0, sizeof(PointerRNA)); - } - else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { - *((PointerRNA *)data) = param->ptr; - } - else { - raise_error = true; - } - } - else { - /* for function calls, we sometimes want to pass the 'ptr' directly, - * watch out that it remains valid!, possibly we could support this later if needed */ - BLI_assert(value_new == NULL); - if (value == Py_None) { - *((void **)data) = NULL; - } - else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { - *((PointerRNA **)data) = ¶m->ptr; - } - else { - raise_error = true; - } - } - } - else if (value == Py_None) { - *((void **)data) = NULL; - } - else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { - *((void **)data) = param->ptr.data; - } - else { - raise_error = true; - } - } - else { - /* data == NULL, assign to RNA */ - if (value == Py_None || RNA_struct_is_a(param->ptr.type, ptr_type)) { - RNA_property_pointer_set(ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr); - } - else { - raise_error = true; - } - } - - if (raise_error) { - if (pyrna_struct_validity_check(param) == -1) { - /* error set */ - } - else { - PointerRNA tmp; - RNA_pointer_create(NULL, ptr_type, NULL, &tmp); - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a %.200s type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), RNA_struct_identifier(tmp.type), - RNA_struct_identifier(param->ptr.type)); - } - Py_XDECREF(value_new); return -1; - } - } - - Py_XDECREF(value_new); - - break; - } - case PROP_COLLECTION: - { - Py_ssize_t seq_len, i; - PyObject *item; - PointerRNA itemptr; - ListBase *lb; - CollectionPointerLink *link; - - lb = (data) ? (ListBase *)data : NULL; - - /* convert a sequence of dict's into a collection */ - if (!PySequence_Check(value)) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a sequence for an RNA collection, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - return -1; - } - - seq_len = PySequence_Size(value); - for (i = 0; i < seq_len; i++) { - item = PySequence_GetItem(value, i); - - if (item == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s failed to get sequence index '%d' for an RNA collection", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), i); - Py_XDECREF(item); - return -1; - } - - if (PyDict_Check(item) == 0) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a each sequence " - "member to be a dict for an RNA collection, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(item)->tp_name); - Py_XDECREF(item); - return -1; - } - - if (lb) { - link = MEM_callocN(sizeof(CollectionPointerLink), "PyCollectionPointerLink"); - link->ptr = itemptr; - BLI_addtail(lb, link); - } - else { - RNA_property_collection_add(ptr, prop, &itemptr); - } - - if (pyrna_pydict_to_props( - &itemptr, item, true, - "Converting a python list to an RNA collection") == -1) - { - PyObject *msg = PyC_ExceptionBuffer(); - const char *msg_char = _PyUnicode_AsString(msg); - - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s error converting a member of a collection " - "from a dicts into an RNA collection, failed with: %s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), msg_char); - - Py_DECREF(item); - Py_DECREF(msg); - return -1; - } - Py_DECREF(item); - } - - break; - } - default: - PyErr_Format(PyExc_AttributeError, - "%.200s %.200s.%.200s unknown property type (pyrna_py_to_prop)", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - return -1; - } - } - - /* Run rna property functions */ - if (RNA_property_update_check(prop)) { - RNA_property_update(BPy_GetContext(), ptr, prop); - } - - return 0; + Py_XDECREF(value_coerce); +#endif /* USE_STRING_COERCE */ + } + break; + } + case PROP_ENUM: { + int val = 0; + + /* type checkins is done by each function */ + if (RNA_property_flag(prop) & PROP_ENUM_FLAG) { + /* set of enum items, concatenate all values with OR */ + if (pyrna_prop_to_enum_bitfield(ptr, prop, value, &val, error_prefix) == -1) { + return -1; + } + } + else { + /* simple enum string */ + if (pyrna_string_to_enum(value, ptr, prop, &val, error_prefix) == -1) { + return -1; + } + } + + if (data) { + *((int *)data) = val; + } + else { + RNA_property_enum_set(ptr, prop, val); + } + + break; + } + case PROP_POINTER: { + PyObject *value_new = NULL; + + StructRNA *ptr_type = RNA_property_pointer_type(ptr, prop); + int flag = RNA_property_flag(prop); + int flag_parameter = RNA_parameter_flag(prop); + + /* this is really nasty!, so we can fake the operator having direct properties eg: + * layout.prop(self, "filepath") + * ... which in fact should be + * layout.prop(self.properties, "filepath") + * + * we need to do this trick. + * if the prop is not an operator type and the pyobject is an operator, + * use its properties in place of its self. + * + * this is so bad that its almost a good reason to do away with fake 'self.properties -> self' + * class mixing if this causes problems in the future it should be removed. + */ + if ((ptr_type == &RNA_AnyType) && (BPy_StructRNA_Check(value))) { + const StructRNA *base_type = RNA_struct_base_child_of( + ((const BPy_StructRNA *)value)->ptr.type, NULL); + if (ELEM(base_type, &RNA_Operator, &RNA_Gizmo)) { + value = PyObject_GetAttr(value, bpy_intern_str_properties); + value_new = value; + } + } + + /* if property is an OperatorProperties/GizmoProperties pointer and value is a map, + * forward back to pyrna_pydict_to_props */ + if (PyDict_Check(value)) { + const StructRNA *base_type = RNA_struct_base_child_of(ptr_type, NULL); + if (base_type == &RNA_OperatorProperties) { + PointerRNA opptr = RNA_property_pointer_get(ptr, prop); + return pyrna_pydict_to_props(&opptr, value, false, error_prefix); + } + else if (base_type == &RNA_GizmoProperties) { + PointerRNA opptr = RNA_property_pointer_get(ptr, prop); + return pyrna_pydict_to_props(&opptr, value, false, error_prefix); + } + } + + /* another exception, allow to pass a collection as an RNA property */ + if (Py_TYPE(value) == &pyrna_prop_collection_Type) { /* ok to ignore idprop collections */ + PointerRNA c_ptr; + BPy_PropertyRNA *value_prop = (BPy_PropertyRNA *)value; + if (RNA_property_collection_type_get(&value_prop->ptr, value_prop->prop, &c_ptr)) { + value = pyrna_struct_CreatePyObject(&c_ptr); + value_new = value; + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s collection has no type, " + "cant be used as a %.200s type", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + RNA_struct_identifier(ptr_type)); + return -1; + } + } + + if (!BPy_StructRNA_Check(value) && value != Py_None) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a %.200s type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + RNA_struct_identifier(ptr_type), + Py_TYPE(value)->tp_name); + Py_XDECREF(value_new); + return -1; + } + else if ((flag & PROP_NEVER_NULL) && value == Py_None) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s does not support a 'None' assignment %.200s type", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + RNA_struct_identifier(ptr_type)); + Py_XDECREF(value_new); + return -1; + } + else if ((value != Py_None) && ((flag & PROP_ID_SELF_CHECK) && + ptr->id.data == ((BPy_StructRNA *)value)->ptr.id.data)) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s ID type does not support assignment to its self", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + Py_XDECREF(value_new); + return -1; + } + else { + BPy_StructRNA *param = (BPy_StructRNA *)value; + bool raise_error = false; + if (data) { + + if (flag_parameter & PARM_RNAPTR) { + if (flag & PROP_THICK_WRAP) { + if (value == Py_None) { + memset(data, 0, sizeof(PointerRNA)); + } + else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { + *((PointerRNA *)data) = param->ptr; + } + else { + raise_error = true; + } + } + else { + /* for function calls, we sometimes want to pass the 'ptr' directly, + * watch out that it remains valid!, possibly we could support this later if needed */ + BLI_assert(value_new == NULL); + if (value == Py_None) { + *((void **)data) = NULL; + } + else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { + *((PointerRNA **)data) = ¶m->ptr; + } + else { + raise_error = true; + } + } + } + else if (value == Py_None) { + *((void **)data) = NULL; + } + else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { + *((void **)data) = param->ptr.data; + } + else { + raise_error = true; + } + } + else { + /* data == NULL, assign to RNA */ + if (value == Py_None || RNA_struct_is_a(param->ptr.type, ptr_type)) { + RNA_property_pointer_set(ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr); + } + else { + raise_error = true; + } + } + + if (raise_error) { + if (pyrna_struct_validity_check(param) == -1) { + /* error set */ + } + else { + PointerRNA tmp; + RNA_pointer_create(NULL, ptr_type, NULL, &tmp); + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a %.200s type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + RNA_struct_identifier(tmp.type), + RNA_struct_identifier(param->ptr.type)); + } + Py_XDECREF(value_new); + return -1; + } + } + + Py_XDECREF(value_new); + + break; + } + case PROP_COLLECTION: { + Py_ssize_t seq_len, i; + PyObject *item; + PointerRNA itemptr; + ListBase *lb; + CollectionPointerLink *link; + + lb = (data) ? (ListBase *)data : NULL; + + /* convert a sequence of dict's into a collection */ + if (!PySequence_Check(value)) { + PyErr_Format( + PyExc_TypeError, + "%.200s %.200s.%.200s expected a sequence for an RNA collection, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + return -1; + } + + seq_len = PySequence_Size(value); + for (i = 0; i < seq_len; i++) { + item = PySequence_GetItem(value, i); + + if (item == NULL) { + PyErr_Format( + PyExc_TypeError, + "%.200s %.200s.%.200s failed to get sequence index '%d' for an RNA collection", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + i); + Py_XDECREF(item); + return -1; + } + + if (PyDict_Check(item) == 0) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a each sequence " + "member to be a dict for an RNA collection, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(item)->tp_name); + Py_XDECREF(item); + return -1; + } + + if (lb) { + link = MEM_callocN(sizeof(CollectionPointerLink), "PyCollectionPointerLink"); + link->ptr = itemptr; + BLI_addtail(lb, link); + } + else { + RNA_property_collection_add(ptr, prop, &itemptr); + } + + if (pyrna_pydict_to_props( + &itemptr, item, true, "Converting a python list to an RNA collection") == -1) { + PyObject *msg = PyC_ExceptionBuffer(); + const char *msg_char = _PyUnicode_AsString(msg); + + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s error converting a member of a collection " + "from a dicts into an RNA collection, failed with: %s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + msg_char); + + Py_DECREF(item); + Py_DECREF(msg); + return -1; + } + Py_DECREF(item); + } + + break; + } + default: + PyErr_Format(PyExc_AttributeError, + "%.200s %.200s.%.200s unknown property type (pyrna_py_to_prop)", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + return -1; + } + } + + /* Run rna property functions */ + if (RNA_property_update_check(prop)) { + RNA_property_update(BPy_GetContext(), ptr, prop); + } + + return 0; } static PyObject *pyrna_prop_array_to_py_index(BPy_PropertyArrayRNA *self, int index) { - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); - return pyrna_py_from_array_index(self, &self->ptr, self->prop, index); + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); + return pyrna_py_from_array_index(self, &self->ptr, self->prop, index); } static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, PyObject *value) { - int ret = 0; - PointerRNA *ptr = &self->ptr; - PropertyRNA *prop = self->prop; - - const int totdim = RNA_property_array_dimension(ptr, prop, NULL); - - if (totdim > 1) { - /* char error_str[512]; */ - if (pyrna_py_to_array_index(&self->ptr, self->prop, self->arraydim, self->arrayoffset, index, value, "") == -1) { - /* error is set */ - ret = -1; - } - } - else { - /* see if we can coerce into a python type - PropertyType */ - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - { - int param = PyC_Long_AsBool(value); - - if (param == -1) { - /* error is set */ - ret = -1; - } - else { - RNA_property_boolean_set_index(ptr, prop, index, param); - } - break; - } - case PROP_INT: - { - int param = PyC_Long_AsI32(value); - if (param == -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected an int type"); - ret = -1; - } - else { - RNA_property_int_clamp(ptr, prop, ¶m); - RNA_property_int_set_index(ptr, prop, index, param); - } - break; - } - case PROP_FLOAT: - { - float param = PyFloat_AsDouble(value); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected a float type"); - ret = -1; - } - else { - RNA_property_float_clamp(ptr, prop, ¶m); - RNA_property_float_set_index(ptr, prop, index, param); - } - break; - } - default: - PyErr_SetString(PyExc_AttributeError, "not an array type"); - ret = -1; - break; - } - } - - /* Run rna property functions */ - if (RNA_property_update_check(prop)) { - RNA_property_update(BPy_GetContext(), ptr, prop); - } - - return ret; + int ret = 0; + PointerRNA *ptr = &self->ptr; + PropertyRNA *prop = self->prop; + + const int totdim = RNA_property_array_dimension(ptr, prop, NULL); + + if (totdim > 1) { + /* char error_str[512]; */ + if (pyrna_py_to_array_index( + &self->ptr, self->prop, self->arraydim, self->arrayoffset, index, value, "") == -1) { + /* error is set */ + ret = -1; + } + } + else { + /* see if we can coerce into a python type - PropertyType */ + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: { + int param = PyC_Long_AsBool(value); + + if (param == -1) { + /* error is set */ + ret = -1; + } + else { + RNA_property_boolean_set_index(ptr, prop, index, param); + } + break; + } + case PROP_INT: { + int param = PyC_Long_AsI32(value); + if (param == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected an int type"); + ret = -1; + } + else { + RNA_property_int_clamp(ptr, prop, ¶m); + RNA_property_int_set_index(ptr, prop, index, param); + } + break; + } + case PROP_FLOAT: { + float param = PyFloat_AsDouble(value); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected a float type"); + ret = -1; + } + else { + RNA_property_float_clamp(ptr, prop, ¶m); + RNA_property_float_set_index(ptr, prop, index, param); + } + break; + } + default: + PyErr_SetString(PyExc_AttributeError, "not an array type"); + ret = -1; + break; + } + } + + /* Run rna property functions */ + if (RNA_property_update_check(prop)) { + RNA_property_update(BPy_GetContext(), ptr, prop); + } + + return ret; } /* ---------------sequence------------------------------------------- */ static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self) { - PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); + PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); - if (RNA_property_array_dimension(&self->ptr, self->prop, NULL) > 1) { - return RNA_property_multi_array_length(&self->ptr, self->prop, self->arraydim); - } - else { - return RNA_property_array_length(&self->ptr, self->prop); - } + if (RNA_property_array_dimension(&self->ptr, self->prop, NULL) > 1) { + return RNA_property_multi_array_length(&self->ptr, self->prop, self->arraydim); + } + else { + return RNA_property_array_length(&self->ptr, self->prop); + } } static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self) { - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - return RNA_property_collection_length(&self->ptr, self->prop); + return RNA_property_collection_length(&self->ptr, self->prop); } /* bool functions are for speed, so we can avoid getting the length * of 1000's of items in a linked list for eg. */ static int pyrna_prop_array_bool(BPy_PropertyRNA *self) { - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - return RNA_property_array_length(&self->ptr, self->prop) ? 1 : 0; + return RNA_property_array_length(&self->ptr, self->prop) ? 1 : 0; } static int pyrna_prop_collection_bool(BPy_PropertyRNA *self) { - /* no callback defined, just iterate and find the nth item */ - CollectionPropertyIterator iter; - int test; + /* no callback defined, just iterate and find the nth item */ + CollectionPropertyIterator iter; + int test; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - RNA_property_collection_begin(&self->ptr, self->prop, &iter); - test = iter.valid; - RNA_property_collection_end(&iter); - return test; + RNA_property_collection_begin(&self->ptr, self->prop, &iter); + test = iter.valid; + RNA_property_collection_end(&iter); + return test; } - /* notice getting the length of the collection is avoided unless negative * index is used or to detect internal error with a valid index. * This is done for faster lookups. */ -#define PYRNA_PROP_COLLECTION_ABS_INDEX(ret_err) \ - if (keynum < 0) { \ - keynum_abs += RNA_property_collection_length(&self->ptr, self->prop); \ - if (keynum_abs < 0) { \ - PyErr_Format(PyExc_IndexError, \ - "bpy_prop_collection[%d]: out of range.", keynum); \ - return ret_err; \ - } \ - } (void)0 - +#define PYRNA_PROP_COLLECTION_ABS_INDEX(ret_err) \ + if (keynum < 0) { \ + keynum_abs += RNA_property_collection_length(&self->ptr, self->prop); \ + if (keynum_abs < 0) { \ + PyErr_Format(PyExc_IndexError, "bpy_prop_collection[%d]: out of range.", keynum); \ + return ret_err; \ + } \ + } \ + (void)0 /* internal use only */ static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum) { - PointerRNA newptr; - Py_ssize_t keynum_abs = keynum; - - PYRNA_PROP_CHECK_OBJ(self); - - PYRNA_PROP_COLLECTION_ABS_INDEX(NULL); - - if (RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum_abs, &newptr)) { - return pyrna_struct_CreatePyObject(&newptr); - } - else { - const int len = RNA_property_collection_length(&self->ptr, self->prop); - if (keynum_abs >= len) { - PyErr_Format(PyExc_IndexError, - "bpy_prop_collection[index]: " - "index %d out of range, size %d", keynum, len); - } - else { - PyErr_Format(PyExc_RuntimeError, - "bpy_prop_collection[index]: internal error, " - "valid index %d given in %d sized collection but value not found", - keynum_abs, len); - } - - return NULL; - } + PointerRNA newptr; + Py_ssize_t keynum_abs = keynum; + + PYRNA_PROP_CHECK_OBJ(self); + + PYRNA_PROP_COLLECTION_ABS_INDEX(NULL); + + if (RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum_abs, &newptr)) { + return pyrna_struct_CreatePyObject(&newptr); + } + else { + const int len = RNA_property_collection_length(&self->ptr, self->prop); + if (keynum_abs >= len) { + PyErr_Format(PyExc_IndexError, + "bpy_prop_collection[index]: " + "index %d out of range, size %d", + keynum, + len); + } + else { + PyErr_Format(PyExc_RuntimeError, + "bpy_prop_collection[index]: internal error, " + "valid index %d given in %d sized collection but value not found", + keynum_abs, + len); + } + + return NULL; + } } /* values type must have been already checked */ -static int pyrna_prop_collection_ass_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum, PyObject *value) +static int pyrna_prop_collection_ass_subscript_int(BPy_PropertyRNA *self, + Py_ssize_t keynum, + PyObject *value) { - Py_ssize_t keynum_abs = keynum; - const PointerRNA *ptr = (value == Py_None) ? (&PointerRNA_NULL) : &((BPy_StructRNA *)value)->ptr; + Py_ssize_t keynum_abs = keynum; + const PointerRNA *ptr = (value == Py_None) ? (&PointerRNA_NULL) : &((BPy_StructRNA *)value)->ptr; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - PYRNA_PROP_COLLECTION_ABS_INDEX(-1); + PYRNA_PROP_COLLECTION_ABS_INDEX(-1); - if (RNA_property_collection_assign_int(&self->ptr, self->prop, keynum_abs, ptr) == 0) { - const int len = RNA_property_collection_length(&self->ptr, self->prop); - if (keynum_abs >= len) { - PyErr_Format(PyExc_IndexError, - "bpy_prop_collection[index] = value: " - "index %d out of range, size %d", keynum, len); - } - else { + if (RNA_property_collection_assign_int(&self->ptr, self->prop, keynum_abs, ptr) == 0) { + const int len = RNA_property_collection_length(&self->ptr, self->prop); + if (keynum_abs >= len) { + PyErr_Format(PyExc_IndexError, + "bpy_prop_collection[index] = value: " + "index %d out of range, size %d", + keynum, + len); + } + else { - PyErr_Format(PyExc_IndexError, - "bpy_prop_collection[index] = value: " - "failed assignment (unknown reason)", keynum); - } - return -1; - } + PyErr_Format(PyExc_IndexError, + "bpy_prop_collection[index] = value: " + "failed assignment (unknown reason)", + keynum); + } + return -1; + } - return 0; + return 0; } static PyObject *pyrna_prop_array_subscript_int(BPy_PropertyArrayRNA *self, int keynum) { - int len; + int len; - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); - len = pyrna_prop_array_length(self); + len = pyrna_prop_array_length(self); - if (keynum < 0) { - keynum += len; - } + if (keynum < 0) { + keynum += len; + } - if (keynum >= 0 && keynum < len) { - return pyrna_prop_array_to_py_index(self, keynum); - } + if (keynum >= 0 && keynum < len) { + return pyrna_prop_array_to_py_index(self, keynum); + } - PyErr_Format(PyExc_IndexError, - "bpy_prop_array[index]: index %d out of range", keynum); - return NULL; + PyErr_Format(PyExc_IndexError, "bpy_prop_array[index]: index %d out of range", keynum); + return NULL; } static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, const char *keyname) { - PointerRNA newptr; + PointerRNA newptr; - PYRNA_PROP_CHECK_OBJ(self); + PYRNA_PROP_CHECK_OBJ(self); - if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) { - return pyrna_struct_CreatePyObject(&newptr); - } + if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) { + return pyrna_struct_CreatePyObject(&newptr); + } - PyErr_Format(PyExc_KeyError, "bpy_prop_collection[key]: key \"%.200s\" not found", keyname); - return NULL; + PyErr_Format(PyExc_KeyError, "bpy_prop_collection[key]: key \"%.200s\" not found", keyname); + return NULL; } /* static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) */ @@ -2363,482 +2397,498 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons * - 0: not found * - 1: found */ -static int pyrna_prop_collection_subscript_str_lib_pair_ptr( - BPy_PropertyRNA *self, PyObject *key, - const char *err_prefix, const short err_not_found, - PointerRNA *r_ptr) -{ - const char *keyname; - - /* first validate the args, all we know is that they are a tuple */ - if (PyTuple_GET_SIZE(key) != 2) { - PyErr_Format(PyExc_KeyError, - "%s: tuple key must be a pair, not size %d", - err_prefix, PyTuple_GET_SIZE(key)); - return -1; - } - else if (self->ptr.type != &RNA_BlendData) { - PyErr_Format(PyExc_KeyError, - "%s: is only valid for bpy.data collections, not %.200s", - err_prefix, RNA_struct_identifier(self->ptr.type)); - return -1; - } - else if ((keyname = _PyUnicode_AsString(PyTuple_GET_ITEM(key, 0))) == NULL) { - PyErr_Format(PyExc_KeyError, - "%s: id must be a string, not %.200s", - err_prefix, Py_TYPE(PyTuple_GET_ITEM(key, 0))->tp_name); - return -1; - } - else { - PyObject *keylib = PyTuple_GET_ITEM(key, 1); - Library *lib; - bool found = false; - - if (keylib == Py_None) { - lib = NULL; - } - else if (PyUnicode_Check(keylib)) { - Main *bmain = self->ptr.data; - const char *keylib_str = _PyUnicode_AsString(keylib); - lib = BLI_findstring(&bmain->libraries, keylib_str, offsetof(Library, name)); - if (lib == NULL) { - if (err_not_found) { - PyErr_Format(PyExc_KeyError, - "%s: lib name '%.240s' " - "does not reference a valid library", - err_prefix, keylib_str); - return -1; - } - else { - return 0; - } - - } - } - else { - PyErr_Format(PyExc_KeyError, - "%s: lib must be a string or None, not %.200s", - err_prefix, Py_TYPE(keylib)->tp_name); - return -1; - } - - /* lib is either a valid pointer or NULL, - * either way can do direct comparison with id.lib */ - - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - ID *id = itemptr.data; /* always an ID */ - if (id->lib == lib && (STREQLEN(keyname, id->name + 2, sizeof(id->name) - 2))) { - found = true; - if (r_ptr) { - *r_ptr = itemptr; - } - break; - } - } - RNA_PROP_END; - - /* we may want to fail silently as with collection.get() */ - if ((found == false) && err_not_found) { - /* only runs for getitem access so use fixed string */ - PyErr_SetString(PyExc_KeyError, - "bpy_prop_collection[key, lib]: not found"); - return -1; - } - else { - return found; /* 1 / 0, no exception */ - } - } -} - -static PyObject *pyrna_prop_collection_subscript_str_lib_pair( - BPy_PropertyRNA *self, PyObject *key, - const char *err_prefix, const bool err_not_found) -{ - PointerRNA ptr; - const int contains = pyrna_prop_collection_subscript_str_lib_pair_ptr(self, key, err_prefix, err_not_found, &ptr); - - if (contains == 1) { - return pyrna_struct_CreatePyObject(&ptr); - } - else { - return NULL; - } -} - - -static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py_ssize_t start, Py_ssize_t stop) -{ - CollectionPropertyIterator rna_macro_iter; - int count; - - PyObject *list; - PyObject *item; - - PYRNA_PROP_CHECK_OBJ(self); - - list = PyList_New(0); - - /* skip to start */ - RNA_property_collection_begin(&self->ptr, self->prop, &rna_macro_iter); - RNA_property_collection_skip(&rna_macro_iter, start); - - /* add items until stop */ - for (count = start; rna_macro_iter.valid; - RNA_property_collection_next(&rna_macro_iter)) - { - item = pyrna_struct_CreatePyObject(&rna_macro_iter.ptr); - PyList_APPEND(list, item); - - count++; - if (count == stop) { - break; - } - } - - RNA_property_collection_end(&rna_macro_iter); - - return list; +static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *self, + PyObject *key, + const char *err_prefix, + const short err_not_found, + PointerRNA *r_ptr) +{ + const char *keyname; + + /* first validate the args, all we know is that they are a tuple */ + if (PyTuple_GET_SIZE(key) != 2) { + PyErr_Format(PyExc_KeyError, + "%s: tuple key must be a pair, not size %d", + err_prefix, + PyTuple_GET_SIZE(key)); + return -1; + } + else if (self->ptr.type != &RNA_BlendData) { + PyErr_Format(PyExc_KeyError, + "%s: is only valid for bpy.data collections, not %.200s", + err_prefix, + RNA_struct_identifier(self->ptr.type)); + return -1; + } + else if ((keyname = _PyUnicode_AsString(PyTuple_GET_ITEM(key, 0))) == NULL) { + PyErr_Format(PyExc_KeyError, + "%s: id must be a string, not %.200s", + err_prefix, + Py_TYPE(PyTuple_GET_ITEM(key, 0))->tp_name); + return -1; + } + else { + PyObject *keylib = PyTuple_GET_ITEM(key, 1); + Library *lib; + bool found = false; + + if (keylib == Py_None) { + lib = NULL; + } + else if (PyUnicode_Check(keylib)) { + Main *bmain = self->ptr.data; + const char *keylib_str = _PyUnicode_AsString(keylib); + lib = BLI_findstring(&bmain->libraries, keylib_str, offsetof(Library, name)); + if (lib == NULL) { + if (err_not_found) { + PyErr_Format(PyExc_KeyError, + "%s: lib name '%.240s' " + "does not reference a valid library", + err_prefix, + keylib_str); + return -1; + } + else { + return 0; + } + } + } + else { + PyErr_Format(PyExc_KeyError, + "%s: lib must be a string or None, not %.200s", + err_prefix, + Py_TYPE(keylib)->tp_name); + return -1; + } + + /* lib is either a valid pointer or NULL, + * either way can do direct comparison with id.lib */ + + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + ID *id = itemptr.data; /* always an ID */ + if (id->lib == lib && (STREQLEN(keyname, id->name + 2, sizeof(id->name) - 2))) { + found = true; + if (r_ptr) { + *r_ptr = itemptr; + } + break; + } + } + RNA_PROP_END; + + /* we may want to fail silently as with collection.get() */ + if ((found == false) && err_not_found) { + /* only runs for getitem access so use fixed string */ + PyErr_SetString(PyExc_KeyError, "bpy_prop_collection[key, lib]: not found"); + return -1; + } + else { + return found; /* 1 / 0, no exception */ + } + } +} + +static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *self, + PyObject *key, + const char *err_prefix, + const bool err_not_found) +{ + PointerRNA ptr; + const int contains = pyrna_prop_collection_subscript_str_lib_pair_ptr( + self, key, err_prefix, err_not_found, &ptr); + + if (contains == 1) { + return pyrna_struct_CreatePyObject(&ptr); + } + else { + return NULL; + } +} + +static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, + Py_ssize_t start, + Py_ssize_t stop) +{ + CollectionPropertyIterator rna_macro_iter; + int count; + + PyObject *list; + PyObject *item; + + PYRNA_PROP_CHECK_OBJ(self); + + list = PyList_New(0); + + /* skip to start */ + RNA_property_collection_begin(&self->ptr, self->prop, &rna_macro_iter); + RNA_property_collection_skip(&rna_macro_iter, start); + + /* add items until stop */ + for (count = start; rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) { + item = pyrna_struct_CreatePyObject(&rna_macro_iter.ptr); + PyList_APPEND(list, item); + + count++; + if (count == stop) { + break; + } + } + + RNA_property_collection_end(&rna_macro_iter); + + return list; } /* TODO - dimensions * note: could also use pyrna_prop_array_to_py_index(self, count) in a loop but its a lot slower * since at the moment it reads (and even allocates) the entire array for each index. */ -static PyObject *pyrna_prop_array_subscript_slice( - BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, - Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length) -{ - int count, totdim; - PyObject *tuple; - - /* isn't needed, internal use only */ - // PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); - - tuple = PyTuple_New(stop - start); - - totdim = RNA_property_array_dimension(ptr, prop, NULL); - - if (totdim > 1) { - for (count = start; count < stop; count++) { - PyTuple_SET_ITEM(tuple, count - start, pyrna_prop_array_to_py_index(self, count)); - } - } - else { - switch (RNA_property_type(prop)) { - case PROP_FLOAT: - { - float values_stack[PYRNA_STACK_ARRAY]; - float *values; - if (length > PYRNA_STACK_ARRAY) { values = PyMem_MALLOC(sizeof(float) * length); } - else { values = values_stack; } - RNA_property_float_get_array(ptr, prop, values); - - for (count = start; count < stop; count++) { - PyTuple_SET_ITEM(tuple, count - start, PyFloat_FromDouble(values[count])); - } - - if (values != values_stack) { - PyMem_FREE(values); - } - break; - } - case PROP_BOOLEAN: - { - bool values_stack[PYRNA_STACK_ARRAY]; - bool *values; - if (length > PYRNA_STACK_ARRAY) { values = PyMem_MALLOC(sizeof(bool) * length); } - else { values = values_stack; } - - RNA_property_boolean_get_array(ptr, prop, values); - for (count = start; count < stop; count++) { - PyTuple_SET_ITEM(tuple, count - start, PyBool_FromLong(values[count])); - } - - if (values != values_stack) { - PyMem_FREE(values); - } - break; - } - case PROP_INT: - { - int values_stack[PYRNA_STACK_ARRAY]; - int *values; - if (length > PYRNA_STACK_ARRAY) { values = PyMem_MALLOC(sizeof(int) * length); } - else { values = values_stack; } - - RNA_property_int_get_array(ptr, prop, values); - for (count = start; count < stop; count++) { - PyTuple_SET_ITEM(tuple, count - start, PyLong_FromLong(values[count])); - } - - if (values != values_stack) { - PyMem_FREE(values); - } - break; - } - default: - BLI_assert(!"Invalid array type"); - - PyErr_SetString(PyExc_TypeError, "not an array type"); - Py_DECREF(tuple); - tuple = NULL; - break; - } - } - return tuple; +static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, + PointerRNA *ptr, + PropertyRNA *prop, + Py_ssize_t start, + Py_ssize_t stop, + Py_ssize_t length) +{ + int count, totdim; + PyObject *tuple; + + /* isn't needed, internal use only */ + // PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); + + tuple = PyTuple_New(stop - start); + + totdim = RNA_property_array_dimension(ptr, prop, NULL); + + if (totdim > 1) { + for (count = start; count < stop; count++) { + PyTuple_SET_ITEM(tuple, count - start, pyrna_prop_array_to_py_index(self, count)); + } + } + else { + switch (RNA_property_type(prop)) { + case PROP_FLOAT: { + float values_stack[PYRNA_STACK_ARRAY]; + float *values; + if (length > PYRNA_STACK_ARRAY) { + values = PyMem_MALLOC(sizeof(float) * length); + } + else { + values = values_stack; + } + RNA_property_float_get_array(ptr, prop, values); + + for (count = start; count < stop; count++) { + PyTuple_SET_ITEM(tuple, count - start, PyFloat_FromDouble(values[count])); + } + + if (values != values_stack) { + PyMem_FREE(values); + } + break; + } + case PROP_BOOLEAN: { + bool values_stack[PYRNA_STACK_ARRAY]; + bool *values; + if (length > PYRNA_STACK_ARRAY) { + values = PyMem_MALLOC(sizeof(bool) * length); + } + else { + values = values_stack; + } + + RNA_property_boolean_get_array(ptr, prop, values); + for (count = start; count < stop; count++) { + PyTuple_SET_ITEM(tuple, count - start, PyBool_FromLong(values[count])); + } + + if (values != values_stack) { + PyMem_FREE(values); + } + break; + } + case PROP_INT: { + int values_stack[PYRNA_STACK_ARRAY]; + int *values; + if (length > PYRNA_STACK_ARRAY) { + values = PyMem_MALLOC(sizeof(int) * length); + } + else { + values = values_stack; + } + + RNA_property_int_get_array(ptr, prop, values); + for (count = start; count < stop; count++) { + PyTuple_SET_ITEM(tuple, count - start, PyLong_FromLong(values[count])); + } + + if (values != values_stack) { + PyMem_FREE(values); + } + break; + } + default: + BLI_assert(!"Invalid array type"); + + PyErr_SetString(PyExc_TypeError, "not an array type"); + Py_DECREF(tuple); + tuple = NULL; + break; + } + } + return tuple; } static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject *key) { - PYRNA_PROP_CHECK_OBJ(self); - - if (PyUnicode_Check(key)) { - return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); - } - else if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return NULL; - } - - return pyrna_prop_collection_subscript_int(self, i); - } - else if (PySlice_Check(key)) { - PySliceObject *key_slice = (PySliceObject *)key; - Py_ssize_t step = 1; - - if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { - return NULL; - } - else if (step != 1) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported"); - return NULL; - } - else if (key_slice->start == Py_None && key_slice->stop == Py_None) { - return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); - } - else { - Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX; - - /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */ - if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) { - return NULL; - } - if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) { - return NULL; - } - - if (start < 0 || stop < 0) { - /* only get the length for negative values */ - Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); - if (start < 0) { - start += len; - } - if (stop < 0) { - stop += len; - } - } - - if (stop - start <= 0) { - return PyList_New(0); - } - else { - return pyrna_prop_collection_subscript_slice(self, start, stop); - } - } - } - else if (PyTuple_Check(key)) { - /* special case, for ID datablocks we */ - return pyrna_prop_collection_subscript_str_lib_pair(self, key, - "bpy_prop_collection[id, lib]", true); - } - else { - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key]: invalid key, " - "must be a string or an int, not %.200s", - Py_TYPE(key)->tp_name); - return NULL; - } + PYRNA_PROP_CHECK_OBJ(self); + + if (PyUnicode_Check(key)) { + return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); + } + else if (PyIndex_Check(key)) { + Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return NULL; + } + + return pyrna_prop_collection_subscript_int(self, i); + } + else if (PySlice_Check(key)) { + PySliceObject *key_slice = (PySliceObject *)key; + Py_ssize_t step = 1; + + if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { + return NULL; + } + else if (step != 1) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported"); + return NULL; + } + else if (key_slice->start == Py_None && key_slice->stop == Py_None) { + return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); + } + else { + Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX; + + /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */ + if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) { + return NULL; + } + if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) { + return NULL; + } + + if (start < 0 || stop < 0) { + /* only get the length for negative values */ + Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); + if (start < 0) { + start += len; + } + if (stop < 0) { + stop += len; + } + } + + if (stop - start <= 0) { + return PyList_New(0); + } + else { + return pyrna_prop_collection_subscript_slice(self, start, stop); + } + } + } + else if (PyTuple_Check(key)) { + /* special case, for ID datablocks we */ + return pyrna_prop_collection_subscript_str_lib_pair( + self, key, "bpy_prop_collection[id, lib]", true); + } + else { + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key]: invalid key, " + "must be a string or an int, not %.200s", + Py_TYPE(key)->tp_name); + return NULL; + } } /* generic check to see if a PyObject is compatible with a collection * -1 on failure, 0 on success, sets the error */ static int pyrna_prop_collection_type_check(BPy_PropertyRNA *self, PyObject *value) { - StructRNA *prop_srna; - - if (value == Py_None) { - if (RNA_property_flag(self->prop) & PROP_NEVER_NULL) { - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key] = value: invalid, " - "this collection doesn't support None assignment"); - return -1; - } - else { - return 0; /* None is OK */ - } - } - else if (BPy_StructRNA_Check(value) == 0) { - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key] = value: invalid, " - "expected a StructRNA type or None, not a %.200s", - Py_TYPE(value)->tp_name); - return -1; - } - else if ((prop_srna = RNA_property_pointer_type(&self->ptr, self->prop))) { - StructRNA *value_srna = ((BPy_StructRNA *)value)->ptr.type; - if (RNA_struct_is_a(value_srna, prop_srna) == 0) { - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key] = value: invalid, " - "expected a '%.200s' type or None, not a '%.200s'", - RNA_struct_identifier(prop_srna), - RNA_struct_identifier(value_srna) - ); - return -1; - } - else { - return 0; /* OK, this is the correct type!*/ - } - } - - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key] = value: internal error, " - "failed to get the collection type"); - return -1; + StructRNA *prop_srna; + + if (value == Py_None) { + if (RNA_property_flag(self->prop) & PROP_NEVER_NULL) { + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key] = value: invalid, " + "this collection doesn't support None assignment"); + return -1; + } + else { + return 0; /* None is OK */ + } + } + else if (BPy_StructRNA_Check(value) == 0) { + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key] = value: invalid, " + "expected a StructRNA type or None, not a %.200s", + Py_TYPE(value)->tp_name); + return -1; + } + else if ((prop_srna = RNA_property_pointer_type(&self->ptr, self->prop))) { + StructRNA *value_srna = ((BPy_StructRNA *)value)->ptr.type; + if (RNA_struct_is_a(value_srna, prop_srna) == 0) { + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key] = value: invalid, " + "expected a '%.200s' type or None, not a '%.200s'", + RNA_struct_identifier(prop_srna), + RNA_struct_identifier(value_srna)); + return -1; + } + else { + return 0; /* OK, this is the correct type!*/ + } + } + + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key] = value: internal error, " + "failed to get the collection type"); + return -1; } /* note: currently this is a copy of 'pyrna_prop_collection_subscript' with * large blocks commented, we may support slice/key indices later */ -static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, PyObject *key, PyObject *value) +static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, + PyObject *key, + PyObject *value) { - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - /* validate the assigned value */ - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, - "del bpy_prop_collection[key]: not supported"); - return -1; - } - else if (pyrna_prop_collection_type_check(self, value) == -1) { - return -1; /* exception is set */ - } + /* validate the assigned value */ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "del bpy_prop_collection[key]: not supported"); + return -1; + } + else if (pyrna_prop_collection_type_check(self, value) == -1) { + return -1; /* exception is set */ + } #if 0 - if (PyUnicode_Check(key)) { - return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); - } - else + if (PyUnicode_Check(key)) { + return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); + } + else #endif - if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return -1; - } - - return pyrna_prop_collection_ass_subscript_int(self, i, value); - } + if (PyIndex_Check(key)) { + Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return -1; + } + + return pyrna_prop_collection_ass_subscript_int(self, i, value); + } #if 0 /* TODO, fake slice assignment */ - else if (PySlice_Check(key)) { - PySliceObject *key_slice = (PySliceObject *)key; - Py_ssize_t step = 1; - - if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { - return NULL; - } - else if (step != 1) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported"); - return NULL; - } - else if (key_slice->start == Py_None && key_slice->stop == Py_None) { - return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); - } - else { - Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX; - - /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */ - if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL; - if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL; - - if (start < 0 || stop < 0) { - /* only get the length for negative values */ - Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); - if (start < 0) start += len; - if (stop < 0) stop += len; - } - - if (stop - start <= 0) { - return PyList_New(0); - } - else { - return pyrna_prop_collection_subscript_slice(self, start, stop); - } - } - } + else if (PySlice_Check(key)) { + PySliceObject *key_slice = (PySliceObject *)key; + Py_ssize_t step = 1; + + if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { + return NULL; + } + else if (step != 1) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported"); + return NULL; + } + else if (key_slice->start == Py_None && key_slice->stop == Py_None) { + return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); + } + else { + Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX; + + /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */ + if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL; + if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL; + + if (start < 0 || stop < 0) { + /* only get the length for negative values */ + Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); + if (start < 0) start += len; + if (stop < 0) stop += len; + } + + if (stop - start <= 0) { + return PyList_New(0); + } + else { + return pyrna_prop_collection_subscript_slice(self, start, stop); + } + } + } #endif - else { - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key]: invalid key, " - "must be a string or an int, not %.200s", - Py_TYPE(key)->tp_name); - return -1; - } + else { + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key]: invalid key, " + "must be a string or an int, not %.200s", + Py_TYPE(key)->tp_name); + return -1; + } } static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject *key) { - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); #if 0 - if (PyUnicode_Check(key)) { - return pyrna_prop_array_subscript_str(self, _PyUnicode_AsString(key)); - } - else + if (PyUnicode_Check(key)) { + return pyrna_prop_array_subscript_str(self, _PyUnicode_AsString(key)); + } + else #endif - if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return NULL; - } - return pyrna_prop_array_subscript_int(self, i); - } - else if (PySlice_Check(key)) { - Py_ssize_t step = 1; - PySliceObject *key_slice = (PySliceObject *)key; - - if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { - return NULL; - } - else if (step != 1) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]: slice steps not supported"); - return NULL; - } - else if (key_slice->start == Py_None && key_slice->stop == Py_None) { - /* note, no significant advantage with optimizing [:] slice as with collections - * but include here for consistency with collection slice func */ - Py_ssize_t len = (Py_ssize_t)pyrna_prop_array_length(self); - return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len); - } - else { - int len = pyrna_prop_array_length(self); - Py_ssize_t start, stop, slicelength; - - if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { - return NULL; - } - - if (slicelength <= 0) { - return PyTuple_New(0); - } - else { - return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, start, stop, len); - } - } - } - else { - PyErr_SetString(PyExc_AttributeError, "bpy_prop_array[key]: invalid key, key must be an int"); - return NULL; - } + if (PyIndex_Check(key)) { + Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return NULL; + } + return pyrna_prop_array_subscript_int(self, i); + } + else if (PySlice_Check(key)) { + Py_ssize_t step = 1; + PySliceObject *key_slice = (PySliceObject *)key; + + if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { + return NULL; + } + else if (step != 1) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]: slice steps not supported"); + return NULL; + } + else if (key_slice->start == Py_None && key_slice->stop == Py_None) { + /* note, no significant advantage with optimizing [:] slice as with collections + * but include here for consistency with collection slice func */ + Py_ssize_t len = (Py_ssize_t)pyrna_prop_array_length(self); + return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len); + } + else { + int len = pyrna_prop_array_length(self); + Py_ssize_t start, stop, slicelength; + + if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { + return NULL; + } + + if (slicelength <= 0) { + return PyTuple_New(0); + } + else { + return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, start, stop, len); + } + } + } + else { + PyErr_SetString(PyExc_AttributeError, "bpy_prop_array[key]: invalid key, key must be an int"); + return NULL; + } } /** @@ -2847,1041 +2897,1043 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject static PyObject *prop_subscript_ass_array_slice__as_seq_fast(PyObject *value, int length) { - PyObject *value_fast; - if (!(value_fast = PySequence_Fast( - value, - "bpy_prop_array[slice] = value: " - "element in assignment is not a sequence type"))) - { - return NULL; - } - else if (PySequence_Fast_GET_SIZE(value_fast) != length) { - Py_DECREF(value_fast); - PyErr_SetString( - PyExc_ValueError, - "bpy_prop_array[slice] = value: " - "re-sizing bpy_struct element in arrays isn't supported"); - - return NULL; - } - else { - return value_fast; - } + PyObject *value_fast; + if (!(value_fast = PySequence_Fast(value, + "bpy_prop_array[slice] = value: " + "element in assignment is not a sequence type"))) { + return NULL; + } + else if (PySequence_Fast_GET_SIZE(value_fast) != length) { + Py_DECREF(value_fast); + PyErr_SetString(PyExc_ValueError, + "bpy_prop_array[slice] = value: " + "re-sizing bpy_struct element in arrays isn't supported"); + + return NULL; + } + else { + return value_fast; + } } static int prop_subscript_ass_array_slice__float_recursive( - PyObject **value_items, float *value, - int totdim, const int dimsize[], - const float range[2]) -{ - const int length = dimsize[0]; - if (totdim > 1) { - int index = 0; - int i; - for (i = 0; i != length; i++) { - PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); - if (UNLIKELY(subvalue == NULL)) { - return 0; - } - - index += prop_subscript_ass_array_slice__float_recursive( - PySequence_Fast_ITEMS(subvalue), &value[index], - totdim - 1, &dimsize[1], range); - - Py_DECREF(subvalue); - } - return index; - } - else { - BLI_assert(totdim == 1); - const float min = range[0], max = range[1]; - int i; - for (i = 0; i != length; i++) { - float v = PyFloat_AsDouble(value_items[i]); - CLAMP(v, min, max); - value[i] = v; - } - return i; - } + PyObject **value_items, float *value, int totdim, const int dimsize[], const float range[2]) +{ + const int length = dimsize[0]; + if (totdim > 1) { + int index = 0; + int i; + for (i = 0; i != length; i++) { + PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); + if (UNLIKELY(subvalue == NULL)) { + return 0; + } + + index += prop_subscript_ass_array_slice__float_recursive( + PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1], range); + + Py_DECREF(subvalue); + } + return index; + } + else { + BLI_assert(totdim == 1); + const float min = range[0], max = range[1]; + int i; + for (i = 0; i != length; i++) { + float v = PyFloat_AsDouble(value_items[i]); + CLAMP(v, min, max); + value[i] = v; + } + return i; + } } static int prop_subscript_ass_array_slice__int_recursive( - PyObject **value_items, int *value, - int totdim, const int dimsize[], - const int range[2]) -{ - const int length = dimsize[0]; - if (totdim > 1) { - int index = 0; - int i; - for (i = 0; i != length; i++) { - PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); - if (UNLIKELY(subvalue == NULL)) { - return 0; - } - - index += prop_subscript_ass_array_slice__int_recursive( - PySequence_Fast_ITEMS(subvalue), &value[index], - totdim - 1, &dimsize[1], range); - - Py_DECREF(subvalue); - } - return index; - } - else { - BLI_assert(totdim == 1); - const int min = range[0], max = range[1]; - int i; - for (i = 0; i != length; i++) { - int v = PyLong_AsLong(value_items[i]); - CLAMP(v, min, max); - value[i] = v; - } - return i; - } -} - -static int prop_subscript_ass_array_slice__bool_recursive( - PyObject **value_items, bool *value, - int totdim, const int dimsize[]) -{ - const int length = dimsize[0]; - if (totdim > 1) { - int index = 0; - int i; - for (i = 0; i != length; i++) { - PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); - if (UNLIKELY(subvalue == NULL)) { - return 0; - } - - index += prop_subscript_ass_array_slice__bool_recursive( - PySequence_Fast_ITEMS(subvalue), &value[index], - totdim - 1, &dimsize[1]); - - Py_DECREF(subvalue); - } - return index; - } - else { - BLI_assert(totdim == 1); - int i; - for (i = 0; i != length; i++) { - int v = PyLong_AsLong(value_items[i]); - value[i] = v; - } - return i; - } + PyObject **value_items, int *value, int totdim, const int dimsize[], const int range[2]) +{ + const int length = dimsize[0]; + if (totdim > 1) { + int index = 0; + int i; + for (i = 0; i != length; i++) { + PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); + if (UNLIKELY(subvalue == NULL)) { + return 0; + } + + index += prop_subscript_ass_array_slice__int_recursive( + PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1], range); + + Py_DECREF(subvalue); + } + return index; + } + else { + BLI_assert(totdim == 1); + const int min = range[0], max = range[1]; + int i; + for (i = 0; i != length; i++) { + int v = PyLong_AsLong(value_items[i]); + CLAMP(v, min, max); + value[i] = v; + } + return i; + } +} + +static int prop_subscript_ass_array_slice__bool_recursive(PyObject **value_items, + bool *value, + int totdim, + const int dimsize[]) +{ + const int length = dimsize[0]; + if (totdim > 1) { + int index = 0; + int i; + for (i = 0; i != length; i++) { + PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); + if (UNLIKELY(subvalue == NULL)) { + return 0; + } + + index += prop_subscript_ass_array_slice__bool_recursive( + PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1]); + + Py_DECREF(subvalue); + } + return index; + } + else { + BLI_assert(totdim == 1); + int i; + for (i = 0; i != length; i++) { + int v = PyLong_AsLong(value_items[i]); + value[i] = v; + } + return i; + } } /* could call (pyrna_py_to_prop_array_index(self, i, value) in a loop but it is slow */ -static int prop_subscript_ass_array_slice( - PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, - int start, int stop, int length, PyObject *value_orig) -{ - const int length_flat = RNA_property_array_length(ptr, prop); - PyObject *value; - PyObject **value_items; - void *values_alloc = NULL; - int ret = 0; - - if (value_orig == NULL) { - PyErr_SetString(PyExc_TypeError, - "bpy_prop_array[slice] = value: deleting with list types is not supported by bpy_struct"); - return -1; - } - - if (!(value = PySequence_Fast(value_orig, "bpy_prop_array[slice] = value: assignment is not a sequence type"))) { - return -1; - } - - if (PySequence_Fast_GET_SIZE(value) != stop - start) { - Py_DECREF(value); - PyErr_SetString(PyExc_TypeError, - "bpy_prop_array[slice] = value: re-sizing bpy_struct arrays isn't supported"); - return -1; - } - - int dimsize[3]; - int totdim = RNA_property_array_dimension(ptr, prop, dimsize); - if (totdim > 1) { - BLI_assert(dimsize[arraydim] == length); - } - - int span = 1; - if (totdim > 1) { - for (int i = arraydim + 1; i < totdim; i++) { - span *= dimsize[i]; - } - } - - value_items = PySequence_Fast_ITEMS(value); - switch (RNA_property_type(prop)) { - case PROP_FLOAT: - { - float values_stack[PYRNA_STACK_ARRAY]; - float *values = (length_flat > PYRNA_STACK_ARRAY) ? - (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) : values_stack; - if (start != 0 || stop != length) { - /* partial assignment? - need to get the array */ - RNA_property_float_get_array(ptr, prop, values); - } - - float range[2]; - RNA_property_float_range(ptr, prop, &range[0], &range[1]); - - dimsize[arraydim] = stop - start; - prop_subscript_ass_array_slice__float_recursive( - value_items, &values[arrayoffset + (start * span)], - totdim - arraydim, &dimsize[arraydim], - range); - - if (PyErr_Occurred()) { - ret = -1; - } - else { - RNA_property_float_set_array(ptr, prop, values); - } - break; - } - case PROP_INT: - { - int values_stack[PYRNA_STACK_ARRAY]; - int *values = (length_flat > PYRNA_STACK_ARRAY) ? - (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) : values_stack; - if (start != 0 || stop != length) { - /* partial assignment? - need to get the array */ - RNA_property_int_get_array(ptr, prop, values); - } - - int range[2]; - RNA_property_int_range(ptr, prop, &range[0], &range[1]); - - dimsize[arraydim] = stop - start; - prop_subscript_ass_array_slice__int_recursive( - value_items, &values[arrayoffset + (start * span)], - totdim - arraydim, &dimsize[arraydim], - range); - - if (PyErr_Occurred()) { - ret = -1; - } - else { - RNA_property_int_set_array(ptr, prop, values); - } - break; - } - case PROP_BOOLEAN: - { - bool values_stack[PYRNA_STACK_ARRAY]; - bool *values = (length_flat > PYRNA_STACK_ARRAY) ? - (values_alloc = PyMem_MALLOC(sizeof(bool) * length_flat)) : values_stack; - - if (start != 0 || stop != length) { - /* partial assignment? - need to get the array */ - RNA_property_boolean_get_array(ptr, prop, values); - } - - dimsize[arraydim] = stop - start; - prop_subscript_ass_array_slice__bool_recursive( - value_items, &values[arrayoffset + (start * span)], - totdim - arraydim, &dimsize[arraydim]); - - if (PyErr_Occurred()) { - ret = -1; - } - else { - RNA_property_boolean_set_array(ptr, prop, values); - } - break; - } - default: - PyErr_SetString(PyExc_TypeError, "not an array type"); - ret = -1; - break; - } - - Py_DECREF(value); - - if (values_alloc) { - PyMem_FREE(values_alloc); - } - - return ret; - -} - -static int prop_subscript_ass_array_int(BPy_PropertyArrayRNA *self, Py_ssize_t keynum, PyObject *value) -{ - int len; - - PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); - - len = pyrna_prop_array_length(self); - - if (keynum < 0) { - keynum += len; - } - - if (keynum >= 0 && keynum < len) { - return pyrna_py_to_prop_array_index(self, keynum, value); - } - - PyErr_SetString(PyExc_IndexError, - "bpy_prop_array[index] = value: index out of range"); - return -1; -} - -static int pyrna_prop_array_ass_subscript(BPy_PropertyArrayRNA *self, PyObject *key, PyObject *value) -{ - /* char *keyname = NULL; */ /* not supported yet */ - int ret = -1; - - PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); - - if (!RNA_property_editable_flag(&self->ptr, self->prop)) { - PyErr_Format(PyExc_AttributeError, - "bpy_prop_collection: attribute \"%.200s\" from \"%.200s\" is read-only", - RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type)); - ret = -1; - } - - else if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - ret = -1; - } - else { - ret = prop_subscript_ass_array_int(self, i, value); - } - } - else if (PySlice_Check(key)) { - Py_ssize_t len = pyrna_prop_array_length(self); - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { - ret = -1; - } - else if (slicelength <= 0) { - ret = 0; /* do nothing */ - } - else if (step == 1) { - ret = prop_subscript_ass_array_slice( - &self->ptr, self->prop, self->arraydim, self->arrayoffset, - start, stop, len, value); - } - else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); - ret = -1; - } - } - else { - PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int"); - ret = -1; - } - - if (ret != -1) { - if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); - } - } - - return ret; +static int prop_subscript_ass_array_slice(PointerRNA *ptr, + PropertyRNA *prop, + int arraydim, + int arrayoffset, + int start, + int stop, + int length, + PyObject *value_orig) +{ + const int length_flat = RNA_property_array_length(ptr, prop); + PyObject *value; + PyObject **value_items; + void *values_alloc = NULL; + int ret = 0; + + if (value_orig == NULL) { + PyErr_SetString( + PyExc_TypeError, + "bpy_prop_array[slice] = value: deleting with list types is not supported by bpy_struct"); + return -1; + } + + if (!(value = PySequence_Fast( + value_orig, "bpy_prop_array[slice] = value: assignment is not a sequence type"))) { + return -1; + } + + if (PySequence_Fast_GET_SIZE(value) != stop - start) { + Py_DECREF(value); + PyErr_SetString(PyExc_TypeError, + "bpy_prop_array[slice] = value: re-sizing bpy_struct arrays isn't supported"); + return -1; + } + + int dimsize[3]; + int totdim = RNA_property_array_dimension(ptr, prop, dimsize); + if (totdim > 1) { + BLI_assert(dimsize[arraydim] == length); + } + + int span = 1; + if (totdim > 1) { + for (int i = arraydim + 1; i < totdim; i++) { + span *= dimsize[i]; + } + } + + value_items = PySequence_Fast_ITEMS(value); + switch (RNA_property_type(prop)) { + case PROP_FLOAT: { + float values_stack[PYRNA_STACK_ARRAY]; + float *values = (length_flat > PYRNA_STACK_ARRAY) ? + (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) : + values_stack; + if (start != 0 || stop != length) { + /* partial assignment? - need to get the array */ + RNA_property_float_get_array(ptr, prop, values); + } + + float range[2]; + RNA_property_float_range(ptr, prop, &range[0], &range[1]); + + dimsize[arraydim] = stop - start; + prop_subscript_ass_array_slice__float_recursive(value_items, + &values[arrayoffset + (start * span)], + totdim - arraydim, + &dimsize[arraydim], + range); + + if (PyErr_Occurred()) { + ret = -1; + } + else { + RNA_property_float_set_array(ptr, prop, values); + } + break; + } + case PROP_INT: { + int values_stack[PYRNA_STACK_ARRAY]; + int *values = (length_flat > PYRNA_STACK_ARRAY) ? + (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) : + values_stack; + if (start != 0 || stop != length) { + /* partial assignment? - need to get the array */ + RNA_property_int_get_array(ptr, prop, values); + } + + int range[2]; + RNA_property_int_range(ptr, prop, &range[0], &range[1]); + + dimsize[arraydim] = stop - start; + prop_subscript_ass_array_slice__int_recursive(value_items, + &values[arrayoffset + (start * span)], + totdim - arraydim, + &dimsize[arraydim], + range); + + if (PyErr_Occurred()) { + ret = -1; + } + else { + RNA_property_int_set_array(ptr, prop, values); + } + break; + } + case PROP_BOOLEAN: { + bool values_stack[PYRNA_STACK_ARRAY]; + bool *values = (length_flat > PYRNA_STACK_ARRAY) ? + (values_alloc = PyMem_MALLOC(sizeof(bool) * length_flat)) : + values_stack; + + if (start != 0 || stop != length) { + /* partial assignment? - need to get the array */ + RNA_property_boolean_get_array(ptr, prop, values); + } + + dimsize[arraydim] = stop - start; + prop_subscript_ass_array_slice__bool_recursive(value_items, + &values[arrayoffset + (start * span)], + totdim - arraydim, + &dimsize[arraydim]); + + if (PyErr_Occurred()) { + ret = -1; + } + else { + RNA_property_boolean_set_array(ptr, prop, values); + } + break; + } + default: + PyErr_SetString(PyExc_TypeError, "not an array type"); + ret = -1; + break; + } + + Py_DECREF(value); + + if (values_alloc) { + PyMem_FREE(values_alloc); + } + + return ret; +} + +static int prop_subscript_ass_array_int(BPy_PropertyArrayRNA *self, + Py_ssize_t keynum, + PyObject *value) +{ + int len; + + PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); + + len = pyrna_prop_array_length(self); + + if (keynum < 0) { + keynum += len; + } + + if (keynum >= 0 && keynum < len) { + return pyrna_py_to_prop_array_index(self, keynum, value); + } + + PyErr_SetString(PyExc_IndexError, "bpy_prop_array[index] = value: index out of range"); + return -1; +} + +static int pyrna_prop_array_ass_subscript(BPy_PropertyArrayRNA *self, + PyObject *key, + PyObject *value) +{ + /* char *keyname = NULL; */ /* not supported yet */ + int ret = -1; + + PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); + + if (!RNA_property_editable_flag(&self->ptr, self->prop)) { + PyErr_Format(PyExc_AttributeError, + "bpy_prop_collection: attribute \"%.200s\" from \"%.200s\" is read-only", + RNA_property_identifier(self->prop), + RNA_struct_identifier(self->ptr.type)); + ret = -1; + } + + else if (PyIndex_Check(key)) { + Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + ret = -1; + } + else { + ret = prop_subscript_ass_array_int(self, i, value); + } + } + else if (PySlice_Check(key)) { + Py_ssize_t len = pyrna_prop_array_length(self); + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { + ret = -1; + } + else if (slicelength <= 0) { + ret = 0; /* do nothing */ + } + else if (step == 1) { + ret = prop_subscript_ass_array_slice( + &self->ptr, self->prop, self->arraydim, self->arrayoffset, start, stop, len, value); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); + ret = -1; + } + } + else { + PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int"); + ret = -1; + } + + if (ret != -1) { + if (RNA_property_update_check(self->prop)) { + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + } + } + + return ret; } /* for slice only */ static PyMappingMethods pyrna_prop_array_as_mapping = { - (lenfunc) pyrna_prop_array_length, /* mp_length */ - (binaryfunc) pyrna_prop_array_subscript, /* mp_subscript */ - (objobjargproc) pyrna_prop_array_ass_subscript, /* mp_ass_subscript */ + (lenfunc)pyrna_prop_array_length, /* mp_length */ + (binaryfunc)pyrna_prop_array_subscript, /* mp_subscript */ + (objobjargproc)pyrna_prop_array_ass_subscript, /* mp_ass_subscript */ }; static PyMappingMethods pyrna_prop_collection_as_mapping = { - (lenfunc) pyrna_prop_collection_length, /* mp_length */ - (binaryfunc) pyrna_prop_collection_subscript, /* mp_subscript */ - (objobjargproc) pyrna_prop_collection_ass_subscript, /* mp_ass_subscript */ + (lenfunc)pyrna_prop_collection_length, /* mp_length */ + (binaryfunc)pyrna_prop_collection_subscript, /* mp_subscript */ + (objobjargproc)pyrna_prop_collection_ass_subscript, /* mp_ass_subscript */ }; /* only for fast bool's, large structs, assign nb_bool on init */ static PyNumberMethods pyrna_prop_array_as_number = { - NULL, /* nb_add */ - NULL, /* nb_subtract */ - NULL, /* nb_multiply */ - NULL, /* nb_remainder */ - NULL, /* nb_divmod */ - NULL, /* nb_power */ - NULL, /* nb_negative */ - NULL, /* nb_positive */ - NULL, /* nb_absolute */ - (inquiry) pyrna_prop_array_bool, /* nb_bool */ + NULL, /* nb_add */ + NULL, /* nb_subtract */ + NULL, /* nb_multiply */ + NULL, /* nb_remainder */ + NULL, /* nb_divmod */ + NULL, /* nb_power */ + NULL, /* nb_negative */ + NULL, /* nb_positive */ + NULL, /* nb_absolute */ + (inquiry)pyrna_prop_array_bool, /* nb_bool */ }; static PyNumberMethods pyrna_prop_collection_as_number = { - NULL, /* nb_add */ - NULL, /* nb_subtract */ - NULL, /* nb_multiply */ - NULL, /* nb_remainder */ - NULL, /* nb_divmod */ - NULL, /* nb_power */ - NULL, /* nb_negative */ - NULL, /* nb_positive */ - NULL, /* nb_absolute */ - (inquiry) pyrna_prop_collection_bool, /* nb_bool */ + NULL, /* nb_add */ + NULL, /* nb_subtract */ + NULL, /* nb_multiply */ + NULL, /* nb_remainder */ + NULL, /* nb_divmod */ + NULL, /* nb_power */ + NULL, /* nb_negative */ + NULL, /* nb_positive */ + NULL, /* nb_absolute */ + (inquiry)pyrna_prop_collection_bool, /* nb_bool */ }; static int pyrna_prop_array_contains(BPy_PropertyRNA *self, PyObject *value) { - return pyrna_array_contains_py(&self->ptr, self->prop, value); + return pyrna_array_contains_py(&self->ptr, self->prop, value); } static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *key) { - PointerRNA newptr; /* not used, just so RNA_property_collection_lookup_string runs */ + PointerRNA newptr; /* not used, just so RNA_property_collection_lookup_string runs */ - if (PyTuple_Check(key)) { - /* special case, for ID datablocks we */ - return pyrna_prop_collection_subscript_str_lib_pair_ptr(self, key, - "(id, lib) in bpy_prop_collection", false, NULL); - } - else { + if (PyTuple_Check(key)) { + /* special case, for ID datablocks we */ + return pyrna_prop_collection_subscript_str_lib_pair_ptr( + self, key, "(id, lib) in bpy_prop_collection", false, NULL); + } + else { - /* key in dict style check */ - const char *keyname = _PyUnicode_AsString(key); + /* key in dict style check */ + const char *keyname = _PyUnicode_AsString(key); - if (keyname == NULL) { - PyErr_SetString(PyExc_TypeError, - "bpy_prop_collection.__contains__: expected a string or a tuple of strings"); - return -1; - } + if (keyname == NULL) { + PyErr_SetString(PyExc_TypeError, + "bpy_prop_collection.__contains__: expected a string or a tuple of strings"); + return -1; + } - if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) { - return 1; - } + if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) { + return 1; + } - return 0; - } + return 0; + } } static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value) { - IDProperty *group; - const char *name = _PyUnicode_AsString(value); + IDProperty *group; + const char *name = _PyUnicode_AsString(value); - PYRNA_STRUCT_CHECK_INT(self); + PYRNA_STRUCT_CHECK_INT(self); - if (!name) { - PyErr_SetString(PyExc_TypeError, "bpy_struct.__contains__: expected a string"); - return -1; - } + if (!name) { + PyErr_SetString(PyExc_TypeError, "bpy_struct.__contains__: expected a string"); + return -1; + } - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "bpy_struct: this type doesn't support IDProperties"); - return -1; - } + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "bpy_struct: this type doesn't support IDProperties"); + return -1; + } - group = RNA_struct_idprops(&self->ptr, 0); + group = RNA_struct_idprops(&self->ptr, 0); - if (!group) { - return 0; - } + if (!group) { + return 0; + } - return IDP_GetPropertyFromGroup(group, name) ? 1 : 0; + return IDP_GetPropertyFromGroup(group, name) ? 1 : 0; } static PySequenceMethods pyrna_prop_array_as_sequence = { - (lenfunc)pyrna_prop_array_length, - NULL, /* sq_concat */ - NULL, /* sq_repeat */ - (ssizeargfunc)pyrna_prop_array_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */ - NULL, /* sq_slice */ - (ssizeobjargproc)prop_subscript_ass_array_int, /* sq_ass_item */ - NULL, /* *was* sq_ass_slice */ - (objobjproc)pyrna_prop_array_contains, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + (lenfunc)pyrna_prop_array_length, + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + (ssizeargfunc)pyrna_prop_array_subscript_int, + /* sq_item */ /* Only set this so PySequence_Check() returns True */ + NULL, /* sq_slice */ + (ssizeobjargproc)prop_subscript_ass_array_int, /* sq_ass_item */ + NULL, /* *was* sq_ass_slice */ + (objobjproc)pyrna_prop_array_contains, /* sq_contains */ + (binaryfunc)NULL, /* sq_inplace_concat */ + (ssizeargfunc)NULL, /* sq_inplace_repeat */ }; static PySequenceMethods pyrna_prop_collection_as_sequence = { - (lenfunc)pyrna_prop_collection_length, - NULL, /* sq_concat */ - NULL, /* sq_repeat */ - (ssizeargfunc)pyrna_prop_collection_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */ - NULL, /* *was* sq_slice */ - (ssizeobjargproc)/* pyrna_prop_collection_ass_subscript_int */ NULL /* let mapping take this one */, /* sq_ass_item */ - NULL, /* *was* sq_ass_slice */ - (objobjproc)pyrna_prop_collection_contains, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + (lenfunc)pyrna_prop_collection_length, + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + (ssizeargfunc)pyrna_prop_collection_subscript_int, + /* sq_item */ /* Only set this so PySequence_Check() returns True */ + NULL, /* *was* sq_slice */ + (ssizeobjargproc) /* pyrna_prop_collection_ass_subscript_int */ + NULL /* let mapping take this one */, /* sq_ass_item */ + NULL, /* *was* sq_ass_slice */ + (objobjproc)pyrna_prop_collection_contains, /* sq_contains */ + (binaryfunc)NULL, /* sq_inplace_concat */ + (ssizeargfunc)NULL, /* sq_inplace_repeat */ }; static PySequenceMethods pyrna_struct_as_sequence = { - NULL, /* Cant set the len otherwise it can evaluate as false */ - NULL, /* sq_concat */ - NULL, /* sq_repeat */ - NULL, /* sq_item */ /* Only set this so PySequence_Check() returns True */ - NULL, /* *was* sq_slice */ - NULL, /* sq_ass_item */ - NULL, /* *was* sq_ass_slice */ - (objobjproc)pyrna_struct_contains, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + NULL, /* Cant set the len otherwise it can evaluate as false */ + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + NULL, + /* sq_item */ /* Only set this so PySequence_Check() returns True */ + NULL, /* *was* sq_slice */ + NULL, /* sq_ass_item */ + NULL, /* *was* sq_ass_slice */ + (objobjproc)pyrna_struct_contains, /* sq_contains */ + (binaryfunc)NULL, /* sq_inplace_concat */ + (ssizeargfunc)NULL, /* sq_inplace_repeat */ }; static PyObject *pyrna_struct_subscript(BPy_StructRNA *self, PyObject *key) { - /* mostly copied from BPy_IDGroup_Map_GetItem */ - IDProperty *group, *idprop; - const char *name = _PyUnicode_AsString(key); + /* mostly copied from BPy_IDGroup_Map_GetItem */ + IDProperty *group, *idprop; + const char *name = _PyUnicode_AsString(key); - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); - return NULL; - } + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); + return NULL; + } - if (name == NULL) { - PyErr_SetString(PyExc_TypeError, "bpy_struct[key]: only strings are allowed as keys of ID properties"); - return NULL; - } + if (name == NULL) { + PyErr_SetString(PyExc_TypeError, + "bpy_struct[key]: only strings are allowed as keys of ID properties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); + group = RNA_struct_idprops(&self->ptr, 0); - if (group == NULL) { - PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); - return NULL; - } + if (group == NULL) { + PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); + return NULL; + } - idprop = IDP_GetPropertyFromGroup(group, name); + idprop = IDP_GetPropertyFromGroup(group, name); - if (idprop == NULL) { - PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); - return NULL; - } + if (idprop == NULL) { + PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); + return NULL; + } - return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); + return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); } static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObject *value) { - IDProperty *group; + IDProperty *group; - PYRNA_STRUCT_CHECK_INT(self); + PYRNA_STRUCT_CHECK_INT(self); - group = RNA_struct_idprops(&self->ptr, 1); + group = RNA_struct_idprops(&self->ptr, 1); #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, key)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ - - if (group == NULL) { - PyErr_SetString(PyExc_TypeError, "bpy_struct[key] = val: id properties not supported for this type"); - return -1; - } - - if (value && BPy_StructRNA_Check(value)) { - BPy_StructRNA *val = (BPy_StructRNA *)value; - if (val && self->ptr.type && val->ptr.type) { - if (!RNA_struct_idprops_datablock_allowed(self->ptr.type) && - RNA_struct_idprops_contains_datablock(val->ptr.type)) - { - PyErr_SetString( - PyExc_TypeError, - "bpy_struct[key] = val: datablock id properties not supported for this type"); - return -1; - } - } - } - - return BPy_Wrap_SetMapItem(group, key, value); + if (rna_disallow_writes && rna_id_write_error(&self->ptr, key)) { + return -1; + } +#endif /* USE_PEDANTIC_WRITE */ + + if (group == NULL) { + PyErr_SetString(PyExc_TypeError, + "bpy_struct[key] = val: id properties not supported for this type"); + return -1; + } + + if (value && BPy_StructRNA_Check(value)) { + BPy_StructRNA *val = (BPy_StructRNA *)value; + if (val && self->ptr.type && val->ptr.type) { + if (!RNA_struct_idprops_datablock_allowed(self->ptr.type) && + RNA_struct_idprops_contains_datablock(val->ptr.type)) { + PyErr_SetString( + PyExc_TypeError, + "bpy_struct[key] = val: datablock id properties not supported for this type"); + return -1; + } + } + } + + return BPy_Wrap_SetMapItem(group, key, value); } static PyMappingMethods pyrna_struct_as_mapping = { - (lenfunc) NULL, /* mp_length */ - (binaryfunc) pyrna_struct_subscript, /* mp_subscript */ - (objobjargproc) pyrna_struct_ass_subscript, /* mp_ass_subscript */ + (lenfunc)NULL, /* mp_length */ + (binaryfunc)pyrna_struct_subscript, /* mp_subscript */ + (objobjargproc)pyrna_struct_ass_subscript, /* mp_ass_subscript */ }; PyDoc_STRVAR(pyrna_struct_keys_doc, -".. method:: keys()\n" -"\n" -" Returns the keys of this objects custom properties (matches pythons\n" -" dictionary function of the same name).\n" -"\n" -" :return: custom property keys.\n" -" :rtype: list of strings\n" -"\n" -BPY_DOC_ID_PROP_TYPE_NOTE -); + ".. method:: keys()\n" + "\n" + " Returns the keys of this objects custom properties (matches pythons\n" + " dictionary function of the same name).\n" + "\n" + " :return: custom property keys.\n" + " :rtype: list of strings\n" + "\n" BPY_DOC_ID_PROP_TYPE_NOTE); static PyObject *pyrna_struct_keys(BPy_PropertyRNA *self) { - IDProperty *group; + IDProperty *group; - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "bpy_struct.keys(): this type doesn't support IDProperties"); - return NULL; - } + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "bpy_struct.keys(): this type doesn't support IDProperties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); + group = RNA_struct_idprops(&self->ptr, 0); - if (group == NULL) { - return PyList_New(0); - } + if (group == NULL) { + return PyList_New(0); + } - return BPy_Wrap_GetKeys(group); + return BPy_Wrap_GetKeys(group); } PyDoc_STRVAR(pyrna_struct_items_doc, -".. method:: items()\n" -"\n" -" Returns the items of this objects custom properties (matches pythons\n" -" dictionary function of the same name).\n" -"\n" -" :return: custom property key, value pairs.\n" -" :rtype: list of key, value tuples\n" -"\n" -BPY_DOC_ID_PROP_TYPE_NOTE -); + ".. method:: items()\n" + "\n" + " Returns the items of this objects custom properties (matches pythons\n" + " dictionary function of the same name).\n" + "\n" + " :return: custom property key, value pairs.\n" + " :rtype: list of key, value tuples\n" + "\n" BPY_DOC_ID_PROP_TYPE_NOTE); static PyObject *pyrna_struct_items(BPy_PropertyRNA *self) { - IDProperty *group; + IDProperty *group; - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "bpy_struct.items(): this type doesn't support IDProperties"); - return NULL; - } + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "bpy_struct.items(): this type doesn't support IDProperties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); + group = RNA_struct_idprops(&self->ptr, 0); - if (group == NULL) { - return PyList_New(0); - } + if (group == NULL) { + return PyList_New(0); + } - return BPy_Wrap_GetItems(self->ptr.id.data, group); + return BPy_Wrap_GetItems(self->ptr.id.data, group); } PyDoc_STRVAR(pyrna_struct_values_doc, -".. method:: values()\n" -"\n" -" Returns the values of this objects custom properties (matches pythons\n" -" dictionary function of the same name).\n" -"\n" -" :return: custom property values.\n" -" :rtype: list\n" -"\n" -BPY_DOC_ID_PROP_TYPE_NOTE -); + ".. method:: values()\n" + "\n" + " Returns the values of this objects custom properties (matches pythons\n" + " dictionary function of the same name).\n" + "\n" + " :return: custom property values.\n" + " :rtype: list\n" + "\n" BPY_DOC_ID_PROP_TYPE_NOTE); static PyObject *pyrna_struct_values(BPy_PropertyRNA *self) { - IDProperty *group; + IDProperty *group; - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "bpy_struct.values(): this type doesn't support IDProperties"); - return NULL; - } + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, + "bpy_struct.values(): this type doesn't support IDProperties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); + group = RNA_struct_idprops(&self->ptr, 0); - if (group == NULL) { - return PyList_New(0); - } + if (group == NULL) { + return PyList_New(0); + } - return BPy_Wrap_GetValues(self->ptr.id.data, group); + return BPy_Wrap_GetValues(self->ptr.id.data, group); } - PyDoc_STRVAR(pyrna_struct_is_property_set_doc, -".. method:: is_property_set(property)\n" -"\n" -" Check if a property is set, use for testing operator properties.\n" -"\n" -" :return: True when the property has been set.\n" -" :rtype: boolean\n" -); + ".. method:: is_property_set(property)\n" + "\n" + " Check if a property is set, use for testing operator properties.\n" + "\n" + " :return: True when the property has been set.\n" + " :rtype: boolean\n"); static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; + PropertyRNA *prop; + const char *name; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:is_property_set", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:is_property_set", &name)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.is_property_set(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.is_property_set(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - return PyBool_FromLong(RNA_property_is_set(&self->ptr, prop)); + return PyBool_FromLong(RNA_property_is_set(&self->ptr, prop)); } PyDoc_STRVAR(pyrna_struct_property_unset_doc, -".. method:: property_unset(property)\n" -"\n" -" Unset a property, will use default value afterward.\n" -); + ".. method:: property_unset(property)\n" + "\n" + " Unset a property, will use default value afterward.\n"); static PyObject *pyrna_struct_property_unset(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; + PropertyRNA *prop; + const char *name; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:property_unset", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:property_unset", &name)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.property_unset(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.property_unset(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - RNA_property_unset(&self->ptr, prop); + RNA_property_unset(&self->ptr, prop); - Py_RETURN_NONE; + Py_RETURN_NONE; } PyDoc_STRVAR(pyrna_struct_is_property_hidden_doc, -".. method:: is_property_hidden(property)\n" -"\n" -" Check if a property is hidden.\n" -"\n" -" :return: True when the property is hidden.\n" -" :rtype: boolean\n" -); + ".. method:: is_property_hidden(property)\n" + "\n" + " Check if a property is hidden.\n" + "\n" + " :return: True when the property is hidden.\n" + " :rtype: boolean\n"); static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; + PropertyRNA *prop; + const char *name; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:is_property_hidden", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:is_property_hidden", &name)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.is_property_hidden(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.is_property_hidden(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - return PyBool_FromLong(RNA_property_flag(prop) & PROP_HIDDEN); + return PyBool_FromLong(RNA_property_flag(prop) & PROP_HIDDEN); } PyDoc_STRVAR(pyrna_struct_is_property_readonly_doc, -".. method:: is_property_readonly(property)\n" -"\n" -" Check if a property is readonly.\n" -"\n" -" :return: True when the property is readonly (not writable).\n" -" :rtype: boolean\n" -); + ".. method:: is_property_readonly(property)\n" + "\n" + " Check if a property is readonly.\n" + "\n" + " :return: True when the property is readonly (not writable).\n" + " :rtype: boolean\n"); static PyObject *pyrna_struct_is_property_readonly(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; + PropertyRNA *prop; + const char *name; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:is_property_readonly", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:is_property_readonly", &name)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.is_property_readonly(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.is_property_readonly(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - return PyBool_FromLong(!RNA_property_editable(&self->ptr, prop)); + return PyBool_FromLong(!RNA_property_editable(&self->ptr, prop)); } - PyDoc_STRVAR(pyrna_struct_is_property_overridable_static_doc, -".. method:: is_property_overridable_static(property)\n" -"\n" -" Check if a property is statically overridable.\n" -"\n" -" :return: True when the property is statically overridable.\n" -" :rtype: boolean\n" -); + ".. method:: is_property_overridable_static(property)\n" + "\n" + " Check if a property is statically overridable.\n" + "\n" + " :return: True when the property is statically overridable.\n" + " :rtype: boolean\n"); static PyObject *pyrna_struct_is_property_overridable_static(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; + PropertyRNA *prop; + const char *name; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:is_property_overridable_static", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:is_property_overridable_static", &name)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.is_property_overridable_static(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.is_property_overridable_static(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - return PyBool_FromLong((long)RNA_property_overridable_get(&self->ptr, prop)); + return PyBool_FromLong((long)RNA_property_overridable_get(&self->ptr, prop)); } -PyDoc_STRVAR(pyrna_struct_property_overridable_static_set_doc, -".. method:: property_overridable_static_set(property)\n" -"\n" -" Define a property as statically overridable or not (only for custom properties!).\n" -"\n" -" :return: True when the overridable status of the property was successfully set.\n" -" :rtype: boolean\n" -); +PyDoc_STRVAR( + pyrna_struct_property_overridable_static_set_doc, + ".. method:: property_overridable_static_set(property)\n" + "\n" + " Define a property as statically overridable or not (only for custom properties!).\n" + "\n" + " :return: True when the overridable status of the property was successfully set.\n" + " :rtype: boolean\n"); static PyObject *pyrna_struct_property_overridable_static_set(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; - int is_overridable; + PropertyRNA *prop; + const char *name; + int is_overridable; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "sp:property_overridable_static_set", &name, &is_overridable)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "sp:property_overridable_static_set", &name, &is_overridable)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.property_overridable_static_set(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.property_overridable_static_set(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - return PyBool_FromLong((long)RNA_property_overridable_static_set(&self->ptr, prop, (bool)is_overridable)); + return PyBool_FromLong( + (long)RNA_property_overridable_static_set(&self->ptr, prop, (bool)is_overridable)); } - - PyDoc_STRVAR(pyrna_struct_path_resolve_doc, -".. method:: path_resolve(path, coerce=True)\n" -"\n" -" Returns the property from the path, raise an exception when not found.\n" -"\n" -" :arg path: path which this property resolves.\n" -" :type path: string\n" -" :arg coerce: optional argument, when True, the property will be converted\n" -" into its python representation.\n" -" :type coerce: boolean\n" -); + ".. method:: path_resolve(path, coerce=True)\n" + "\n" + " Returns the property from the path, raise an exception when not found.\n" + "\n" + " :arg path: path which this property resolves.\n" + " :type path: string\n" + " :arg coerce: optional argument, when True, the property will be converted\n" + " into its python representation.\n" + " :type coerce: boolean\n"); static PyObject *pyrna_struct_path_resolve(BPy_StructRNA *self, PyObject *args) { - const char *path; - PyObject *coerce = Py_True; - PointerRNA r_ptr; - PropertyRNA *r_prop; - int index = -1; - - PYRNA_STRUCT_CHECK_OBJ(self); - - if (!PyArg_ParseTuple(args, "s|O!:path_resolve", &path, &PyBool_Type, &coerce)) { - return NULL; - } - - if (RNA_path_resolve_full(&self->ptr, path, &r_ptr, &r_prop, &index)) { - if (r_prop) { - if (index != -1) { - if (index >= RNA_property_array_length(&r_ptr, r_prop) || index < 0) { - PyErr_Format(PyExc_IndexError, - "%.200s.path_resolve(\"%.200s\") index out of range", - RNA_struct_identifier(self->ptr.type), path); - return NULL; - } - else { - return pyrna_array_index(&r_ptr, r_prop, index); - } - } - else { - if (coerce == Py_False) { - return pyrna_prop_CreatePyObject(&r_ptr, r_prop); - } - else { - return pyrna_prop_to_py(&r_ptr, r_prop); - } - } - } - else { - return pyrna_struct_CreatePyObject(&r_ptr); - } - } - else { - PyErr_Format(PyExc_ValueError, - "%.200s.path_resolve(\"%.200s\") could not be resolved", - RNA_struct_identifier(self->ptr.type), path); - return NULL; - } + const char *path; + PyObject *coerce = Py_True; + PointerRNA r_ptr; + PropertyRNA *r_prop; + int index = -1; + + PYRNA_STRUCT_CHECK_OBJ(self); + + if (!PyArg_ParseTuple(args, "s|O!:path_resolve", &path, &PyBool_Type, &coerce)) { + return NULL; + } + + if (RNA_path_resolve_full(&self->ptr, path, &r_ptr, &r_prop, &index)) { + if (r_prop) { + if (index != -1) { + if (index >= RNA_property_array_length(&r_ptr, r_prop) || index < 0) { + PyErr_Format(PyExc_IndexError, + "%.200s.path_resolve(\"%.200s\") index out of range", + RNA_struct_identifier(self->ptr.type), + path); + return NULL; + } + else { + return pyrna_array_index(&r_ptr, r_prop, index); + } + } + else { + if (coerce == Py_False) { + return pyrna_prop_CreatePyObject(&r_ptr, r_prop); + } + else { + return pyrna_prop_to_py(&r_ptr, r_prop); + } + } + } + else { + return pyrna_struct_CreatePyObject(&r_ptr); + } + } + else { + PyErr_Format(PyExc_ValueError, + "%.200s.path_resolve(\"%.200s\") could not be resolved", + RNA_struct_identifier(self->ptr.type), + path); + return NULL; + } } PyDoc_STRVAR(pyrna_struct_path_from_id_doc, -".. method:: path_from_id(property=\"\")\n" -"\n" -" Returns the data path from the ID to this object (string).\n" -"\n" -" :arg property: Optional property name which can be used if the path is\n" -" to a property of this object.\n" -" :type property: string\n" -" :return: The path from :class:`bpy.types.bpy_struct.id_data`\n" -" to this struct and property (when given).\n" -" :rtype: str\n" -); + ".. method:: path_from_id(property=\"\")\n" + "\n" + " Returns the data path from the ID to this object (string).\n" + "\n" + " :arg property: Optional property name which can be used if the path is\n" + " to a property of this object.\n" + " :type property: string\n" + " :return: The path from :class:`bpy.types.bpy_struct.id_data`\n" + " to this struct and property (when given).\n" + " :rtype: str\n"); static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args) { - const char *name = NULL; - const char *path; - PropertyRNA *prop; - PyObject *ret; - - PYRNA_STRUCT_CHECK_OBJ(self); - - if (!PyArg_ParseTuple(args, "|s:path_from_id", &name)) { - return NULL; - } - - if (name) { - prop = RNA_struct_find_property(&self->ptr, name); - if (prop == NULL) { - PyErr_Format(PyExc_AttributeError, - "%.200s.path_from_id(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } - - path = RNA_path_from_ID_to_property(&self->ptr, prop); - } - else { - path = RNA_path_from_ID_to_struct(&self->ptr); - } - - if (path == NULL) { - if (name) { - PyErr_Format(PyExc_ValueError, - "%.200s.path_from_id(\"%s\") found but does not support path creation", - RNA_struct_identifier(self->ptr.type), name); - } - else { - PyErr_Format(PyExc_ValueError, - "%.200s.path_from_id() does not support path creation for this type", - RNA_struct_identifier(self->ptr.type)); - } - return NULL; - } - - ret = PyUnicode_FromString(path); - MEM_freeN((void *)path); - - return ret; + const char *name = NULL; + const char *path; + PropertyRNA *prop; + PyObject *ret; + + PYRNA_STRUCT_CHECK_OBJ(self); + + if (!PyArg_ParseTuple(args, "|s:path_from_id", &name)) { + return NULL; + } + + if (name) { + prop = RNA_struct_find_property(&self->ptr, name); + if (prop == NULL) { + PyErr_Format(PyExc_AttributeError, + "%.200s.path_from_id(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } + + path = RNA_path_from_ID_to_property(&self->ptr, prop); + } + else { + path = RNA_path_from_ID_to_struct(&self->ptr); + } + + if (path == NULL) { + if (name) { + PyErr_Format(PyExc_ValueError, + "%.200s.path_from_id(\"%s\") found but does not support path creation", + RNA_struct_identifier(self->ptr.type), + name); + } + else { + PyErr_Format(PyExc_ValueError, + "%.200s.path_from_id() does not support path creation for this type", + RNA_struct_identifier(self->ptr.type)); + } + return NULL; + } + + ret = PyUnicode_FromString(path); + MEM_freeN((void *)path); + + return ret; } PyDoc_STRVAR(pyrna_prop_path_from_id_doc, -".. method:: path_from_id()\n" -"\n" -" Returns the data path from the ID to this property (string).\n" -"\n" -" :return: The path from :class:`bpy.types.bpy_struct.id_data` to this property.\n" -" :rtype: str\n" -); + ".. method:: path_from_id()\n" + "\n" + " Returns the data path from the ID to this property (string).\n" + "\n" + " :return: The path from :class:`bpy.types.bpy_struct.id_data` to this property.\n" + " :rtype: str\n"); static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self) { - const char *path; - PropertyRNA *prop = self->prop; - PyObject *ret; + const char *path; + PropertyRNA *prop = self->prop; + PyObject *ret; - path = RNA_path_from_ID_to_property(&self->ptr, self->prop); + path = RNA_path_from_ID_to_property(&self->ptr, self->prop); - if (path == NULL) { - PyErr_Format(PyExc_ValueError, - "%.200s.%.200s.path_from_id() does not support path creation for this type", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(prop)); - return NULL; - } + if (path == NULL) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s.path_from_id() does not support path creation for this type", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(prop)); + return NULL; + } - ret = PyUnicode_FromString(path); - MEM_freeN((void *)path); + ret = PyUnicode_FromString(path); + MEM_freeN((void *)path); - return ret; + return ret; } PyDoc_STRVAR(pyrna_prop_as_bytes_doc, -".. method:: as_bytes()\n" -"\n" -" Returns this string property as a byte rather than a python string.\n" -"\n" -" :return: The string as bytes.\n" -" :rtype: bytes\n" -); + ".. method:: as_bytes()\n" + "\n" + " Returns this string property as a byte rather than a python string.\n" + "\n" + " :return: The string as bytes.\n" + " :rtype: bytes\n"); static PyObject *pyrna_prop_as_bytes(BPy_PropertyRNA *self) { - if (RNA_property_type(self->prop) != PROP_STRING) { - PyErr_Format(PyExc_TypeError, - "%.200s.%.200s.as_bytes() must be a string", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop)); - return NULL; - } - else { - PyObject *ret; - char buf_fixed[256], *buf; - int buf_len; + if (RNA_property_type(self->prop) != PROP_STRING) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s.as_bytes() must be a string", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); + return NULL; + } + else { + PyObject *ret; + char buf_fixed[256], *buf; + int buf_len; - buf = RNA_property_string_get_alloc(&self->ptr, self->prop, buf_fixed, sizeof(buf_fixed), &buf_len); + buf = RNA_property_string_get_alloc( + &self->ptr, self->prop, buf_fixed, sizeof(buf_fixed), &buf_len); - ret = PyBytes_FromStringAndSize(buf, buf_len); + ret = PyBytes_FromStringAndSize(buf, buf_len); - if (buf_fixed != buf) { - MEM_freeN(buf); - } + if (buf_fixed != buf) { + MEM_freeN(buf); + } - return ret; - } + return ret; + } } PyDoc_STRVAR(pyrna_prop_update_doc, -".. method:: update()\n" -"\n" -" Execute the properties update callback.\n" -"\n" -" .. note::\n" -" This is called when assigning a property,\n" -" however in rare cases its useful to call explicitly.\n" -); + ".. method:: update()\n" + "\n" + " Execute the properties update callback.\n" + "\n" + " .. note::\n" + " This is called when assigning a property,\n" + " however in rare cases its useful to call explicitly.\n"); static PyObject *pyrna_prop_update(BPy_PropertyRNA *self) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); - Py_RETURN_NONE; + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + Py_RETURN_NONE; } PyDoc_STRVAR(pyrna_struct_type_recast_doc, -".. method:: type_recast()\n" -"\n" -" Return a new instance, this is needed because types\n" -" such as textures can be changed at runtime.\n" -"\n" -" :return: a new instance of this object with the type initialized again.\n" -" :rtype: subclass of :class:`bpy.types.bpy_struct`\n" -); + ".. method:: type_recast()\n" + "\n" + " Return a new instance, this is needed because types\n" + " such as textures can be changed at runtime.\n" + "\n" + " :return: a new instance of this object with the type initialized again.\n" + " :rtype: subclass of :class:`bpy.types.bpy_struct`\n"); static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self) { - PointerRNA r_ptr; + PointerRNA r_ptr; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - RNA_pointer_recast(&self->ptr, &r_ptr); - return pyrna_struct_CreatePyObject(&r_ptr); + RNA_pointer_recast(&self->ptr, &r_ptr); + return pyrna_struct_CreatePyObject(&r_ptr); } /** @@ -3889,1441 +3941,1445 @@ static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self) */ static PyObject *pyrna_struct_bl_rna_find_subclass_recursive(PyObject *cls, const char *id) { - PyObject *ret_test = NULL; - PyObject *subclasses = ((PyTypeObject *)cls)->tp_subclasses; - if (subclasses) { - /* Unfortunately we can't use the dict key because Python class names - * don't match the bl_idname used internally. */ - BLI_assert(PyDict_CheckExact(subclasses)); - PyObject *key = NULL; - Py_ssize_t pos = 0; - PyObject *value = NULL; - while (PyDict_Next(subclasses, &pos, &key, &value)) { - BLI_assert(PyWeakref_CheckRef(value)); - PyObject *subcls = PyWeakref_GET_OBJECT(value); - if (subcls != Py_None) { - BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem( - ((PyTypeObject *)subcls)->tp_dict, bpy_intern_str_bl_rna); - if (py_srna) { - StructRNA *srna = py_srna->ptr.data; - if (STREQ(id, RNA_struct_identifier(srna))) { - ret_test = subcls; - break; - } - } - ret_test = pyrna_struct_bl_rna_find_subclass_recursive(subcls, id); - if (ret_test) { - break; - } - } - } - } - return ret_test; + PyObject *ret_test = NULL; + PyObject *subclasses = ((PyTypeObject *)cls)->tp_subclasses; + if (subclasses) { + /* Unfortunately we can't use the dict key because Python class names + * don't match the bl_idname used internally. */ + BLI_assert(PyDict_CheckExact(subclasses)); + PyObject *key = NULL; + Py_ssize_t pos = 0; + PyObject *value = NULL; + while (PyDict_Next(subclasses, &pos, &key, &value)) { + BLI_assert(PyWeakref_CheckRef(value)); + PyObject *subcls = PyWeakref_GET_OBJECT(value); + if (subcls != Py_None) { + BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)subcls)->tp_dict, + bpy_intern_str_bl_rna); + if (py_srna) { + StructRNA *srna = py_srna->ptr.data; + if (STREQ(id, RNA_struct_identifier(srna))) { + ret_test = subcls; + break; + } + } + ret_test = pyrna_struct_bl_rna_find_subclass_recursive(subcls, id); + if (ret_test) { + break; + } + } + } + } + return ret_test; } PyDoc_STRVAR(pyrna_struct_bl_rna_get_subclass_py_doc, -".. classmethod:: bl_rna_get_subclass_py(id, default=None)\n" -"\n" -" :arg id: The RNA type identifier.\n" -" :type id: string\n" -" :return: The class or default when not found.\n" -" :rtype: type\n" -); + ".. classmethod:: bl_rna_get_subclass_py(id, default=None)\n" + "\n" + " :arg id: The RNA type identifier.\n" + " :type id: string\n" + " :return: The class or default when not found.\n" + " :rtype: type\n"); static PyObject *pyrna_struct_bl_rna_get_subclass_py(PyObject *cls, PyObject *args) { - char *id; - PyObject *ret_default = Py_None; + char *id; + PyObject *ret_default = Py_None; - if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass_py", &id, &ret_default)) { - return NULL; - } - PyObject *ret = pyrna_struct_bl_rna_find_subclass_recursive(cls, id); - if (ret == NULL) { - ret = ret_default; - } - return Py_INCREF_RET(ret); + if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass_py", &id, &ret_default)) { + return NULL; + } + PyObject *ret = pyrna_struct_bl_rna_find_subclass_recursive(cls, id); + if (ret == NULL) { + ret = ret_default; + } + return Py_INCREF_RET(ret); } PyDoc_STRVAR(pyrna_struct_bl_rna_get_subclass_doc, -".. classmethod:: bl_rna_get_subclass(id, default=None)\n" -"\n" -" :arg id: The RNA type identifier.\n" -" :type id: string\n" -" :return: The RNA type or default when not found.\n" -" :rtype: :class:`bpy.types.Struct` subclass\n" -); + ".. classmethod:: bl_rna_get_subclass(id, default=None)\n" + "\n" + " :arg id: The RNA type identifier.\n" + " :type id: string\n" + " :return: The RNA type or default when not found.\n" + " :rtype: :class:`bpy.types.Struct` subclass\n"); static PyObject *pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args) { - char *id; - PyObject *ret_default = Py_None; - - if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass", &id, &ret_default)) { - return NULL; - } - - - const BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)cls)->tp_dict, bpy_intern_str_bl_rna); - if (py_srna == NULL) { - PyErr_SetString(PyExc_ValueError, "Not a registered class"); - return NULL; - - } - const StructRNA *srna_base = py_srna->ptr.data; - - PointerRNA ptr; - if (srna_base == &RNA_Node) { - bNodeType *nt = nodeTypeFind(id); - if (nt) { - RNA_pointer_create(NULL, &RNA_Struct, nt->ext.srna, &ptr); - return pyrna_struct_CreatePyObject(&ptr); - } - } - else { - /* TODO, panels, menus etc. */ - PyErr_Format(PyExc_ValueError, "Class type \"%.200s\" not supported", - RNA_struct_identifier(srna_base)); - return NULL; - } - - return Py_INCREF_RET(ret_default); + char *id; + PyObject *ret_default = Py_None; + + if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass", &id, &ret_default)) { + return NULL; + } + + const BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)cls)->tp_dict, + bpy_intern_str_bl_rna); + if (py_srna == NULL) { + PyErr_SetString(PyExc_ValueError, "Not a registered class"); + return NULL; + } + const StructRNA *srna_base = py_srna->ptr.data; + + PointerRNA ptr; + if (srna_base == &RNA_Node) { + bNodeType *nt = nodeTypeFind(id); + if (nt) { + RNA_pointer_create(NULL, &RNA_Struct, nt->ext.srna, &ptr); + return pyrna_struct_CreatePyObject(&ptr); + } + } + else { + /* TODO, panels, menus etc. */ + PyErr_Format( + PyExc_ValueError, "Class type \"%.200s\" not supported", RNA_struct_identifier(srna_base)); + return NULL; + } + + return Py_INCREF_RET(ret_default); } static void pyrna_dir_members_py__add_keys(PyObject *list, PyObject *dict) { - PyObject *list_tmp; + PyObject *list_tmp; - list_tmp = PyDict_Keys(dict); - PyList_SetSlice(list, INT_MAX, INT_MAX, list_tmp); - Py_DECREF(list_tmp); + list_tmp = PyDict_Keys(dict); + PyList_SetSlice(list, INT_MAX, INT_MAX, list_tmp); + Py_DECREF(list_tmp); } static void pyrna_dir_members_py(PyObject *list, PyObject *self) { - PyObject *dict; - PyObject **dict_ptr; + PyObject *dict; + PyObject **dict_ptr; - dict_ptr = _PyObject_GetDictPtr((PyObject *)self); + dict_ptr = _PyObject_GetDictPtr((PyObject *)self); - if (dict_ptr && (dict = *dict_ptr)) { - pyrna_dir_members_py__add_keys(list, dict); - } + if (dict_ptr && (dict = *dict_ptr)) { + pyrna_dir_members_py__add_keys(list, dict); + } - dict = ((PyTypeObject *)Py_TYPE(self))->tp_dict; - if (dict) { - pyrna_dir_members_py__add_keys(list, dict); - } + dict = ((PyTypeObject *)Py_TYPE(self))->tp_dict; + if (dict) { + pyrna_dir_members_py__add_keys(list, dict); + } - /* since this is least common case, handle it last */ - if (BPy_PropertyRNA_Check(self)) { - BPy_PropertyRNA *self_prop = (BPy_PropertyRNA *)self; - if (RNA_property_type(self_prop->prop) == PROP_COLLECTION) { - PointerRNA r_ptr; + /* since this is least common case, handle it last */ + if (BPy_PropertyRNA_Check(self)) { + BPy_PropertyRNA *self_prop = (BPy_PropertyRNA *)self; + if (RNA_property_type(self_prop->prop) == PROP_COLLECTION) { + PointerRNA r_ptr; - if (RNA_property_collection_type_get(&self_prop->ptr, self_prop->prop, &r_ptr)) { - PyObject *cls = pyrna_struct_Subtype(&r_ptr); /* borrows */ - dict = ((PyTypeObject *)cls)->tp_dict; - pyrna_dir_members_py__add_keys(list, dict); - Py_DECREF(cls); - } - } - } + if (RNA_property_collection_type_get(&self_prop->ptr, self_prop->prop, &r_ptr)) { + PyObject *cls = pyrna_struct_Subtype(&r_ptr); /* borrows */ + dict = ((PyTypeObject *)cls)->tp_dict; + pyrna_dir_members_py__add_keys(list, dict); + Py_DECREF(cls); + } + } + } } static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr) { - const char *idname; + const char *idname; - /* for looping over attrs and funcs */ - PointerRNA tptr; - PropertyRNA *iterprop; + /* for looping over attrs and funcs */ + PointerRNA tptr; + PropertyRNA *iterprop; - { - RNA_pointer_create(NULL, &RNA_Struct, ptr->type, &tptr); - iterprop = RNA_struct_find_property(&tptr, "functions"); + { + RNA_pointer_create(NULL, &RNA_Struct, ptr->type, &tptr); + iterprop = RNA_struct_find_property(&tptr, "functions"); - RNA_PROP_BEGIN (&tptr, itemptr, iterprop) - { - FunctionRNA *func = itemptr.data; - if (RNA_function_defined(func)) { - idname = RNA_function_identifier(itemptr.data); - PyList_APPEND(list, PyUnicode_FromString(idname)); - } - } - RNA_PROP_END; - } + RNA_PROP_BEGIN (&tptr, itemptr, iterprop) { + FunctionRNA *func = itemptr.data; + if (RNA_function_defined(func)) { + idname = RNA_function_identifier(itemptr.data); + PyList_APPEND(list, PyUnicode_FromString(idname)); + } + } + RNA_PROP_END; + } - { - /* - * Collect RNA attributes - */ - char name[256], *nameptr; - int namelen; + { + /* + * Collect RNA attributes + */ + char name[256], *nameptr; + int namelen; - iterprop = RNA_struct_iterator_property(ptr->type); + iterprop = RNA_struct_iterator_property(ptr->type); - RNA_PROP_BEGIN (ptr, itemptr, iterprop) - { - nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); + RNA_PROP_BEGIN (ptr, itemptr, iterprop) { + nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); - if (nameptr) { - PyList_APPEND(list, PyUnicode_FromStringAndSize(nameptr, namelen)); + if (nameptr) { + PyList_APPEND(list, PyUnicode_FromStringAndSize(nameptr, namelen)); - if (name != nameptr) { - MEM_freeN(nameptr); - } - } - } - RNA_PROP_END; - } + if (name != nameptr) { + MEM_freeN(nameptr); + } + } + } + RNA_PROP_END; + } } - static PyObject *pyrna_struct_dir(BPy_StructRNA *self) { - PyObject *ret; + PyObject *ret; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - /* Include this in case this instance is a subtype of a python class - * In these instances we may want to return a function or variable provided by the subtype - * */ - ret = PyList_New(0); + /* Include this in case this instance is a subtype of a python class + * In these instances we may want to return a function or variable provided by the subtype + * */ + ret = PyList_New(0); - if (!BPy_StructRNA_CheckExact(self)) { - pyrna_dir_members_py(ret, (PyObject *)self); - } + if (!BPy_StructRNA_CheckExact(self)) { + pyrna_dir_members_py(ret, (PyObject *)self); + } - pyrna_dir_members_rna(ret, &self->ptr); + pyrna_dir_members_rna(ret, &self->ptr); - if (self->ptr.type == &RNA_Context) { - ListBase lb = CTX_data_dir_get(self->ptr.data); - LinkData *link; + if (self->ptr.type == &RNA_Context) { + ListBase lb = CTX_data_dir_get(self->ptr.data); + LinkData *link; - for (link = lb.first; link; link = link->next) { - PyList_APPEND(ret, PyUnicode_FromString(link->data)); - } + for (link = lb.first; link; link = link->next) { + PyList_APPEND(ret, PyUnicode_FromString(link->data)); + } - BLI_freelistN(&lb); - } + BLI_freelistN(&lb); + } - { - /* set(), this is needed to remove-doubles because the deferred - * register-props will be in both the python __dict__ and accessed as RNA */ + { + /* set(), this is needed to remove-doubles because the deferred + * register-props will be in both the python __dict__ and accessed as RNA */ - PyObject *set = PySet_New(ret); + PyObject *set = PySet_New(ret); - Py_DECREF(ret); - ret = PySequence_List(set); - Py_DECREF(set); - } + Py_DECREF(ret); + ret = PySequence_List(set); + Py_DECREF(set); + } - return ret; + return ret; } /* ---------------getattr-------------------------------------------- */ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) { - const char *name = _PyUnicode_AsString(pyname); - PyObject *ret; - PropertyRNA *prop; - FunctionRNA *func; - - PYRNA_STRUCT_CHECK_OBJ(self); - - if (name == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_struct: __getattr__ must be a string"); - ret = NULL; - } - else if (name[0] == '_') { /* rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups */ - /* annoying exception, maybe we need to have different types for this... */ - if (STR_ELEM(name, "__getitem__", "__setitem__") && !RNA_struct_idprops_check(self->ptr.type)) { - PyErr_SetString(PyExc_AttributeError, "bpy_struct: no __getitem__ support for this type"); - ret = NULL; - } - else { - ret = PyObject_GenericGetAttr((PyObject *)self, pyname); - } - } - else if ((prop = RNA_struct_find_property(&self->ptr, name))) { - ret = pyrna_prop_to_py(&self->ptr, prop); - } - /* RNA function only if callback is declared (no optional functions) */ - else if ((func = RNA_struct_find_function(self->ptr.type, name)) && RNA_function_defined(func)) { - ret = pyrna_func_to_py(&self->ptr, func); - } - else if (self->ptr.type == &RNA_Context) { - bContext *C = self->ptr.data; - if (C == NULL) { - PyErr_Format(PyExc_AttributeError, - "bpy_struct: Context is 'NULL', can't get \"%.200s\" from context", - name); - ret = NULL; - } - else { - PointerRNA newptr; - ListBase newlb; - short newtype; - - int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); - - if (done == 1) { /* found */ - switch (newtype) { - case CTX_DATA_TYPE_POINTER: - if (newptr.data == NULL) { - ret = Py_None; - Py_INCREF(ret); - } - else { - ret = pyrna_struct_CreatePyObject(&newptr); - } - break; - case CTX_DATA_TYPE_COLLECTION: - { - CollectionPointerLink *link; - - ret = PyList_New(0); - - for (link = newlb.first; link; link = link->next) { - PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr)); - } - break; - } - default: - /* should never happen */ - BLI_assert(!"Invalid context type"); - - PyErr_Format(PyExc_AttributeError, - "bpy_struct: Context type invalid %d, can't get \"%.200s\" from context", - newtype, name); - ret = NULL; - break; - } - } - else if (done == -1) { /* found but not set */ - ret = Py_None; - Py_INCREF(ret); - } - else { /* not found in the context */ - /* lookup the subclass. raise an error if its not found */ - ret = PyObject_GenericGetAttr((PyObject *)self, pyname); - } - - BLI_freelistN(&newlb); - } - } - else { + const char *name = _PyUnicode_AsString(pyname); + PyObject *ret; + PropertyRNA *prop; + FunctionRNA *func; + + PYRNA_STRUCT_CHECK_OBJ(self); + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_struct: __getattr__ must be a string"); + ret = NULL; + } + else if ( + name[0] == + '_') { /* rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups */ + /* annoying exception, maybe we need to have different types for this... */ + if (STR_ELEM(name, "__getitem__", "__setitem__") && + !RNA_struct_idprops_check(self->ptr.type)) { + PyErr_SetString(PyExc_AttributeError, "bpy_struct: no __getitem__ support for this type"); + ret = NULL; + } + else { + ret = PyObject_GenericGetAttr((PyObject *)self, pyname); + } + } + else if ((prop = RNA_struct_find_property(&self->ptr, name))) { + ret = pyrna_prop_to_py(&self->ptr, prop); + } + /* RNA function only if callback is declared (no optional functions) */ + else if ((func = RNA_struct_find_function(self->ptr.type, name)) && RNA_function_defined(func)) { + ret = pyrna_func_to_py(&self->ptr, func); + } + else if (self->ptr.type == &RNA_Context) { + bContext *C = self->ptr.data; + if (C == NULL) { + PyErr_Format(PyExc_AttributeError, + "bpy_struct: Context is 'NULL', can't get \"%.200s\" from context", + name); + ret = NULL; + } + else { + PointerRNA newptr; + ListBase newlb; + short newtype; + + int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); + + if (done == 1) { /* found */ + switch (newtype) { + case CTX_DATA_TYPE_POINTER: + if (newptr.data == NULL) { + ret = Py_None; + Py_INCREF(ret); + } + else { + ret = pyrna_struct_CreatePyObject(&newptr); + } + break; + case CTX_DATA_TYPE_COLLECTION: { + CollectionPointerLink *link; + + ret = PyList_New(0); + + for (link = newlb.first; link; link = link->next) { + PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr)); + } + break; + } + default: + /* should never happen */ + BLI_assert(!"Invalid context type"); + + PyErr_Format(PyExc_AttributeError, + "bpy_struct: Context type invalid %d, can't get \"%.200s\" from context", + newtype, + name); + ret = NULL; + break; + } + } + else if (done == -1) { /* found but not set */ + ret = Py_None; + Py_INCREF(ret); + } + else { /* not found in the context */ + /* lookup the subclass. raise an error if its not found */ + ret = PyObject_GenericGetAttr((PyObject *)self, pyname); + } + + BLI_freelistN(&newlb); + } + } + else { #if 0 - PyErr_Format(PyExc_AttributeError, - "bpy_struct: attribute \"%.200s\" not found", - name); - ret = NULL; + PyErr_Format(PyExc_AttributeError, + "bpy_struct: attribute \"%.200s\" not found", + name); + ret = NULL; #endif - /* Include this in case this instance is a subtype of a python class - * In these instances we may want to return a function or variable provided by the subtype - * - * Also needed to return methods when its not a subtype - * */ + /* Include this in case this instance is a subtype of a python class + * In these instances we may want to return a function or variable provided by the subtype + * + * Also needed to return methods when its not a subtype + * */ - /* The error raised here will be displayed */ - ret = PyObject_GenericGetAttr((PyObject *)self, pyname); - } + /* The error raised here will be displayed */ + ret = PyObject_GenericGetAttr((PyObject *)self, pyname); + } - return ret; + return ret; } #if 0 static int pyrna_struct_pydict_contains(PyObject *self, PyObject *pyname) { - PyObject *dict = *(_PyObject_GetDictPtr((PyObject *)self)); - if (dict == NULL) /* unlikely */ - return 0; + PyObject *dict = *(_PyObject_GetDictPtr((PyObject *)self)); + if (dict == NULL) /* unlikely */ + return 0; - return PyDict_Contains(dict, pyname); + return PyDict_Contains(dict, pyname); } #endif /* --------------- setattr------------------------------------------- */ static bool pyrna_is_deferred_prop(const PyObject *value) { - return PyTuple_CheckExact(value) && - PyTuple_GET_SIZE(value) == 2 && - PyCFunction_Check(PyTuple_GET_ITEM(value, 0)) && - PyDict_CheckExact(PyTuple_GET_ITEM(value, 1)); + return PyTuple_CheckExact(value) && PyTuple_GET_SIZE(value) == 2 && + PyCFunction_Check(PyTuple_GET_ITEM(value, 0)) && + PyDict_CheckExact(PyTuple_GET_ITEM(value, 1)); } #if 0 static PyObject *pyrna_struct_meta_idprop_getattro(PyObject *cls, PyObject *attr) { - PyObject *ret = PyType_Type.tp_getattro(cls, attr); - - /* Allows: - * >>> bpy.types.Scene.foo = BoolProperty() - * >>> bpy.types.Scene.foo - * <bpy_struct, BoolProperty("foo")> - * ...rather than returning the deferred class register tuple as checked by pyrna_is_deferred_prop() - * - * Disable for now, this is faking internal behavior in a way that's too tricky to maintain well. */ -#if 0 - if (ret == NULL) { // || pyrna_is_deferred_prop(ret) - StructRNA *srna = srna_from_self(cls, "StructRNA.__getattr__"); - if (srna) { - PropertyRNA *prop = RNA_struct_type_find_property(srna, _PyUnicode_AsString(attr)); - if (prop) { - PointerRNA tptr; - PyErr_Clear(); /* clear error from tp_getattro */ - RNA_pointer_create(NULL, &RNA_Property, prop, &tptr); - ret = pyrna_struct_CreatePyObject(&tptr); - } - } - } -#endif - - return ret; + PyObject *ret = PyType_Type.tp_getattro(cls, attr); + + /* Allows: + * >>> bpy.types.Scene.foo = BoolProperty() + * >>> bpy.types.Scene.foo + * <bpy_struct, BoolProperty("foo")> + * ...rather than returning the deferred class register tuple as checked by pyrna_is_deferred_prop() + * + * Disable for now, this is faking internal behavior in a way that's too tricky to maintain well. */ +# if 0 + if (ret == NULL) { // || pyrna_is_deferred_prop(ret) + StructRNA *srna = srna_from_self(cls, "StructRNA.__getattr__"); + if (srna) { + PropertyRNA *prop = RNA_struct_type_find_property(srna, _PyUnicode_AsString(attr)); + if (prop) { + PointerRNA tptr; + PyErr_Clear(); /* clear error from tp_getattro */ + RNA_pointer_create(NULL, &RNA_Property, prop, &tptr); + ret = pyrna_struct_CreatePyObject(&tptr); + } + } + } +# endif + + return ret; } #endif static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyObject *value) { - StructRNA *srna = srna_from_self(cls, "StructRNA.__setattr__"); - const bool is_deferred_prop = (value && pyrna_is_deferred_prop(value)); - const char *attr_str = _PyUnicode_AsString(attr); - - if (srna && !pyrna_write_check() && (is_deferred_prop || RNA_struct_type_find_property(srna, attr_str))) { - PyErr_Format(PyExc_AttributeError, - "pyrna_struct_meta_idprop_setattro() " - "can't set in readonly state '%.200s.%S'", - ((PyTypeObject *)cls)->tp_name, attr); - return -1; - } - - if (srna == NULL) { - /* allow setting on unregistered classes which can be registered later on */ + StructRNA *srna = srna_from_self(cls, "StructRNA.__setattr__"); + const bool is_deferred_prop = (value && pyrna_is_deferred_prop(value)); + const char *attr_str = _PyUnicode_AsString(attr); + + if (srna && !pyrna_write_check() && + (is_deferred_prop || RNA_struct_type_find_property(srna, attr_str))) { + PyErr_Format(PyExc_AttributeError, + "pyrna_struct_meta_idprop_setattro() " + "can't set in readonly state '%.200s.%S'", + ((PyTypeObject *)cls)->tp_name, + attr); + return -1; + } + + if (srna == NULL) { + /* allow setting on unregistered classes which can be registered later on */ #if 0 - if (value && is_deferred_prop) { - PyErr_Format(PyExc_AttributeError, - "pyrna_struct_meta_idprop_setattro() unable to get srna from class '%.200s'", - ((PyTypeObject *)cls)->tp_name); - return -1; - } + if (value && is_deferred_prop) { + PyErr_Format(PyExc_AttributeError, + "pyrna_struct_meta_idprop_setattro() unable to get srna from class '%.200s'", + ((PyTypeObject *)cls)->tp_name); + return -1; + } #endif - /* srna_from_self may set an error */ - PyErr_Clear(); - return PyType_Type.tp_setattro(cls, attr, value); - } - - if (value) { - /* check if the value is a property */ - if (is_deferred_prop) { - int ret = deferred_register_prop(srna, attr, value); - if (ret == -1) { - /* error set */ - return ret; - } - - /* pass through and assign to the classes __dict__ as well - * when the value isn't assigned it still creates the RNA property - * but gets confusing from script writers POV if the assigned value cant be read back. */ - } - else { - /* remove existing property if its set or we also end up with confusion */ - RNA_def_property_free_identifier(srna, attr_str); /* ignore on failure */ - } - } - else { /* __delattr__ */ - /* first find if this is a registered property */ - const int ret = RNA_def_property_free_identifier(srna, attr_str); - if (ret == -1) { - PyErr_Format(PyExc_TypeError, - "struct_meta_idprop.detattr(): '%s' not a dynamic property", - attr_str); - return -1; - } - } - - /* fallback to standard py, delattr/setattr */ - return PyType_Type.tp_setattro(cls, attr, value); + /* srna_from_self may set an error */ + PyErr_Clear(); + return PyType_Type.tp_setattro(cls, attr, value); + } + + if (value) { + /* check if the value is a property */ + if (is_deferred_prop) { + int ret = deferred_register_prop(srna, attr, value); + if (ret == -1) { + /* error set */ + return ret; + } + + /* pass through and assign to the classes __dict__ as well + * when the value isn't assigned it still creates the RNA property + * but gets confusing from script writers POV if the assigned value cant be read back. */ + } + else { + /* remove existing property if its set or we also end up with confusion */ + RNA_def_property_free_identifier(srna, attr_str); /* ignore on failure */ + } + } + else { /* __delattr__ */ + /* first find if this is a registered property */ + const int ret = RNA_def_property_free_identifier(srna, attr_str); + if (ret == -1) { + PyErr_Format( + PyExc_TypeError, "struct_meta_idprop.detattr(): '%s' not a dynamic property", attr_str); + return -1; + } + } + + /* fallback to standard py, delattr/setattr */ + return PyType_Type.tp_setattro(cls, attr, value); } static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject *value) { - const char *name = _PyUnicode_AsString(pyname); - PropertyRNA *prop = NULL; + const char *name = _PyUnicode_AsString(pyname); + PropertyRNA *prop = NULL; - PYRNA_STRUCT_CHECK_INT(self); + PYRNA_STRUCT_CHECK_INT(self); #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ - - if (name == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_struct: __setattr__ must be a string"); - return -1; - } - else if (name[0] != '_' && (prop = RNA_struct_find_property(&self->ptr, name))) { - if (!RNA_property_editable_flag(&self->ptr, prop)) { - PyErr_Format(PyExc_AttributeError, - "bpy_struct: attribute \"%.200s\" from \"%.200s\" is read-only", - RNA_property_identifier(prop), RNA_struct_identifier(self->ptr.type)); - return -1; - } - } - else if (self->ptr.type == &RNA_Context) { - /* code just raises correct error, context prop's cant be set, unless its apart of the py class */ - bContext *C = self->ptr.data; - if (C == NULL) { - PyErr_Format(PyExc_AttributeError, - "bpy_struct: Context is 'NULL', can't set \"%.200s\" from context", - name); - return -1; - } - else { - PointerRNA newptr; - ListBase newlb; - short newtype; - - int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); - - if (done == 1) { - PyErr_Format(PyExc_AttributeError, - "bpy_struct: Context property \"%.200s\" is read-only", - name); - BLI_freelistN(&newlb); - return -1; - } - - BLI_freelistN(&newlb); - } - } - - /* pyrna_py_to_prop sets its own exceptions */ - if (prop) { - if (value == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_struct: del not supported"); - return -1; - } - return pyrna_py_to_prop(&self->ptr, prop, NULL, value, "bpy_struct: item.attr = val:"); - } - else { - return PyObject_GenericSetAttr((PyObject *)self, pyname, value); - } + if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { + return -1; + } +#endif /* USE_PEDANTIC_WRITE */ + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_struct: __setattr__ must be a string"); + return -1; + } + else if (name[0] != '_' && (prop = RNA_struct_find_property(&self->ptr, name))) { + if (!RNA_property_editable_flag(&self->ptr, prop)) { + PyErr_Format(PyExc_AttributeError, + "bpy_struct: attribute \"%.200s\" from \"%.200s\" is read-only", + RNA_property_identifier(prop), + RNA_struct_identifier(self->ptr.type)); + return -1; + } + } + else if (self->ptr.type == &RNA_Context) { + /* code just raises correct error, context prop's cant be set, unless its apart of the py class */ + bContext *C = self->ptr.data; + if (C == NULL) { + PyErr_Format(PyExc_AttributeError, + "bpy_struct: Context is 'NULL', can't set \"%.200s\" from context", + name); + return -1; + } + else { + PointerRNA newptr; + ListBase newlb; + short newtype; + + int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); + + if (done == 1) { + PyErr_Format( + PyExc_AttributeError, "bpy_struct: Context property \"%.200s\" is read-only", name); + BLI_freelistN(&newlb); + return -1; + } + + BLI_freelistN(&newlb); + } + } + + /* pyrna_py_to_prop sets its own exceptions */ + if (prop) { + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_struct: del not supported"); + return -1; + } + return pyrna_py_to_prop(&self->ptr, prop, NULL, value, "bpy_struct: item.attr = val:"); + } + else { + return PyObject_GenericSetAttr((PyObject *)self, pyname, value); + } } static PyObject *pyrna_prop_dir(BPy_PropertyRNA *self) { - PyObject *ret; - PointerRNA r_ptr; + PyObject *ret; + PointerRNA r_ptr; - /* Include this in case this instance is a subtype of a python class - * In these instances we may want to return a function or variable provided by the subtype - * */ - ret = PyList_New(0); + /* Include this in case this instance is a subtype of a python class + * In these instances we may want to return a function or variable provided by the subtype + * */ + ret = PyList_New(0); - if (!BPy_PropertyRNA_CheckExact(self)) { - pyrna_dir_members_py(ret, (PyObject *)self); - } + if (!BPy_PropertyRNA_CheckExact(self)) { + pyrna_dir_members_py(ret, (PyObject *)self); + } - if (RNA_property_type(self->prop) == PROP_COLLECTION) { - if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - pyrna_dir_members_rna(ret, &r_ptr); - } - } + if (RNA_property_type(self->prop) == PROP_COLLECTION) { + if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + pyrna_dir_members_rna(ret, &r_ptr); + } + } - return ret; + return ret; } - static PyObject *pyrna_prop_array_getattro(BPy_PropertyRNA *self, PyObject *pyname) { - return PyObject_GenericGetAttr((PyObject *)self, pyname); + return PyObject_GenericGetAttr((PyObject *)self, pyname); } static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject *pyname) { - const char *name = _PyUnicode_AsString(pyname); - - if (name == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_prop_collection: __getattr__ must be a string"); - return NULL; - } - else if (name[0] != '_') { - PyObject *ret; - PropertyRNA *prop; - FunctionRNA *func; - - PointerRNA r_ptr; - if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - if ((prop = RNA_struct_find_property(&r_ptr, name))) { - ret = pyrna_prop_to_py(&r_ptr, prop); - - return ret; - } - else if ((func = RNA_struct_find_function(r_ptr.type, name))) { - PyObject *self_collection = pyrna_struct_CreatePyObject(&r_ptr); - ret = pyrna_func_to_py(&((BPy_DummyPointerRNA *)self_collection)->ptr, func); - Py_DECREF(self_collection); - - return ret; - } - } - } + const char *name = _PyUnicode_AsString(pyname); + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_prop_collection: __getattr__ must be a string"); + return NULL; + } + else if (name[0] != '_') { + PyObject *ret; + PropertyRNA *prop; + FunctionRNA *func; + + PointerRNA r_ptr; + if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + if ((prop = RNA_struct_find_property(&r_ptr, name))) { + ret = pyrna_prop_to_py(&r_ptr, prop); + + return ret; + } + else if ((func = RNA_struct_find_function(r_ptr.type, name))) { + PyObject *self_collection = pyrna_struct_CreatePyObject(&r_ptr); + ret = pyrna_func_to_py(&((BPy_DummyPointerRNA *)self_collection)->ptr, func); + Py_DECREF(self_collection); + + return ret; + } + } + } #if 0 - return PyObject_GenericGetAttr((PyObject *)self, pyname); + return PyObject_GenericGetAttr((PyObject *)self, pyname); #else - { - /* Could just do this except for 1 awkward case. - * PyObject_GenericGetAttr((PyObject *)self, pyname); - * so as to support 'bpy.data.library.load()' - * note, this _only_ supports static methods */ - - PyObject *ret = PyObject_GenericGetAttr((PyObject *)self, pyname); - - if (ret == NULL && name[0] != '_') { /* avoid inheriting __call__ and similar */ - /* since this is least common case, handle it last */ - PointerRNA r_ptr; - if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - PyObject *cls; - - PyObject *error_type, *error_value, *error_traceback; - PyErr_Fetch(&error_type, &error_value, &error_traceback); - PyErr_Clear(); - - cls = pyrna_struct_Subtype(&r_ptr); - ret = PyObject_GenericGetAttr(cls, pyname); - Py_DECREF(cls); - - /* restore the original error */ - if (ret == NULL) { - PyErr_Restore(error_type, error_value, error_traceback); - } - } - } - - return ret; - } + { + /* Could just do this except for 1 awkward case. + * PyObject_GenericGetAttr((PyObject *)self, pyname); + * so as to support 'bpy.data.library.load()' + * note, this _only_ supports static methods */ + + PyObject *ret = PyObject_GenericGetAttr((PyObject *)self, pyname); + + if (ret == NULL && name[0] != '_') { /* avoid inheriting __call__ and similar */ + /* since this is least common case, handle it last */ + PointerRNA r_ptr; + if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + PyObject *cls; + + PyObject *error_type, *error_value, *error_traceback; + PyErr_Fetch(&error_type, &error_value, &error_traceback); + PyErr_Clear(); + + cls = pyrna_struct_Subtype(&r_ptr); + ret = PyObject_GenericGetAttr(cls, pyname); + Py_DECREF(cls); + + /* restore the original error */ + if (ret == NULL) { + PyErr_Restore(error_type, error_value, error_traceback); + } + } + } + + return ret; + } #endif } /* --------------- setattr------------------------------------------- */ static int pyrna_prop_collection_setattro(BPy_PropertyRNA *self, PyObject *pyname, PyObject *value) { - const char *name = _PyUnicode_AsString(pyname); - PropertyRNA *prop; - PointerRNA r_ptr; + const char *name = _PyUnicode_AsString(pyname); + PropertyRNA *prop; + PointerRNA r_ptr; #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ - - if (name == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_prop: __setattr__ must be a string"); - return -1; - } - else if (value == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_prop: del not supported"); - return -1; - } - else if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - if ((prop = RNA_struct_find_property(&r_ptr, name))) { - /* pyrna_py_to_prop sets its own exceptions */ - return pyrna_py_to_prop(&r_ptr, prop, NULL, value, "BPy_PropertyRNA - Attribute (setattr):"); - } - } - - PyErr_Format(PyExc_AttributeError, - "bpy_prop_collection: attribute \"%.200s\" not found", - name); - return -1; + if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { + return -1; + } +#endif /* USE_PEDANTIC_WRITE */ + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_prop: __setattr__ must be a string"); + return -1; + } + else if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_prop: del not supported"); + return -1; + } + else if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + if ((prop = RNA_struct_find_property(&r_ptr, name))) { + /* pyrna_py_to_prop sets its own exceptions */ + return pyrna_py_to_prop(&r_ptr, prop, NULL, value, "BPy_PropertyRNA - Attribute (setattr):"); + } + } + + PyErr_Format(PyExc_AttributeError, "bpy_prop_collection: attribute \"%.200s\" not found", name); + return -1; } /* odd case, we need to be able return a python method from a tp_getset */ static PyObject *pyrna_prop_collection_idprop_add(BPy_PropertyRNA *self) { - PointerRNA r_ptr; + PointerRNA r_ptr; #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return NULL; - } -#endif /* USE_PEDANTIC_WRITE */ - - RNA_property_collection_add(&self->ptr, self->prop, &r_ptr); - if (!r_ptr.data) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.add(): not supported for this collection"); - return NULL; - } - else { - return pyrna_struct_CreatePyObject(&r_ptr); - } + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ + + RNA_property_collection_add(&self->ptr, self->prop, &r_ptr); + if (!r_ptr.data) { + PyErr_SetString(PyExc_TypeError, + "bpy_prop_collection.add(): not supported for this collection"); + return NULL; + } + else { + return pyrna_struct_CreatePyObject(&r_ptr); + } } static PyObject *pyrna_prop_collection_idprop_remove(BPy_PropertyRNA *self, PyObject *value) { - int key = PyLong_AsLong(value); + int key = PyLong_AsLong(value); #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return NULL; - } -#endif /* USE_PEDANTIC_WRITE */ + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ - if (key == -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.remove(): expected one int argument"); - return NULL; - } + if (key == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.remove(): expected one int argument"); + return NULL; + } - if (!RNA_property_collection_remove(&self->ptr, self->prop, key)) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.remove() not supported for this collection"); - return NULL; - } + if (!RNA_property_collection_remove(&self->ptr, self->prop, key)) { + PyErr_SetString(PyExc_TypeError, + "bpy_prop_collection.remove() not supported for this collection"); + return NULL; + } - Py_RETURN_NONE; + Py_RETURN_NONE; } static PyObject *pyrna_prop_collection_idprop_clear(BPy_PropertyRNA *self) { #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return NULL; - } -#endif /* USE_PEDANTIC_WRITE */ + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ - RNA_property_collection_clear(&self->ptr, self->prop); + RNA_property_collection_clear(&self->ptr, self->prop); - Py_RETURN_NONE; + Py_RETURN_NONE; } static PyObject *pyrna_prop_collection_idprop_move(BPy_PropertyRNA *self, PyObject *args) { - int key = 0, pos = 0; + int key = 0, pos = 0; #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return NULL; - } -#endif /* USE_PEDANTIC_WRITE */ + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ - if (!PyArg_ParseTuple(args, "ii", &key, &pos)) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.move(): expected two ints as arguments"); - return NULL; - } + if (!PyArg_ParseTuple(args, "ii", &key, &pos)) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.move(): expected two ints as arguments"); + return NULL; + } - if (!RNA_property_collection_move(&self->ptr, self->prop, key, pos)) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.move() not supported for this collection"); - return NULL; - } + if (!RNA_property_collection_move(&self->ptr, self->prop, key, pos)) { + PyErr_SetString(PyExc_TypeError, + "bpy_prop_collection.move() not supported for this collection"); + return NULL; + } - Py_RETURN_NONE; + Py_RETURN_NONE; } - PyDoc_STRVAR(pyrna_struct_get_id_data_doc, -"The :class:`bpy.types.ID` object this datablock is from or None, (not available for all data types)" -); + "The :class:`bpy.types.ID` object this datablock is from or None, (not available for " + "all data types)"); static PyObject *pyrna_struct_get_id_data(BPy_DummyPointerRNA *self) { - /* used for struct and pointer since both have a ptr */ - if (self->ptr.id.data) { - PointerRNA id_ptr; - RNA_id_pointer_create((ID *)self->ptr.id.data, &id_ptr); - return pyrna_struct_CreatePyObject(&id_ptr); - } + /* used for struct and pointer since both have a ptr */ + if (self->ptr.id.data) { + PointerRNA id_ptr; + RNA_id_pointer_create((ID *)self->ptr.id.data, &id_ptr); + return pyrna_struct_CreatePyObject(&id_ptr); + } - Py_RETURN_NONE; + Py_RETURN_NONE; } PyDoc_STRVAR(pyrna_struct_get_data_doc, -"The data this property is using, *type* :class:`bpy.types.bpy_struct`" -); + "The data this property is using, *type* :class:`bpy.types.bpy_struct`"); static PyObject *pyrna_struct_get_data(BPy_DummyPointerRNA *self) { - return pyrna_struct_CreatePyObject(&self->ptr); + return pyrna_struct_CreatePyObject(&self->ptr); } -PyDoc_STRVAR(pyrna_struct_get_rna_type_doc, -"The property type for introspection" -); +PyDoc_STRVAR(pyrna_struct_get_rna_type_doc, "The property type for introspection"); static PyObject *pyrna_struct_get_rna_type(BPy_PropertyRNA *self) { - PointerRNA tptr; - RNA_pointer_create(NULL, &RNA_Property, self->prop, &tptr); - return pyrna_struct_Subtype(&tptr); + PointerRNA tptr; + RNA_pointer_create(NULL, &RNA_Property, self->prop, &tptr); + return pyrna_struct_Subtype(&tptr); } - - /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef pyrna_prop_getseters[] = { - {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)pyrna_struct_get_id_data_doc, NULL}, - {(char *)"data", (getter)pyrna_struct_get_data, (setter)NULL, (char *)pyrna_struct_get_data_doc, NULL}, - {(char *)"rna_type", (getter)pyrna_struct_get_rna_type, (setter)NULL, (char *)pyrna_struct_get_rna_type_doc, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {(char *)"id_data", + (getter)pyrna_struct_get_id_data, + (setter)NULL, + (char *)pyrna_struct_get_id_data_doc, + NULL}, + {(char *)"data", + (getter)pyrna_struct_get_data, + (setter)NULL, + (char *)pyrna_struct_get_data_doc, + NULL}, + {(char *)"rna_type", + (getter)pyrna_struct_get_rna_type, + (setter)NULL, + (char *)pyrna_struct_get_rna_type_doc, + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; static PyGetSetDef pyrna_struct_getseters[] = { - {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)pyrna_struct_get_id_data_doc, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {(char *)"id_data", + (getter)pyrna_struct_get_id_data, + (setter)NULL, + (char *)pyrna_struct_get_id_data_doc, + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void *closure); static PyGetSetDef pyrna_func_getseters[] = { - {(char *)"__doc__", (getter)pyrna_func_doc_get, (setter)NULL, NULL, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {(char *)"__doc__", (getter)pyrna_func_doc_get, (setter)NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; PyDoc_STRVAR(pyrna_prop_collection_keys_doc, -".. method:: keys()\n" -"\n" -" Return the identifiers of collection members\n" -" (matching pythons dict.keys() functionality).\n" -"\n" -" :return: the identifiers for each member of this collection.\n" -" :rtype: list of strings\n" -); + ".. method:: keys()\n" + "\n" + " Return the identifiers of collection members\n" + " (matching pythons dict.keys() functionality).\n" + "\n" + " :return: the identifiers for each member of this collection.\n" + " :rtype: list of strings\n"); static PyObject *pyrna_prop_collection_keys(BPy_PropertyRNA *self) { - PyObject *ret = PyList_New(0); - char name[256], *nameptr; - int namelen; + PyObject *ret = PyList_New(0); + char name[256], *nameptr; + int namelen; - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); - if (nameptr) { - PyList_APPEND(ret, PyUnicode_FromStringAndSize(nameptr, namelen)); + if (nameptr) { + PyList_APPEND(ret, PyUnicode_FromStringAndSize(nameptr, namelen)); - if (name != nameptr) { - MEM_freeN(nameptr); - } - } - } - RNA_PROP_END; + if (name != nameptr) { + MEM_freeN(nameptr); + } + } + } + RNA_PROP_END; - return ret; + return ret; } PyDoc_STRVAR(pyrna_prop_collection_items_doc, -".. method:: items()\n" -"\n" -" Return the identifiers of collection members\n" -" (matching pythons dict.items() functionality).\n" -"\n" -" :return: (key, value) pairs for each member of this collection.\n" -" :rtype: list of tuples\n" -); + ".. method:: items()\n" + "\n" + " Return the identifiers of collection members\n" + " (matching pythons dict.items() functionality).\n" + "\n" + " :return: (key, value) pairs for each member of this collection.\n" + " :rtype: list of tuples\n"); static PyObject *pyrna_prop_collection_items(BPy_PropertyRNA *self) { - PyObject *ret = PyList_New(0); - PyObject *item; - char name[256], *nameptr; - int namelen; - int i = 0; - - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - if (itemptr.data) { - /* add to python list */ - item = PyTuple_New(2); - nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); - if (nameptr) { - PyTuple_SET_ITEM(item, 0, PyUnicode_FromStringAndSize(nameptr, namelen)); - if (name != nameptr) { - MEM_freeN(nameptr); - } - } - else { - /* a bit strange but better then returning an empty list */ - PyTuple_SET_ITEM(item, 0, PyLong_FromLong(i)); - } - PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); - - PyList_APPEND(ret, item); - - i++; - } - } - RNA_PROP_END; - - return ret; + PyObject *ret = PyList_New(0); + PyObject *item; + char name[256], *nameptr; + int namelen; + int i = 0; + + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + if (itemptr.data) { + /* add to python list */ + item = PyTuple_New(2); + nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); + if (nameptr) { + PyTuple_SET_ITEM(item, 0, PyUnicode_FromStringAndSize(nameptr, namelen)); + if (name != nameptr) { + MEM_freeN(nameptr); + } + } + else { + /* a bit strange but better then returning an empty list */ + PyTuple_SET_ITEM(item, 0, PyLong_FromLong(i)); + } + PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); + + PyList_APPEND(ret, item); + + i++; + } + } + RNA_PROP_END; + + return ret; } PyDoc_STRVAR(pyrna_prop_collection_values_doc, -".. method:: values()\n" -"\n" -" Return the values of collection\n" -" (matching pythons dict.values() functionality).\n" -"\n" -" :return: the members of this collection.\n" -" :rtype: list\n" -); + ".. method:: values()\n" + "\n" + " Return the values of collection\n" + " (matching pythons dict.values() functionality).\n" + "\n" + " :return: the members of this collection.\n" + " :rtype: list\n"); static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self) { - /* re-use slice*/ - return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); + /* re-use slice*/ + return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); } PyDoc_STRVAR(pyrna_struct_get_doc, -".. method:: get(key, default=None)\n" -"\n" -" Returns the value of the custom property assigned to key or default\n" -" when not found (matches pythons dictionary function of the same name).\n" -"\n" -" :arg key: The key associated with the custom property.\n" -" :type key: string\n" -" :arg default: Optional argument for the value to return if\n" -" *key* is not found.\n" -" :type default: Undefined\n" -"\n" -BPY_DOC_ID_PROP_TYPE_NOTE -); + ".. method:: get(key, default=None)\n" + "\n" + " Returns the value of the custom property assigned to key or default\n" + " when not found (matches pythons dictionary function of the same name).\n" + "\n" + " :arg key: The key associated with the custom property.\n" + " :type key: string\n" + " :arg default: Optional argument for the value to return if\n" + " *key* is not found.\n" + " :type default: Undefined\n" + "\n" BPY_DOC_ID_PROP_TYPE_NOTE); static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args) { - IDProperty *group, *idprop; + IDProperty *group, *idprop; - const char *key; - PyObject *def = Py_None; + const char *key; + PyObject *def = Py_None; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) { + return NULL; + } - /* mostly copied from BPy_IDGroup_Map_GetItem */ - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); - return NULL; - } + /* mostly copied from BPy_IDGroup_Map_GetItem */ + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); - if (group) { - idprop = IDP_GetPropertyFromGroup(group, key); + group = RNA_struct_idprops(&self->ptr, 0); + if (group) { + idprop = IDP_GetPropertyFromGroup(group, key); - if (idprop) { - return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); - } - } + if (idprop) { + return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); + } + } - return Py_INCREF_RET(def); + return Py_INCREF_RET(def); } PyDoc_STRVAR(pyrna_struct_pop_doc, -".. method:: pop(key, default=None)\n" -"\n" -" Remove and return the value of the custom property assigned to key or default\n" -" when not found (matches pythons dictionary function of the same name).\n" -"\n" -" :arg key: The key associated with the custom property.\n" -" :type key: string\n" -" :arg default: Optional argument for the value to return if\n" -" *key* is not found.\n" -" :type default: Undefined\n" -"\n" -BPY_DOC_ID_PROP_TYPE_NOTE -); + ".. method:: pop(key, default=None)\n" + "\n" + " Remove and return the value of the custom property assigned to key or default\n" + " when not found (matches pythons dictionary function of the same name).\n" + "\n" + " :arg key: The key associated with the custom property.\n" + " :type key: string\n" + " :arg default: Optional argument for the value to return if\n" + " *key* is not found.\n" + " :type default: Undefined\n" + "\n" BPY_DOC_ID_PROP_TYPE_NOTE); static PyObject *pyrna_struct_pop(BPy_StructRNA *self, PyObject *args) { - IDProperty *group, *idprop; + IDProperty *group, *idprop; - const char *key; - PyObject *def = NULL; + const char *key; + PyObject *def = NULL; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) { + return NULL; + } - /* mostly copied from BPy_IDGroup_Map_GetItem */ - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); - return NULL; - } + /* mostly copied from BPy_IDGroup_Map_GetItem */ + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); - if (group) { - idprop = IDP_GetPropertyFromGroup(group, key); + group = RNA_struct_idprops(&self->ptr, 0); + if (group) { + idprop = IDP_GetPropertyFromGroup(group, key); - if (idprop) { - PyObject *ret = BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); - IDP_RemoveFromGroup(group, idprop); - return ret; - } - } + if (idprop) { + PyObject *ret = BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); + IDP_RemoveFromGroup(group, idprop); + return ret; + } + } - if (def == NULL) { - PyErr_SetString(PyExc_KeyError, "key not found"); - return NULL; - } - return Py_INCREF_RET(def); + if (def == NULL) { + PyErr_SetString(PyExc_KeyError, "key not found"); + return NULL; + } + return Py_INCREF_RET(def); } PyDoc_STRVAR(pyrna_struct_as_pointer_doc, -".. method:: as_pointer()\n" -"\n" -" Returns the memory address which holds a pointer to blenders internal data\n" -"\n" -" :return: int (memory address).\n" -" :rtype: int\n" -"\n" -" .. note:: This is intended only for advanced script writers who need to\n" -" pass blender data to their own C/Python modules.\n" -); + ".. method:: as_pointer()\n" + "\n" + " Returns the memory address which holds a pointer to blenders internal data\n" + "\n" + " :return: int (memory address).\n" + " :rtype: int\n" + "\n" + " .. note:: This is intended only for advanced script writers who need to\n" + " pass blender data to their own C/Python modules.\n"); static PyObject *pyrna_struct_as_pointer(BPy_StructRNA *self) { - return PyLong_FromVoidPtr(self->ptr.data); + return PyLong_FromVoidPtr(self->ptr.data); } PyDoc_STRVAR(pyrna_prop_collection_get_doc, -".. method:: get(key, default=None)\n" -"\n" -" Returns the value of the item assigned to key or default when not found\n" -" (matches pythons dictionary function of the same name).\n" -"\n" -" :arg key: The identifier for the collection member.\n" -" :type key: string\n" -" :arg default: Optional argument for the value to return if\n" -" *key* is not found.\n" -" :type default: Undefined\n" -); + ".. method:: get(key, default=None)\n" + "\n" + " Returns the value of the item assigned to key or default when not found\n" + " (matches pythons dictionary function of the same name).\n" + "\n" + " :arg key: The identifier for the collection member.\n" + " :type key: string\n" + " :arg default: Optional argument for the value to return if\n" + " *key* is not found.\n" + " :type default: Undefined\n"); static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args) { - PointerRNA newptr; + PointerRNA newptr; - PyObject *key_ob; - PyObject *def = Py_None; + PyObject *key_ob; + PyObject *def = Py_None; - PYRNA_PROP_CHECK_OBJ(self); + PYRNA_PROP_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "O|O:get", &key_ob, &def)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "O|O:get", &key_ob, &def)) { + return NULL; + } - if (PyUnicode_Check(key_ob)) { - const char *key = _PyUnicode_AsString(key_ob); + if (PyUnicode_Check(key_ob)) { + const char *key = _PyUnicode_AsString(key_ob); - if (RNA_property_collection_lookup_string(&self->ptr, self->prop, key, &newptr)) { - return pyrna_struct_CreatePyObject(&newptr); - } - } - else if (PyTuple_Check(key_ob)) { - PyObject *ret = pyrna_prop_collection_subscript_str_lib_pair(self, key_ob, - "bpy_prop_collection.get((id, lib))", false); - if (ret) { - return ret; - } - } - else { - PyErr_Format(PyExc_KeyError, - "bpy_prop_collection.get(key, ...): key must be a string or tuple, not %.200s", - Py_TYPE(key_ob)->tp_name); - } + if (RNA_property_collection_lookup_string(&self->ptr, self->prop, key, &newptr)) { + return pyrna_struct_CreatePyObject(&newptr); + } + } + else if (PyTuple_Check(key_ob)) { + PyObject *ret = pyrna_prop_collection_subscript_str_lib_pair( + self, key_ob, "bpy_prop_collection.get((id, lib))", false); + if (ret) { + return ret; + } + } + else { + PyErr_Format(PyExc_KeyError, + "bpy_prop_collection.get(key, ...): key must be a string or tuple, not %.200s", + Py_TYPE(key_ob)->tp_name); + } - return Py_INCREF_RET(def); + return Py_INCREF_RET(def); } PyDoc_STRVAR(pyrna_prop_collection_find_doc, -".. method:: find(key)\n" -"\n" -" Returns the index of a key in a collection or -1 when not found\n" -" (matches pythons string find function of the same name).\n" -"\n" -" :arg key: The identifier for the collection member.\n" -" :type key: string\n" -" :return: index of the key.\n" -" :rtype: int\n" -); + ".. method:: find(key)\n" + "\n" + " Returns the index of a key in a collection or -1 when not found\n" + " (matches pythons string find function of the same name).\n" + "\n" + " :arg key: The identifier for the collection member.\n" + " :type key: string\n" + " :return: index of the key.\n" + " :rtype: int\n"); static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key_ob) { - Py_ssize_t key_len_ssize_t; - const char *key = _PyUnicode_AsStringAndSize(key_ob, &key_len_ssize_t); - const int key_len = (int)key_len_ssize_t; /* comare with same type */ - - char name[256], *nameptr; - int namelen; - int i = 0; - int index = -1; - - PYRNA_PROP_CHECK_OBJ(self); - - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); - - if (nameptr) { - if ((key_len == namelen) && memcmp(nameptr, key, key_len) == 0) { - index = i; - break; - } - - if (name != nameptr) { - MEM_freeN(nameptr); - } - } - - i++; - } - RNA_PROP_END; - - return PyLong_FromLong(index); -} - -static bool foreach_attr_type( - BPy_PropertyRNA *self, const char *attr, - /* values to assign */ - RawPropertyType *raw_type, int *attr_tot, bool *attr_signed) -{ - PropertyRNA *prop; - bool attr_ok = true; - *raw_type = PROP_RAW_UNSET; - *attr_tot = 0; - *attr_signed = false; - - /* note: this is fail with zero length lists, so don't let this get caled in that case */ - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - prop = RNA_struct_find_property(&itemptr, attr); - if (prop) { - *raw_type = RNA_property_raw_type(prop); - *attr_tot = RNA_property_array_length(&itemptr, prop); - *attr_signed = (RNA_property_subtype(prop) != PROP_UNSIGNED); - } - else { - attr_ok = false; - } - break; - } - RNA_PROP_END; - - return attr_ok; + Py_ssize_t key_len_ssize_t; + const char *key = _PyUnicode_AsStringAndSize(key_ob, &key_len_ssize_t); + const int key_len = (int)key_len_ssize_t; /* comare with same type */ + + char name[256], *nameptr; + int namelen; + int i = 0; + int index = -1; + + PYRNA_PROP_CHECK_OBJ(self); + + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); + + if (nameptr) { + if ((key_len == namelen) && memcmp(nameptr, key, key_len) == 0) { + index = i; + break; + } + + if (name != nameptr) { + MEM_freeN(nameptr); + } + } + + i++; + } + RNA_PROP_END; + + return PyLong_FromLong(index); +} + +static bool foreach_attr_type(BPy_PropertyRNA *self, + const char *attr, + /* values to assign */ + RawPropertyType *raw_type, + int *attr_tot, + bool *attr_signed) +{ + PropertyRNA *prop; + bool attr_ok = true; + *raw_type = PROP_RAW_UNSET; + *attr_tot = 0; + *attr_signed = false; + + /* note: this is fail with zero length lists, so don't let this get caled in that case */ + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + prop = RNA_struct_find_property(&itemptr, attr); + if (prop) { + *raw_type = RNA_property_raw_type(prop); + *attr_tot = RNA_property_array_length(&itemptr, prop); + *attr_signed = (RNA_property_subtype(prop) != PROP_UNSIGNED); + } + else { + attr_ok = false; + } + break; + } + RNA_PROP_END; + + return attr_ok; } /* pyrna_prop_collection_foreach_get/set both use this */ -static int foreach_parse_args( - BPy_PropertyRNA *self, PyObject *args, - - /* values to assign */ - const char **attr, PyObject **seq, int *tot, int *size, - RawPropertyType *raw_type, int *attr_tot, bool *attr_signed) +static int foreach_parse_args(BPy_PropertyRNA *self, + PyObject *args, + + /* values to assign */ + const char **attr, + PyObject **seq, + int *tot, + int *size, + RawPropertyType *raw_type, + int *attr_tot, + bool *attr_signed) { #if 0 - int array_tot; - int target_tot; + int array_tot; + int target_tot; #endif - *size = *attr_tot = 0; - *attr_signed = false; - *raw_type = PROP_RAW_UNSET; - - if (!PyArg_ParseTuple(args, "sO:foreach_get/set", attr, seq)) { - return -1; - } - - if (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq)) { - PyErr_Format(PyExc_TypeError, - "foreach_get/set expected second argument to be a sequence or buffer, not a %.200s", - Py_TYPE(*seq)->tp_name); - return -1; - } - - *tot = PySequence_Size(*seq); /* TODO - buffer may not be a sequence! array.array() is tho. */ - - if (*tot > 0) { - if (!foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed)) { - PyErr_Format(PyExc_AttributeError, - "foreach_get/set '%.200s.%200s[...]' elements have no attribute '%.200s'", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), *attr); - return -1; - } - *size = RNA_raw_type_sizeof(*raw_type); - -#if 0 /* works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks */ - if ((*attr_tot) < 1) { - *attr_tot = 1; - } - - if (RNA_property_type(self->prop) == PROP_COLLECTION) { - array_tot = RNA_property_collection_length(&self->ptr, self->prop); - } - else { - array_tot = RNA_property_array_length(&self->ptr, self->prop); - } - - - target_tot = array_tot * (*attr_tot); - - /* rna_access.c - rna_raw_access(...) uses this same method */ - if (target_tot != (*tot)) { - PyErr_Format(PyExc_TypeError, - "foreach_get(attr, sequence) sequence length mismatch given %d, needed %d", - *tot, target_tot); - return -1; - } + *size = *attr_tot = 0; + *attr_signed = false; + *raw_type = PROP_RAW_UNSET; + + if (!PyArg_ParseTuple(args, "sO:foreach_get/set", attr, seq)) { + return -1; + } + + if (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq)) { + PyErr_Format( + PyExc_TypeError, + "foreach_get/set expected second argument to be a sequence or buffer, not a %.200s", + Py_TYPE(*seq)->tp_name); + return -1; + } + + *tot = PySequence_Size(*seq); /* TODO - buffer may not be a sequence! array.array() is tho. */ + + if (*tot > 0) { + if (!foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed)) { + PyErr_Format(PyExc_AttributeError, + "foreach_get/set '%.200s.%200s[...]' elements have no attribute '%.200s'", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop), + *attr); + return -1; + } + *size = RNA_raw_type_sizeof(*raw_type); + +#if 0 /* works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks */ + if ((*attr_tot) < 1) { + *attr_tot = 1; + } + + if (RNA_property_type(self->prop) == PROP_COLLECTION) { + array_tot = RNA_property_collection_length(&self->ptr, self->prop); + } + else { + array_tot = RNA_property_array_length(&self->ptr, self->prop); + } + + + target_tot = array_tot * (*attr_tot); + + /* rna_access.c - rna_raw_access(...) uses this same method */ + if (target_tot != (*tot)) { + PyErr_Format(PyExc_TypeError, + "foreach_get(attr, sequence) sequence length mismatch given %d, needed %d", + *tot, target_tot); + return -1; + } #endif - } + } - /* check 'attr_tot' otherwise we don't know if any values were set - * this isn't ideal because it means running on an empty list may fail silently when its not compatible. */ - if (*size == 0 && *attr_tot != 0) { - PyErr_SetString(PyExc_AttributeError, "attribute does not support foreach method"); - return -1; - } - return 0; + /* check 'attr_tot' otherwise we don't know if any values were set + * this isn't ideal because it means running on an empty list may fail silently when its not compatible. */ + if (*size == 0 && *attr_tot != 0) { + PyErr_SetString(PyExc_AttributeError, "attribute does not support foreach method"); + return -1; + } + return 0; } static bool foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, const char *format) { - char f = format ? *format : 'B'; /* B is assumed when not set */ - - switch (raw_type) { - case PROP_RAW_CHAR: - if (attr_signed) { - return (f == 'b') ? 1 : 0; - } - else { - return (f == 'B') ? 1 : 0; - } - case PROP_RAW_SHORT: - if (attr_signed) { - return (f == 'h') ? 1 : 0; - } - else { - return (f == 'H') ? 1 : 0; - } - case PROP_RAW_INT: - if (attr_signed) { - return (f == 'i') ? 1 : 0; - } - else { - return (f == 'I') ? 1 : 0; - } - case PROP_RAW_BOOLEAN: - return (f == '?') ? 1 : 0; - case PROP_RAW_FLOAT: - return (f == 'f') ? 1 : 0; - case PROP_RAW_DOUBLE: - return (f == 'd') ? 1 : 0; - case PROP_RAW_UNSET: - return 0; - } - - return 0; + char f = format ? *format : 'B'; /* B is assumed when not set */ + + switch (raw_type) { + case PROP_RAW_CHAR: + if (attr_signed) { + return (f == 'b') ? 1 : 0; + } + else { + return (f == 'B') ? 1 : 0; + } + case PROP_RAW_SHORT: + if (attr_signed) { + return (f == 'h') ? 1 : 0; + } + else { + return (f == 'H') ? 1 : 0; + } + case PROP_RAW_INT: + if (attr_signed) { + return (f == 'i') ? 1 : 0; + } + else { + return (f == 'I') ? 1 : 0; + } + case PROP_RAW_BOOLEAN: + return (f == '?') ? 1 : 0; + case PROP_RAW_FLOAT: + return (f == 'f') ? 1 : 0; + case PROP_RAW_DOUBLE: + return (f == 'd') ? 1 : 0; + case PROP_RAW_UNSET: + return 0; + } + + return 0; } static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) { - PyObject *item = NULL; - int i = 0, ok = 0; - bool buffer_is_compat; - void *array = NULL; - - /* get/set both take the same args currently */ - const char *attr; - PyObject *seq; - int tot, size, attr_tot; - bool attr_signed; - RawPropertyType raw_type; - - if (foreach_parse_args(self, args, &attr, &seq, &tot, &size, &raw_type, &attr_tot, &attr_signed) == -1) { - return NULL; - } - - if (tot == 0) { - Py_RETURN_NONE; - } - - - - if (set) { /* get the array from python */ - buffer_is_compat = false; - if (PyObject_CheckBuffer(seq)) { - Py_buffer buf; - PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); - - /* check if the buffer matches */ - - buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); - - if (buffer_is_compat) { - ok = RNA_property_collection_raw_set(NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); - } - - PyBuffer_Release(&buf); - } - - /* could not use the buffer, fallback to sequence */ - if (!buffer_is_compat) { - array = PyMem_Malloc(size * tot); - - for ( ; i < tot; i++) { - item = PySequence_GetItem(seq, i); - switch (raw_type) { - case PROP_RAW_CHAR: - ((char *)array)[i] = (char)PyLong_AsLong(item); - break; - case PROP_RAW_SHORT: - ((short *)array)[i] = (short)PyLong_AsLong(item); - break; - case PROP_RAW_INT: - ((int *)array)[i] = (int)PyLong_AsLong(item); - break; - case PROP_RAW_BOOLEAN: - ((bool *)array)[i] = (int)PyLong_AsLong(item) != 0; - break; - case PROP_RAW_FLOAT: - ((float *)array)[i] = (float)PyFloat_AsDouble(item); - break; - case PROP_RAW_DOUBLE: - ((double *)array)[i] = (double)PyFloat_AsDouble(item); - break; - case PROP_RAW_UNSET: - /* should never happen */ - BLI_assert(!"Invalid array type - set"); - break; - } - - Py_DECREF(item); - } - - ok = RNA_property_collection_raw_set(NULL, &self->ptr, self->prop, attr, array, raw_type, tot); - } - } - else { - buffer_is_compat = false; - if (PyObject_CheckBuffer(seq)) { - Py_buffer buf; - PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); - - /* check if the buffer matches, TODO - signed/unsigned types */ - - buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); - - if (buffer_is_compat) { - ok = RNA_property_collection_raw_get(NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); - } - - PyBuffer_Release(&buf); - } - - /* could not use the buffer, fallback to sequence */ - if (!buffer_is_compat) { - array = PyMem_Malloc(size * tot); - - ok = RNA_property_collection_raw_get(NULL, &self->ptr, self->prop, attr, array, raw_type, tot); - - if (!ok) { - /* skip the loop */ - i = tot; - } - - for ( ; i < tot; i++) { - - switch (raw_type) { - case PROP_RAW_CHAR: - item = PyLong_FromLong((long) ((char *)array)[i]); - break; - case PROP_RAW_SHORT: - item = PyLong_FromLong((long) ((short *)array)[i]); - break; - case PROP_RAW_INT: - item = PyLong_FromLong((long) ((int *)array)[i]); - break; - case PROP_RAW_FLOAT: - item = PyFloat_FromDouble((double) ((float *)array)[i]); - break; - case PROP_RAW_DOUBLE: - item = PyFloat_FromDouble((double) ((double *)array)[i]); - break; - case PROP_RAW_BOOLEAN: - item = PyBool_FromLong((long) ((bool *)array)[i]); - break; - default: /* PROP_RAW_UNSET */ - /* should never happen */ - BLI_assert(!"Invalid array type - get"); - item = Py_None; - Py_INCREF(item); - break; - } - - PySequence_SetItem(seq, i, item); - Py_DECREF(item); - } - } - } - - if (array) { - PyMem_Free(array); - } - - if (PyErr_Occurred()) { - /* Maybe we could make our own error */ - PyErr_Print(); - PyErr_SetString(PyExc_TypeError, "couldn't access the py sequence"); - return NULL; - } - if (!ok) { - PyErr_SetString(PyExc_RuntimeError, "internal error setting the array"); - return NULL; - } - - Py_RETURN_NONE; + PyObject *item = NULL; + int i = 0, ok = 0; + bool buffer_is_compat; + void *array = NULL; + + /* get/set both take the same args currently */ + const char *attr; + PyObject *seq; + int tot, size, attr_tot; + bool attr_signed; + RawPropertyType raw_type; + + if (foreach_parse_args( + self, args, &attr, &seq, &tot, &size, &raw_type, &attr_tot, &attr_signed) == -1) { + return NULL; + } + + if (tot == 0) { + Py_RETURN_NONE; + } + + if (set) { /* get the array from python */ + buffer_is_compat = false; + if (PyObject_CheckBuffer(seq)) { + Py_buffer buf; + PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); + + /* check if the buffer matches */ + + buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); + + if (buffer_is_compat) { + ok = RNA_property_collection_raw_set( + NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); + } + + PyBuffer_Release(&buf); + } + + /* could not use the buffer, fallback to sequence */ + if (!buffer_is_compat) { + array = PyMem_Malloc(size * tot); + + for (; i < tot; i++) { + item = PySequence_GetItem(seq, i); + switch (raw_type) { + case PROP_RAW_CHAR: + ((char *)array)[i] = (char)PyLong_AsLong(item); + break; + case PROP_RAW_SHORT: + ((short *)array)[i] = (short)PyLong_AsLong(item); + break; + case PROP_RAW_INT: + ((int *)array)[i] = (int)PyLong_AsLong(item); + break; + case PROP_RAW_BOOLEAN: + ((bool *)array)[i] = (int)PyLong_AsLong(item) != 0; + break; + case PROP_RAW_FLOAT: + ((float *)array)[i] = (float)PyFloat_AsDouble(item); + break; + case PROP_RAW_DOUBLE: + ((double *)array)[i] = (double)PyFloat_AsDouble(item); + break; + case PROP_RAW_UNSET: + /* should never happen */ + BLI_assert(!"Invalid array type - set"); + break; + } + + Py_DECREF(item); + } + + ok = RNA_property_collection_raw_set( + NULL, &self->ptr, self->prop, attr, array, raw_type, tot); + } + } + else { + buffer_is_compat = false; + if (PyObject_CheckBuffer(seq)) { + Py_buffer buf; + PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); + + /* check if the buffer matches, TODO - signed/unsigned types */ + + buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); + + if (buffer_is_compat) { + ok = RNA_property_collection_raw_get( + NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); + } + + PyBuffer_Release(&buf); + } + + /* could not use the buffer, fallback to sequence */ + if (!buffer_is_compat) { + array = PyMem_Malloc(size * tot); + + ok = RNA_property_collection_raw_get( + NULL, &self->ptr, self->prop, attr, array, raw_type, tot); + + if (!ok) { + /* skip the loop */ + i = tot; + } + + for (; i < tot; i++) { + + switch (raw_type) { + case PROP_RAW_CHAR: + item = PyLong_FromLong((long)((char *)array)[i]); + break; + case PROP_RAW_SHORT: + item = PyLong_FromLong((long)((short *)array)[i]); + break; + case PROP_RAW_INT: + item = PyLong_FromLong((long)((int *)array)[i]); + break; + case PROP_RAW_FLOAT: + item = PyFloat_FromDouble((double)((float *)array)[i]); + break; + case PROP_RAW_DOUBLE: + item = PyFloat_FromDouble((double)((double *)array)[i]); + break; + case PROP_RAW_BOOLEAN: + item = PyBool_FromLong((long)((bool *)array)[i]); + break; + default: /* PROP_RAW_UNSET */ + /* should never happen */ + BLI_assert(!"Invalid array type - get"); + item = Py_None; + Py_INCREF(item); + break; + } + + PySequence_SetItem(seq, i, item); + Py_DECREF(item); + } + } + } + + if (array) { + PyMem_Free(array); + } + + if (PyErr_Occurred()) { + /* Maybe we could make our own error */ + PyErr_Print(); + PyErr_SetString(PyExc_TypeError, "couldn't access the py sequence"); + return NULL; + } + if (!ok) { + PyErr_SetString(PyExc_RuntimeError, "internal error setting the array"); + return NULL; + } + + Py_RETURN_NONE; } PyDoc_STRVAR(pyrna_prop_collection_foreach_get_doc, -".. method:: foreach_get(attr, seq)\n" -"\n" -" This is a function to give fast access to attributes within a collection.\n" -); + ".. method:: foreach_get(attr, seq)\n" + "\n" + " This is a function to give fast access to attributes within a collection.\n"); static PyObject *pyrna_prop_collection_foreach_get(BPy_PropertyRNA *self, PyObject *args) { - PYRNA_PROP_CHECK_OBJ(self); + PYRNA_PROP_CHECK_OBJ(self); - return foreach_getset(self, args, 0); + return foreach_getset(self, args, 0); } PyDoc_STRVAR(pyrna_prop_collection_foreach_set_doc, -".. method:: foreach_set(attr, seq)\n" -"\n" -" This is a function to give fast access to attributes within a collection.\n" -); + ".. method:: foreach_set(attr, seq)\n" + "\n" + " This is a function to give fast access to attributes within a collection.\n"); static PyObject *pyrna_prop_collection_foreach_set(BPy_PropertyRNA *self, PyObject *args) { - PYRNA_PROP_CHECK_OBJ(self); + PYRNA_PROP_CHECK_OBJ(self); - return foreach_getset(self, args, 1); + return foreach_getset(self, args, 1); } /* A bit of a kludge, make a list out of a collection or array, * then return the lists iter function, not especially fast but convenient for now */ static PyObject *pyrna_prop_array_iter(BPy_PropertyArrayRNA *self) { - /* Try get values from a collection */ - PyObject *ret; - PyObject *iter = NULL; - int len; + /* Try get values from a collection */ + PyObject *ret; + PyObject *iter = NULL; + int len; - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); - len = pyrna_prop_array_length(self); - ret = pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len); + len = pyrna_prop_array_length(self); + ret = pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len); - /* we know this is a list so no need to PyIter_Check - * otherwise it could be NULL (unlikely) if conversion failed */ - if (ret) { - iter = PyObject_GetIter(ret); - Py_DECREF(ret); - } + /* we know this is a list so no need to PyIter_Check + * otherwise it could be NULL (unlikely) if conversion failed */ + if (ret) { + iter = PyObject_GetIter(ret); + Py_DECREF(ret); + } - return iter; + return iter; } static PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self); @@ -5331,348 +5387,400 @@ static PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self); #ifndef USE_PYRNA_ITER static PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self) { - /* Try get values from a collection */ - PyObject *ret; - PyObject *iter = NULL; - ret = pyrna_prop_collection_values(self); + /* Try get values from a collection */ + PyObject *ret; + PyObject *iter = NULL; + ret = pyrna_prop_collection_values(self); - /* we know this is a list so no need to PyIter_Check - * otherwise it could be NULL (unlikely) if conversion failed */ - if (ret) { - iter = PyObject_GetIter(ret); - Py_DECREF(ret); - } + /* we know this is a list so no need to PyIter_Check + * otherwise it could be NULL (unlikely) if conversion failed */ + if (ret) { + iter = PyObject_GetIter(ret); + Py_DECREF(ret); + } - return iter; + return iter; } #endif /* # !USE_PYRNA_ITER */ static struct PyMethodDef pyrna_struct_methods[] = { - /* only for PointerRNA's with ID'props */ - {"keys", (PyCFunction)pyrna_struct_keys, METH_NOARGS, pyrna_struct_keys_doc}, - {"values", (PyCFunction)pyrna_struct_values, METH_NOARGS, pyrna_struct_values_doc}, - {"items", (PyCFunction)pyrna_struct_items, METH_NOARGS, pyrna_struct_items_doc}, - - {"get", (PyCFunction)pyrna_struct_get, METH_VARARGS, pyrna_struct_get_doc}, - {"pop", (PyCFunction)pyrna_struct_pop, METH_VARARGS, pyrna_struct_pop_doc}, - - {"as_pointer", (PyCFunction)pyrna_struct_as_pointer, METH_NOARGS, pyrna_struct_as_pointer_doc}, - - /* bpy_rna_anim.c */ - {"keyframe_insert", (PyCFunction)pyrna_struct_keyframe_insert, METH_VARARGS | METH_KEYWORDS, pyrna_struct_keyframe_insert_doc}, - {"keyframe_delete", (PyCFunction)pyrna_struct_keyframe_delete, METH_VARARGS | METH_KEYWORDS, pyrna_struct_keyframe_delete_doc}, - {"driver_add", (PyCFunction)pyrna_struct_driver_add, METH_VARARGS, pyrna_struct_driver_add_doc}, - {"driver_remove", (PyCFunction)pyrna_struct_driver_remove, METH_VARARGS, pyrna_struct_driver_remove_doc}, - - {"is_property_set", (PyCFunction)pyrna_struct_is_property_set, METH_VARARGS, pyrna_struct_is_property_set_doc}, - {"property_unset", (PyCFunction)pyrna_struct_property_unset, METH_VARARGS, pyrna_struct_property_unset_doc}, - {"is_property_hidden", (PyCFunction)pyrna_struct_is_property_hidden, METH_VARARGS, pyrna_struct_is_property_hidden_doc}, - {"is_property_readonly", (PyCFunction)pyrna_struct_is_property_readonly, METH_VARARGS, pyrna_struct_is_property_readonly_doc}, - {"is_property_overridable_static", (PyCFunction)pyrna_struct_is_property_overridable_static, METH_VARARGS, pyrna_struct_is_property_overridable_static_doc}, - {"property_overridable_static_set", (PyCFunction)pyrna_struct_property_overridable_static_set, METH_VARARGS, pyrna_struct_property_overridable_static_set_doc}, - {"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc}, - {"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc}, - {"type_recast", (PyCFunction)pyrna_struct_type_recast, METH_NOARGS, pyrna_struct_type_recast_doc}, - {"bl_rna_get_subclass_py", (PyCFunction) pyrna_struct_bl_rna_get_subclass_py, METH_VARARGS | METH_CLASS, pyrna_struct_bl_rna_get_subclass_py_doc}, - {"bl_rna_get_subclass", (PyCFunction) pyrna_struct_bl_rna_get_subclass, METH_VARARGS | METH_CLASS, pyrna_struct_bl_rna_get_subclass_doc}, - {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL}, - - /* experimental */ - /* unused for now */ + /* only for PointerRNA's with ID'props */ + {"keys", (PyCFunction)pyrna_struct_keys, METH_NOARGS, pyrna_struct_keys_doc}, + {"values", (PyCFunction)pyrna_struct_values, METH_NOARGS, pyrna_struct_values_doc}, + {"items", (PyCFunction)pyrna_struct_items, METH_NOARGS, pyrna_struct_items_doc}, + + {"get", (PyCFunction)pyrna_struct_get, METH_VARARGS, pyrna_struct_get_doc}, + {"pop", (PyCFunction)pyrna_struct_pop, METH_VARARGS, pyrna_struct_pop_doc}, + + {"as_pointer", (PyCFunction)pyrna_struct_as_pointer, METH_NOARGS, pyrna_struct_as_pointer_doc}, + + /* bpy_rna_anim.c */ + {"keyframe_insert", + (PyCFunction)pyrna_struct_keyframe_insert, + METH_VARARGS | METH_KEYWORDS, + pyrna_struct_keyframe_insert_doc}, + {"keyframe_delete", + (PyCFunction)pyrna_struct_keyframe_delete, + METH_VARARGS | METH_KEYWORDS, + pyrna_struct_keyframe_delete_doc}, + {"driver_add", + (PyCFunction)pyrna_struct_driver_add, + METH_VARARGS, + pyrna_struct_driver_add_doc}, + {"driver_remove", + (PyCFunction)pyrna_struct_driver_remove, + METH_VARARGS, + pyrna_struct_driver_remove_doc}, + + {"is_property_set", + (PyCFunction)pyrna_struct_is_property_set, + METH_VARARGS, + pyrna_struct_is_property_set_doc}, + {"property_unset", + (PyCFunction)pyrna_struct_property_unset, + METH_VARARGS, + pyrna_struct_property_unset_doc}, + {"is_property_hidden", + (PyCFunction)pyrna_struct_is_property_hidden, + METH_VARARGS, + pyrna_struct_is_property_hidden_doc}, + {"is_property_readonly", + (PyCFunction)pyrna_struct_is_property_readonly, + METH_VARARGS, + pyrna_struct_is_property_readonly_doc}, + {"is_property_overridable_static", + (PyCFunction)pyrna_struct_is_property_overridable_static, + METH_VARARGS, + pyrna_struct_is_property_overridable_static_doc}, + {"property_overridable_static_set", + (PyCFunction)pyrna_struct_property_overridable_static_set, + METH_VARARGS, + pyrna_struct_property_overridable_static_set_doc}, + {"path_resolve", + (PyCFunction)pyrna_struct_path_resolve, + METH_VARARGS, + pyrna_struct_path_resolve_doc}, + {"path_from_id", + (PyCFunction)pyrna_struct_path_from_id, + METH_VARARGS, + pyrna_struct_path_from_id_doc}, + {"type_recast", + (PyCFunction)pyrna_struct_type_recast, + METH_NOARGS, + pyrna_struct_type_recast_doc}, + {"bl_rna_get_subclass_py", + (PyCFunction)pyrna_struct_bl_rna_get_subclass_py, + METH_VARARGS | METH_CLASS, + pyrna_struct_bl_rna_get_subclass_py_doc}, + {"bl_rna_get_subclass", + (PyCFunction)pyrna_struct_bl_rna_get_subclass, + METH_VARARGS | METH_CLASS, + pyrna_struct_bl_rna_get_subclass_doc}, + {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL}, + +/* experimental */ +/* unused for now */ #if 0 - {"callback_add", (PyCFunction)pyrna_callback_add, METH_VARARGS, NULL}, - {"callback_remove", (PyCFunction)pyrna_callback_remove, METH_VARARGS, NULL}, + {"callback_add", (PyCFunction)pyrna_callback_add, METH_VARARGS, NULL}, + {"callback_remove", (PyCFunction)pyrna_callback_remove, METH_VARARGS, NULL}, - {"callback_add", (PyCFunction)pyrna_callback_classmethod_add, METH_VARARGS | METH_CLASS, NULL}, - {"callback_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_CLASS, NULL}, + {"callback_add", (PyCFunction)pyrna_callback_classmethod_add, METH_VARARGS | METH_CLASS, NULL}, + {"callback_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_CLASS, NULL}, #endif - {NULL, NULL, 0, NULL}, + {NULL, NULL, 0, NULL}, }; static struct PyMethodDef pyrna_prop_methods[] = { - {"path_from_id", (PyCFunction)pyrna_prop_path_from_id, METH_NOARGS, pyrna_prop_path_from_id_doc}, - {"as_bytes", (PyCFunction)pyrna_prop_as_bytes, METH_NOARGS, pyrna_prop_as_bytes_doc}, - {"update", (PyCFunction)pyrna_prop_update, METH_NOARGS, pyrna_prop_update_doc}, - {"__dir__", (PyCFunction)pyrna_prop_dir, METH_NOARGS, NULL}, - {NULL, NULL, 0, NULL}, + {"path_from_id", + (PyCFunction)pyrna_prop_path_from_id, + METH_NOARGS, + pyrna_prop_path_from_id_doc}, + {"as_bytes", (PyCFunction)pyrna_prop_as_bytes, METH_NOARGS, pyrna_prop_as_bytes_doc}, + {"update", (PyCFunction)pyrna_prop_update, METH_NOARGS, pyrna_prop_update_doc}, + {"__dir__", (PyCFunction)pyrna_prop_dir, METH_NOARGS, NULL}, + {NULL, NULL, 0, NULL}, }; static struct PyMethodDef pyrna_prop_array_methods[] = { - {NULL, NULL, 0, NULL}, + {NULL, NULL, 0, NULL}, }; static struct PyMethodDef pyrna_prop_collection_methods[] = { - {"foreach_get", (PyCFunction)pyrna_prop_collection_foreach_get, METH_VARARGS, pyrna_prop_collection_foreach_get_doc}, - {"foreach_set", (PyCFunction)pyrna_prop_collection_foreach_set, METH_VARARGS, pyrna_prop_collection_foreach_set_doc}, - - {"keys", (PyCFunction)pyrna_prop_collection_keys, METH_NOARGS, pyrna_prop_collection_keys_doc}, - {"items", (PyCFunction)pyrna_prop_collection_items, METH_NOARGS, pyrna_prop_collection_items_doc}, - {"values", (PyCFunction)pyrna_prop_collection_values, METH_NOARGS, pyrna_prop_collection_values_doc}, - - {"get", (PyCFunction)pyrna_prop_collection_get, METH_VARARGS, pyrna_prop_collection_get_doc}, - {"find", (PyCFunction)pyrna_prop_collection_find, METH_O, pyrna_prop_collection_find_doc}, - {NULL, NULL, 0, NULL}, + {"foreach_get", + (PyCFunction)pyrna_prop_collection_foreach_get, + METH_VARARGS, + pyrna_prop_collection_foreach_get_doc}, + {"foreach_set", + (PyCFunction)pyrna_prop_collection_foreach_set, + METH_VARARGS, + pyrna_prop_collection_foreach_set_doc}, + + {"keys", (PyCFunction)pyrna_prop_collection_keys, METH_NOARGS, pyrna_prop_collection_keys_doc}, + {"items", + (PyCFunction)pyrna_prop_collection_items, + METH_NOARGS, + pyrna_prop_collection_items_doc}, + {"values", + (PyCFunction)pyrna_prop_collection_values, + METH_NOARGS, + pyrna_prop_collection_values_doc}, + + {"get", (PyCFunction)pyrna_prop_collection_get, METH_VARARGS, pyrna_prop_collection_get_doc}, + {"find", (PyCFunction)pyrna_prop_collection_find, METH_O, pyrna_prop_collection_find_doc}, + {NULL, NULL, 0, NULL}, }; static struct PyMethodDef pyrna_prop_collection_idprop_methods[] = { - {"add", (PyCFunction)pyrna_prop_collection_idprop_add, METH_NOARGS, NULL}, - {"remove", (PyCFunction)pyrna_prop_collection_idprop_remove, METH_O, NULL}, - {"clear", (PyCFunction)pyrna_prop_collection_idprop_clear, METH_NOARGS, NULL}, - {"move", (PyCFunction)pyrna_prop_collection_idprop_move, METH_VARARGS, NULL}, - {NULL, NULL, 0, NULL}, + {"add", (PyCFunction)pyrna_prop_collection_idprop_add, METH_NOARGS, NULL}, + {"remove", (PyCFunction)pyrna_prop_collection_idprop_remove, METH_O, NULL}, + {"clear", (PyCFunction)pyrna_prop_collection_idprop_clear, METH_NOARGS, NULL}, + {"move", (PyCFunction)pyrna_prop_collection_idprop_move, METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL}, }; /* only needed for subtyping, so a new class gets a valid BPy_StructRNA * todo - also accept useful args */ static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds)) { - if (PyTuple_GET_SIZE(args) == 1) { - BPy_StructRNA *base = (BPy_StructRNA *)PyTuple_GET_ITEM(args, 0); - if (Py_TYPE(base) == type) { - Py_INCREF(base); - return (PyObject *)base; - } - else if (PyType_IsSubtype(Py_TYPE(base), &pyrna_struct_Type)) { - /* this almost never runs, only when using user defined subclasses of built-in object. - * this isn't common since its NOT related to registerable subclasses. eg: - * - * >>> class MyObSubclass(bpy.types.Object): - * ... def test_func(self): - * ... print(100) - * ... - * >>> myob = MyObSubclass(bpy.context.object) - * >>> myob.test_func() - * 100 - * - * Keep this since it could be useful. - */ - BPy_StructRNA *ret; - if ((ret = (BPy_StructRNA *)type->tp_alloc(type, 0))) { - ret->ptr = base->ptr; - } - /* pass on exception & NULL if tp_alloc fails */ - return (PyObject *)ret; - } - - /* error, invalid type given */ - PyErr_Format(PyExc_TypeError, - "bpy_struct.__new__(type): type '%.200s' is not a subtype of bpy_struct", - type->tp_name); - return NULL; - } - else { - PyErr_Format(PyExc_TypeError, - "bpy_struct.__new__(type): expected a single argument"); - return NULL; - } + if (PyTuple_GET_SIZE(args) == 1) { + BPy_StructRNA *base = (BPy_StructRNA *)PyTuple_GET_ITEM(args, 0); + if (Py_TYPE(base) == type) { + Py_INCREF(base); + return (PyObject *)base; + } + else if (PyType_IsSubtype(Py_TYPE(base), &pyrna_struct_Type)) { + /* this almost never runs, only when using user defined subclasses of built-in object. + * this isn't common since its NOT related to registerable subclasses. eg: + * + * >>> class MyObSubclass(bpy.types.Object): + * ... def test_func(self): + * ... print(100) + * ... + * >>> myob = MyObSubclass(bpy.context.object) + * >>> myob.test_func() + * 100 + * + * Keep this since it could be useful. + */ + BPy_StructRNA *ret; + if ((ret = (BPy_StructRNA *)type->tp_alloc(type, 0))) { + ret->ptr = base->ptr; + } + /* pass on exception & NULL if tp_alloc fails */ + return (PyObject *)ret; + } + + /* error, invalid type given */ + PyErr_Format(PyExc_TypeError, + "bpy_struct.__new__(type): type '%.200s' is not a subtype of bpy_struct", + type->tp_name); + return NULL; + } + else { + PyErr_Format(PyExc_TypeError, "bpy_struct.__new__(type): expected a single argument"); + return NULL; + } } /* only needed for subtyping, so a new class gets a valid BPy_StructRNA * todo - also accept useful args */ static PyObject *pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds)) { - BPy_PropertyRNA *base; - - if (!PyArg_ParseTuple(args, "O!:bpy_prop.__new__", &pyrna_prop_Type, &base)) { - return NULL; - } - - if (type == Py_TYPE(base)) { - return Py_INCREF_RET((PyObject *)base); - } - else if (PyType_IsSubtype(type, &pyrna_prop_Type)) { - BPy_PropertyRNA *ret = (BPy_PropertyRNA *) type->tp_alloc(type, 0); - ret->ptr = base->ptr; - ret->prop = base->prop; - return (PyObject *)ret; - } - else { - PyErr_Format(PyExc_TypeError, - "bpy_prop.__new__(type): type '%.200s' is not a subtype of bpy_prop", - type->tp_name); - return NULL; - } + BPy_PropertyRNA *base; + + if (!PyArg_ParseTuple(args, "O!:bpy_prop.__new__", &pyrna_prop_Type, &base)) { + return NULL; + } + + if (type == Py_TYPE(base)) { + return Py_INCREF_RET((PyObject *)base); + } + else if (PyType_IsSubtype(type, &pyrna_prop_Type)) { + BPy_PropertyRNA *ret = (BPy_PropertyRNA *)type->tp_alloc(type, 0); + ret->ptr = base->ptr; + ret->prop = base->prop; + return (PyObject *)ret; + } + else { + PyErr_Format(PyExc_TypeError, + "bpy_prop.__new__(type): type '%.200s' is not a subtype of bpy_prop", + type->tp_name); + return NULL; + } } static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) { - PyObject *ret; - const int type = RNA_property_type(prop); - const int flag = RNA_property_flag(prop); - const int flag_parameter = RNA_parameter_flag(prop); - - if (RNA_property_array_check(prop)) { - int a, len; - - if (flag & PROP_DYNAMIC) { - ParameterDynAlloc *data_alloc = data; - len = data_alloc->array_tot; - data = data_alloc->array; - } - else { - len = RNA_property_array_length(ptr, prop); - } - - /* resolve the array from a new pytype */ - - /* kazanbas: TODO make multidim sequences here */ - - switch (type) { - case PROP_BOOLEAN: - ret = PyTuple_New(len); - for (a = 0; a < len; a++) { - PyTuple_SET_ITEM(ret, a, PyBool_FromLong(((bool *)data)[a])); - } - break; - case PROP_INT: - ret = PyTuple_New(len); - for (a = 0; a < len; a++) { - PyTuple_SET_ITEM(ret, a, PyLong_FromLong(((int *)data)[a])); - } - break; - case PROP_FLOAT: - switch (RNA_property_subtype(prop)) { + PyObject *ret; + const int type = RNA_property_type(prop); + const int flag = RNA_property_flag(prop); + const int flag_parameter = RNA_parameter_flag(prop); + + if (RNA_property_array_check(prop)) { + int a, len; + + if (flag & PROP_DYNAMIC) { + ParameterDynAlloc *data_alloc = data; + len = data_alloc->array_tot; + data = data_alloc->array; + } + else { + len = RNA_property_array_length(ptr, prop); + } + + /* resolve the array from a new pytype */ + + /* kazanbas: TODO make multidim sequences here */ + + switch (type) { + case PROP_BOOLEAN: + ret = PyTuple_New(len); + for (a = 0; a < len; a++) { + PyTuple_SET_ITEM(ret, a, PyBool_FromLong(((bool *)data)[a])); + } + break; + case PROP_INT: + ret = PyTuple_New(len); + for (a = 0; a < len; a++) { + PyTuple_SET_ITEM(ret, a, PyLong_FromLong(((int *)data)[a])); + } + break; + case PROP_FLOAT: + switch (RNA_property_subtype(prop)) { #ifdef USE_MATHUTILS - case PROP_ALL_VECTOR_SUBTYPES: - ret = Vector_CreatePyObject(data, len, NULL); - break; - case PROP_MATRIX: - if (len == 16) { - ret = Matrix_CreatePyObject(data, 4, 4, NULL); - break; - } - else if (len == 9) { - ret = Matrix_CreatePyObject(data, 3, 3, NULL); - break; - } - ATTR_FALLTHROUGH; + case PROP_ALL_VECTOR_SUBTYPES: + ret = Vector_CreatePyObject(data, len, NULL); + break; + case PROP_MATRIX: + if (len == 16) { + ret = Matrix_CreatePyObject(data, 4, 4, NULL); + break; + } + else if (len == 9) { + ret = Matrix_CreatePyObject(data, 3, 3, NULL); + break; + } + ATTR_FALLTHROUGH; #endif - default: - ret = PyTuple_New(len); - for (a = 0; a < len; a++) { - PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble(((float *)data)[a])); - } - break; - } - break; - default: - PyErr_Format(PyExc_TypeError, - "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", - type); - ret = NULL; - break; - } - } - else { - /* see if we can coerce into a python type - PropertyType */ - switch (type) { - case PROP_BOOLEAN: - ret = PyBool_FromLong(*(bool *)data); - break; - case PROP_INT: - ret = PyLong_FromLong(*(int *)data); - break; - case PROP_FLOAT: - ret = PyFloat_FromDouble(*(float *)data); - break; - case PROP_STRING: - { - const char *data_ch; - PyObject *value_coerce = NULL; - const int subtype = RNA_property_subtype(prop); - - if (flag & PROP_THICK_WRAP) { - data_ch = (char *)data; - } - else { - data_ch = *(char **)data; - } + default: + ret = PyTuple_New(len); + for (a = 0; a < len; a++) { + PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble(((float *)data)[a])); + } + break; + } + break; + default: + PyErr_Format( + PyExc_TypeError, "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", type); + ret = NULL; + break; + } + } + else { + /* see if we can coerce into a python type - PropertyType */ + switch (type) { + case PROP_BOOLEAN: + ret = PyBool_FromLong(*(bool *)data); + break; + case PROP_INT: + ret = PyLong_FromLong(*(int *)data); + break; + case PROP_FLOAT: + ret = PyFloat_FromDouble(*(float *)data); + break; + case PROP_STRING: { + const char *data_ch; + PyObject *value_coerce = NULL; + const int subtype = RNA_property_subtype(prop); + + if (flag & PROP_THICK_WRAP) { + data_ch = (char *)data; + } + else { + data_ch = *(char **)data; + } #ifdef USE_STRING_COERCE - if (subtype == PROP_BYTESTRING) { - ret = PyBytes_FromString(data_ch); - } - else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - ret = PyC_UnicodeFromByte(data_ch); - } - else { - ret = PyUnicode_FromString(data_ch); - } + if (subtype == PROP_BYTESTRING) { + ret = PyBytes_FromString(data_ch); + } + else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { + ret = PyC_UnicodeFromByte(data_ch); + } + else { + ret = PyUnicode_FromString(data_ch); + } #else - if (subtype == PROP_BYTESTRING) { - ret = PyBytes_FromString(buf); - } - else { - ret = PyUnicode_FromString(data_ch); - } + if (subtype == PROP_BYTESTRING) { + ret = PyBytes_FromString(buf); + } + else { + ret = PyUnicode_FromString(data_ch); + } #endif #ifdef USE_STRING_COERCE - Py_XDECREF(value_coerce); + Py_XDECREF(value_coerce); #endif - break; - } - case PROP_ENUM: - { - ret = pyrna_enum_to_py(ptr, prop, *(int *)data); - break; - } - case PROP_POINTER: - { - PointerRNA newptr; - StructRNA *ptype = RNA_property_pointer_type(ptr, prop); - - if (flag_parameter & PARM_RNAPTR) { - /* in this case we get the full ptr */ - newptr = *(PointerRNA *)data; - } - else { - if (RNA_struct_is_ID(ptype)) { - RNA_id_pointer_create(*(void **)data, &newptr); - } - else { - /* note: this is taken from the function's ID pointer - * and will break if a function returns a pointer from - * another ID block, watch this! - it should at least be - * easy to debug since they are all ID's */ - RNA_pointer_create(ptr->id.data, ptype, *(void **)data, &newptr); - } - } - - if (newptr.data) { - ret = pyrna_struct_CreatePyObject(&newptr); - } - else { - ret = Py_None; - Py_INCREF(ret); - } - break; - } - case PROP_COLLECTION: - { - CollectionListBase *lb = (CollectionListBase *)data; - CollectionPointerLink *link; - - ret = PyList_New(0); - - for (link = lb->first; link; link = link->next) { - PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr)); - } - - break; - } - default: - PyErr_Format(PyExc_TypeError, - "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", - type); - ret = NULL; - break; - } - } - - return ret; + break; + } + case PROP_ENUM: { + ret = pyrna_enum_to_py(ptr, prop, *(int *)data); + break; + } + case PROP_POINTER: { + PointerRNA newptr; + StructRNA *ptype = RNA_property_pointer_type(ptr, prop); + + if (flag_parameter & PARM_RNAPTR) { + /* in this case we get the full ptr */ + newptr = *(PointerRNA *)data; + } + else { + if (RNA_struct_is_ID(ptype)) { + RNA_id_pointer_create(*(void **)data, &newptr); + } + else { + /* note: this is taken from the function's ID pointer + * and will break if a function returns a pointer from + * another ID block, watch this! - it should at least be + * easy to debug since they are all ID's */ + RNA_pointer_create(ptr->id.data, ptype, *(void **)data, &newptr); + } + } + + if (newptr.data) { + ret = pyrna_struct_CreatePyObject(&newptr); + } + else { + ret = Py_None; + Py_INCREF(ret); + } + break; + } + case PROP_COLLECTION: { + CollectionListBase *lb = (CollectionListBase *)data; + CollectionPointerLink *link; + + ret = PyList_New(0); + + for (link = lb->first; link; link = link->next) { + PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr)); + } + + break; + } + default: + PyErr_Format(PyExc_TypeError, "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", type); + ret = NULL; + break; + } + } + + return ret; } /* Use to replace PyDict_GetItemString() when the overhead of converting a @@ -5680,954 +5788,963 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat * works on small dict's such as keyword args. */ static PyObject *small_dict_get_item_string(PyObject *dict, const char *key_lookup) { - PyObject *key = NULL; - Py_ssize_t pos = 0; - PyObject *value = NULL; + PyObject *key = NULL; + Py_ssize_t pos = 0; + PyObject *value = NULL; - while (PyDict_Next(dict, &pos, &key, &value)) { - if (PyUnicode_Check(key)) { - if (STREQ(key_lookup, _PyUnicode_AsString(key))) { - return value; - } - } - } + while (PyDict_Next(dict, &pos, &key, &value)) { + if (PyUnicode_Check(key)) { + if (STREQ(key_lookup, _PyUnicode_AsString(key))) { + return value; + } + } + } - return NULL; + return NULL; } static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject *kw) { - /* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here */ - PointerRNA *self_ptr = &self->ptr; - FunctionRNA *self_func = self->func; + /* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here */ + PointerRNA *self_ptr = &self->ptr; + FunctionRNA *self_func = self->func; - PointerRNA funcptr; - ParameterList parms; - ParameterIterator iter; - PropertyRNA *parm; - PyObject *ret, *item; - int i, pyargs_len, pykw_len, parms_len, ret_len, flag_parameter, err = 0, kw_tot = 0; - bool kw_arg; + PointerRNA funcptr; + ParameterList parms; + ParameterIterator iter; + PropertyRNA *parm; + PyObject *ret, *item; + int i, pyargs_len, pykw_len, parms_len, ret_len, flag_parameter, err = 0, kw_tot = 0; + bool kw_arg; - PropertyRNA *pret_single = NULL; - void *retdata_single = NULL; + PropertyRNA *pret_single = NULL; + void *retdata_single = NULL; - /* enable this so all strings are copied and freed after calling. - * this exposes bugs where the pointer to the string is held and re-used */ -// #define DEBUG_STRING_FREE + /* enable this so all strings are copied and freed after calling. + * this exposes bugs where the pointer to the string is held and re-used */ + // #define DEBUG_STRING_FREE #ifdef DEBUG_STRING_FREE - PyObject *string_free_ls = PyList_New(0); + PyObject *string_free_ls = PyList_New(0); #endif - /* Should never happen but it does in rare cases */ - BLI_assert(self_ptr != NULL); + /* Should never happen but it does in rare cases */ + BLI_assert(self_ptr != NULL); - if (self_ptr == NULL) { - PyErr_SetString(PyExc_RuntimeError, "rna functions internal rna pointer is NULL, this is a bug. aborting"); - return NULL; - } + if (self_ptr == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "rna functions internal rna pointer is NULL, this is a bug. aborting"); + return NULL; + } - if (self_func == NULL) { - PyErr_Format(PyExc_RuntimeError, - "%.200s.<unknown>(): rna function internal function is NULL, this is a bug. aborting", - RNA_struct_identifier(self_ptr->type)); - return NULL; - } + if (self_func == NULL) { + PyErr_Format( + PyExc_RuntimeError, + "%.200s.<unknown>(): rna function internal function is NULL, this is a bug. aborting", + RNA_struct_identifier(self_ptr->type)); + return NULL; + } - /* for testing */ + /* for testing */ #if 0 - { - const char *fn; - int lineno; - PyC_FileAndNum(&fn, &lineno); - printf("pyrna_func_call > %.200s.%.200s : %.200s:%d\n", - RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), fn, lineno); - } + { + const char *fn; + int lineno; + PyC_FileAndNum(&fn, &lineno); + printf("pyrna_func_call > %.200s.%.200s : %.200s:%d\n", + RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), fn, lineno); + } #endif - /* include the ID pointer for pyrna_param_to_py() so we can include the - * ID pointer on return values, this only works when returned values have - * the same ID as the functions. */ - RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr); - - pyargs_len = PyTuple_GET_SIZE(args); - pykw_len = kw ? PyDict_Size(kw) : 0; - - RNA_parameter_list_create(&parms, self_ptr, self_func); - RNA_parameter_list_begin(&parms, &iter); - parms_len = RNA_parameter_list_arg_count(&parms); - ret_len = 0; - - if (pyargs_len + pykw_len > parms_len) { - RNA_parameter_list_end(&iter); - PyErr_Format(PyExc_TypeError, - "%.200s.%.200s(): takes at most %d arguments, got %d", - RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), - parms_len, pyargs_len + pykw_len); - err = -1; - } - - /* parse function parameters */ - for (i = 0; iter.valid && err == 0; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - flag_parameter = RNA_parameter_flag(parm); - - /* only useful for single argument returns, we'll need another list loop for multiple */ - if (flag_parameter & PARM_OUTPUT) { - ret_len++; - if (pret_single == NULL) { - pret_single = parm; - retdata_single = iter.data; - } - - continue; - } - - item = NULL; - - if (i < pyargs_len) { - /* New in 2.8x, optional arguments must be keywords. */ - if (UNLIKELY((flag_parameter & PARM_REQUIRED) == 0)) { - PyErr_Format(PyExc_TypeError, - "%.200s.%.200s(): required parameter \"%.200s\" to be a keyword argument!", - RNA_struct_identifier(self_ptr->type), - RNA_function_identifier(self_func), - RNA_property_identifier(parm)); - err = -1; - break; - } - - item = PyTuple_GET_ITEM(args, i); - kw_arg = false; - } - else if (kw != NULL) { + /* include the ID pointer for pyrna_param_to_py() so we can include the + * ID pointer on return values, this only works when returned values have + * the same ID as the functions. */ + RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr); + + pyargs_len = PyTuple_GET_SIZE(args); + pykw_len = kw ? PyDict_Size(kw) : 0; + + RNA_parameter_list_create(&parms, self_ptr, self_func); + RNA_parameter_list_begin(&parms, &iter); + parms_len = RNA_parameter_list_arg_count(&parms); + ret_len = 0; + + if (pyargs_len + pykw_len > parms_len) { + RNA_parameter_list_end(&iter); + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s(): takes at most %d arguments, got %d", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + parms_len, + pyargs_len + pykw_len); + err = -1; + } + + /* parse function parameters */ + for (i = 0; iter.valid && err == 0; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + flag_parameter = RNA_parameter_flag(parm); + + /* only useful for single argument returns, we'll need another list loop for multiple */ + if (flag_parameter & PARM_OUTPUT) { + ret_len++; + if (pret_single == NULL) { + pret_single = parm; + retdata_single = iter.data; + } + + continue; + } + + item = NULL; + + if (i < pyargs_len) { + /* New in 2.8x, optional arguments must be keywords. */ + if (UNLIKELY((flag_parameter & PARM_REQUIRED) == 0)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s(): required parameter \"%.200s\" to be a keyword argument!", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + RNA_property_identifier(parm)); + err = -1; + break; + } + + item = PyTuple_GET_ITEM(args, i); + kw_arg = false; + } + else if (kw != NULL) { #if 0 - item = PyDict_GetItemString(kw, RNA_property_identifier(parm)); /* borrow ref */ + item = PyDict_GetItemString(kw, RNA_property_identifier(parm)); /* borrow ref */ #else - item = small_dict_get_item_string(kw, RNA_property_identifier(parm)); /* borrow ref */ + item = small_dict_get_item_string(kw, RNA_property_identifier(parm)); /* borrow ref */ #endif - if (item) { - kw_tot++; /* make sure invalid keywords are not given */ - } - - kw_arg = true; - } - - i++; /* current argument */ - - if (item == NULL) { - if (flag_parameter & PARM_REQUIRED) { - PyErr_Format(PyExc_TypeError, - "%.200s.%.200s(): required parameter \"%.200s\" not specified", - RNA_struct_identifier(self_ptr->type), - RNA_function_identifier(self_func), - RNA_property_identifier(parm)); - err = -1; - break; - } - else { /* PyDict_GetItemString wont raise an error */ - continue; - } - } + if (item) { + kw_tot++; /* make sure invalid keywords are not given */ + } + + kw_arg = true; + } + + i++; /* current argument */ + + if (item == NULL) { + if (flag_parameter & PARM_REQUIRED) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s(): required parameter \"%.200s\" not specified", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + RNA_property_identifier(parm)); + err = -1; + break; + } + else { /* PyDict_GetItemString wont raise an error */ + continue; + } + } #ifdef DEBUG_STRING_FREE - if (item) { - if (PyUnicode_Check(item)) { - PyList_APPEND(string_free_ls, PyUnicode_FromString(_PyUnicode_AsString(item))); - } - } + if (item) { + if (PyUnicode_Check(item)) { + PyList_APPEND(string_free_ls, PyUnicode_FromString(_PyUnicode_AsString(item))); + } + } #endif - err = pyrna_py_to_prop(&funcptr, parm, iter.data, item, ""); - - if (err != 0) { - /* the error generated isn't that useful, so generate it again with a useful prefix - * could also write a function to prepend to error messages */ - char error_prefix[512]; - PyErr_Clear(); /* re-raise */ - - if (kw_arg == true) { - BLI_snprintf(error_prefix, sizeof(error_prefix), - "%.200s.%.200s(): error with keyword argument \"%.200s\" - ", - RNA_struct_identifier(self_ptr->type), - RNA_function_identifier(self_func), - RNA_property_identifier(parm)); - } - else { - BLI_snprintf(error_prefix, sizeof(error_prefix), - "%.200s.%.200s(): error with argument %d, \"%.200s\" - ", - RNA_struct_identifier(self_ptr->type), - RNA_function_identifier(self_func), - i, - RNA_property_identifier(parm)); - } - - pyrna_py_to_prop(&funcptr, parm, iter.data, item, error_prefix); - - break; - } - } - - RNA_parameter_list_end(&iter); - - /* Check if we gave args that don't exist in the function - * printing the error is slow but it should only happen when developing. - * the if below is quick, checking if it passed less keyword args then we gave. - * (Don't overwrite the error if we have one, otherwise can skip important messages and confuse with args) - */ - if (err == 0 && kw && (pykw_len > kw_tot)) { - PyObject *key, *value; - Py_ssize_t pos = 0; - - DynStr *bad_args = BLI_dynstr_new(); - DynStr *good_args = BLI_dynstr_new(); - - const char *arg_name, *bad_args_str, *good_args_str; - bool found = false, first = true; - - while (PyDict_Next(kw, &pos, &key, &value)) { - - arg_name = _PyUnicode_AsString(key); - found = false; - - if (arg_name == NULL) { /* unlikely the argname is not a string but ignore if it is*/ - PyErr_Clear(); - } - else { - /* Search for arg_name */ - RNA_parameter_list_begin(&parms, &iter); - for (; iter.valid; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - if (STREQ(arg_name, RNA_property_identifier(parm))) { - found = true; - break; - } - } - - RNA_parameter_list_end(&iter); - - if (found == false) { - BLI_dynstr_appendf(bad_args, first ? "%s" : ", %s", arg_name); - first = false; - } - } - } - - /* list good args */ - first = true; - - RNA_parameter_list_begin(&parms, &iter); - for (; iter.valid; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - if (RNA_parameter_flag(parm) & PARM_OUTPUT) { - continue; - } - - BLI_dynstr_appendf(good_args, first ? "%s" : ", %s", RNA_property_identifier(parm)); - first = false; - } - RNA_parameter_list_end(&iter); - - - bad_args_str = BLI_dynstr_get_cstring(bad_args); - good_args_str = BLI_dynstr_get_cstring(good_args); - - PyErr_Format(PyExc_TypeError, - "%.200s.%.200s(): was called with invalid keyword argument(s) (%s), expected (%s)", - RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), - bad_args_str, good_args_str); - - BLI_dynstr_free(bad_args); - BLI_dynstr_free(good_args); - MEM_freeN((void *)bad_args_str); - MEM_freeN((void *)good_args_str); - - err = -1; - } - - ret = NULL; - if (err == 0) { - /* call function */ - ReportList reports; - bContext *C = BPy_GetContext(); - - BKE_reports_init(&reports, RPT_STORE); - RNA_function_call(C, &reports, self_ptr, self_func, &parms); - - err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true)); - - /* return value */ - if (err != -1) { - if (ret_len > 0) { - if (ret_len > 1) { - ret = PyTuple_New(ret_len); - i = 0; /* arg index */ - - RNA_parameter_list_begin(&parms, &iter); - - for (; iter.valid; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - - if (RNA_parameter_flag(parm) & PARM_OUTPUT) { - PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, parm, iter.data)); - } - } - - RNA_parameter_list_end(&iter); - } - else { - ret = pyrna_param_to_py(&funcptr, pret_single, retdata_single); - } - - /* possible there is an error in conversion */ - if (ret == NULL) { - err = -1; - } - } - } - } - + err = pyrna_py_to_prop(&funcptr, parm, iter.data, item, ""); + + if (err != 0) { + /* the error generated isn't that useful, so generate it again with a useful prefix + * could also write a function to prepend to error messages */ + char error_prefix[512]; + PyErr_Clear(); /* re-raise */ + + if (kw_arg == true) { + BLI_snprintf(error_prefix, + sizeof(error_prefix), + "%.200s.%.200s(): error with keyword argument \"%.200s\" - ", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + RNA_property_identifier(parm)); + } + else { + BLI_snprintf(error_prefix, + sizeof(error_prefix), + "%.200s.%.200s(): error with argument %d, \"%.200s\" - ", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + i, + RNA_property_identifier(parm)); + } + + pyrna_py_to_prop(&funcptr, parm, iter.data, item, error_prefix); + + break; + } + } + + RNA_parameter_list_end(&iter); + + /* Check if we gave args that don't exist in the function + * printing the error is slow but it should only happen when developing. + * the if below is quick, checking if it passed less keyword args then we gave. + * (Don't overwrite the error if we have one, otherwise can skip important messages and confuse with args) + */ + if (err == 0 && kw && (pykw_len > kw_tot)) { + PyObject *key, *value; + Py_ssize_t pos = 0; + + DynStr *bad_args = BLI_dynstr_new(); + DynStr *good_args = BLI_dynstr_new(); + + const char *arg_name, *bad_args_str, *good_args_str; + bool found = false, first = true; + + while (PyDict_Next(kw, &pos, &key, &value)) { + + arg_name = _PyUnicode_AsString(key); + found = false; + + if (arg_name == NULL) { /* unlikely the argname is not a string but ignore if it is*/ + PyErr_Clear(); + } + else { + /* Search for arg_name */ + RNA_parameter_list_begin(&parms, &iter); + for (; iter.valid; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + if (STREQ(arg_name, RNA_property_identifier(parm))) { + found = true; + break; + } + } + + RNA_parameter_list_end(&iter); + + if (found == false) { + BLI_dynstr_appendf(bad_args, first ? "%s" : ", %s", arg_name); + first = false; + } + } + } + + /* list good args */ + first = true; + + RNA_parameter_list_begin(&parms, &iter); + for (; iter.valid; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + if (RNA_parameter_flag(parm) & PARM_OUTPUT) { + continue; + } + + BLI_dynstr_appendf(good_args, first ? "%s" : ", %s", RNA_property_identifier(parm)); + first = false; + } + RNA_parameter_list_end(&iter); + + bad_args_str = BLI_dynstr_get_cstring(bad_args); + good_args_str = BLI_dynstr_get_cstring(good_args); + + PyErr_Format( + PyExc_TypeError, + "%.200s.%.200s(): was called with invalid keyword argument(s) (%s), expected (%s)", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + bad_args_str, + good_args_str); + + BLI_dynstr_free(bad_args); + BLI_dynstr_free(good_args); + MEM_freeN((void *)bad_args_str); + MEM_freeN((void *)good_args_str); + + err = -1; + } + + ret = NULL; + if (err == 0) { + /* call function */ + ReportList reports; + bContext *C = BPy_GetContext(); + + BKE_reports_init(&reports, RPT_STORE); + RNA_function_call(C, &reports, self_ptr, self_func, &parms); + + err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true)); + + /* return value */ + if (err != -1) { + if (ret_len > 0) { + if (ret_len > 1) { + ret = PyTuple_New(ret_len); + i = 0; /* arg index */ + + RNA_parameter_list_begin(&parms, &iter); + + for (; iter.valid; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + + if (RNA_parameter_flag(parm) & PARM_OUTPUT) { + PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, parm, iter.data)); + } + } + + RNA_parameter_list_end(&iter); + } + else { + ret = pyrna_param_to_py(&funcptr, pret_single, retdata_single); + } + + /* possible there is an error in conversion */ + if (ret == NULL) { + err = -1; + } + } + } + } #ifdef DEBUG_STRING_FREE -#if 0 - if (PyList_GET_SIZE(string_free_ls)) { - printf("%.200s.%.200s(): has %d strings\n", - RNA_struct_identifier(self_ptr->type), - RNA_function_identifier(self_func), - (int)PyList_GET_SIZE(string_free_ls)); - } -#endif - Py_DECREF(string_free_ls); -#undef DEBUG_STRING_FREE +# if 0 + if (PyList_GET_SIZE(string_free_ls)) { + printf("%.200s.%.200s(): has %d strings\n", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + (int)PyList_GET_SIZE(string_free_ls)); + } +# endif + Py_DECREF(string_free_ls); +# undef DEBUG_STRING_FREE #endif - /* cleanup */ - RNA_parameter_list_end(&iter); - RNA_parameter_list_free(&parms); + /* cleanup */ + RNA_parameter_list_end(&iter); + RNA_parameter_list_free(&parms); - if (ret) { - return ret; - } + if (ret) { + return ret; + } - if (err == -1) { - return NULL; - } + if (err == -1) { + return NULL; + } - Py_RETURN_NONE; + Py_RETURN_NONE; } static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void *UNUSED(closure)) { - PyObject *ret; - char *args; + PyObject *ret; + char *args; - args = RNA_function_as_string_keywords(NULL, self->func, true, true, INT_MAX); + args = RNA_function_as_string_keywords(NULL, self->func, true, true, INT_MAX); - ret = PyUnicode_FromFormat("%.200s.%.200s(%.200s)\n%s", - RNA_struct_identifier(self->ptr.type), - RNA_function_identifier(self->func), - args, RNA_function_ui_description(self->func)); + ret = PyUnicode_FromFormat("%.200s.%.200s(%.200s)\n%s", + RNA_struct_identifier(self->ptr.type), + RNA_function_identifier(self->func), + args, + RNA_function_ui_description(self->func)); - MEM_freeN(args); + MEM_freeN(args); - return ret; + return ret; } /* subclasses of pyrna_struct_Type which support idprop definitions use this as a metaclass */ /* note: tp_base member is set to &PyType_Type on init */ PyTypeObject pyrna_struct_meta_idprop_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_struct_meta_idprop", /* tp_name */ - - /* NOTE! would be PyTypeObject, but subtypes of Type must be PyHeapTypeObject's */ - sizeof(PyHeapTypeObject), /* tp_basicsize */ - - 0, /* tp_itemsize */ - /* methods */ - NULL, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* deprecated in python 3.0! */ - NULL, /* tp_repr */ - - /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - NULL /*(getattrofunc) pyrna_struct_meta_idprop_getattro*/, /* getattrofunc tp_getattro; */ - (setattrofunc) pyrna_struct_meta_idprop_setattro, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ - 0, /* long tp_weaklistoffset; */ - - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - NULL, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL, /* struct PyGetSetDef *tp_getset; */ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_struct_meta_idprop", /* tp_name */ + + /* NOTE! would be PyTypeObject, but subtypes of Type must be PyHeapTypeObject's */ + sizeof(PyHeapTypeObject), /* tp_basicsize */ + + 0, /* tp_itemsize */ + /* methods */ + NULL, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* deprecated in python 3.0! */ + NULL, /* tp_repr */ + + /* Method suites for standard classes */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL /*(getattrofunc) pyrna_struct_meta_idprop_getattro*/, /* getattrofunc tp_getattro; */ + (setattrofunc)pyrna_struct_meta_idprop_setattro, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL, /* struct PyGetSetDef *tp_getset; */ #if defined(_MSC_VER) - NULL, /* defer assignment */ + NULL, /* defer assignment */ #else - &PyType_Type, /* struct _typeobject *tp_base; */ + &PyType_Type, /* struct _typeobject *tp_base; */ #endif - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; - /*-----------------------BPy_StructRNA method def------------------------------*/ PyTypeObject pyrna_struct_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_struct", /* tp_name */ - sizeof(BPy_StructRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor) pyrna_struct_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - (reprfunc) pyrna_struct_repr, /* tp_repr */ - - /* Method suites for standard classes */ - - NULL, /* PyNumberMethods *tp_as_number; */ - &pyrna_struct_as_sequence, /* PySequenceMethods *tp_as_sequence; */ - &pyrna_struct_as_mapping, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - - (hashfunc) pyrna_struct_hash, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - (reprfunc) pyrna_struct_str, /* reprfunc tp_str; */ - (getattrofunc) pyrna_struct_getattro, /* getattrofunc tp_getattro; */ - (setattrofunc) pyrna_struct_setattro, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_struct", /* tp_name */ + sizeof(BPy_StructRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_struct_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + (reprfunc)pyrna_struct_repr, /* tp_repr */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + &pyrna_struct_as_sequence, /* PySequenceMethods *tp_as_sequence; */ + &pyrna_struct_as_mapping, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + (hashfunc)pyrna_struct_hash, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + (reprfunc)pyrna_struct_str, /* reprfunc tp_str; */ + (getattrofunc)pyrna_struct_getattro, /* getattrofunc tp_getattro; */ + (setattrofunc)pyrna_struct_setattro, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ +/*** Assigned meaning in release 2.0 ***/ +/* call function for all accessible objects */ #ifdef USE_PYRNA_STRUCT_REFERENCE - (traverseproc) pyrna_struct_traverse, /* traverseproc tp_traverse; */ + (traverseproc)pyrna_struct_traverse, /* traverseproc tp_traverse; */ - /* delete references to contained objects */ - (inquiry)pyrna_struct_clear, /* inquiry tp_clear; */ + /* delete references to contained objects */ + (inquiry)pyrna_struct_clear, /* inquiry tp_clear; */ #else - NULL, /* traverseproc tp_traverse; */ + NULL, /* traverseproc tp_traverse; */ -/* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ #endif /* !USE_PYRNA_STRUCT_REFERENCE */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - (richcmpfunc)pyrna_struct_richcmp, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + (richcmpfunc)pyrna_struct_richcmp, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_StructRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_StructRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - pyrna_struct_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - pyrna_struct_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - pyrna_struct_new, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + pyrna_struct_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + pyrna_struct_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + pyrna_struct_new, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; /*-----------------------BPy_PropertyRNA method def------------------------------*/ PyTypeObject pyrna_prop_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_prop", /* tp_name */ - sizeof(BPy_PropertyRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor) pyrna_prop_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - (reprfunc) pyrna_prop_repr, /* tp_repr */ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_prop", /* tp_name */ + sizeof(BPy_PropertyRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + (reprfunc)pyrna_prop_repr, /* tp_repr */ - /* Method suites for standard classes */ + /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ - /* More standard operations (here for binary compatibility) */ + /* More standard operations (here for binary compatibility) */ - (hashfunc) pyrna_prop_hash, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - (reprfunc) pyrna_prop_str, /* reprfunc tp_str; */ + (hashfunc)pyrna_prop_hash, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + (reprfunc)pyrna_prop_str, /* reprfunc tp_str; */ - /* will only use these if this is a subtype of a py class */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ + /* will only use these if this is a subtype of a py class */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - (richcmpfunc)pyrna_prop_richcmp, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + (richcmpfunc)pyrna_prop_richcmp, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - pyrna_prop_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - pyrna_prop_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - pyrna_prop_new, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + pyrna_prop_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + pyrna_prop_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + pyrna_prop_new, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; PyTypeObject pyrna_prop_array_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_prop_array", /* tp_name */ - sizeof(BPy_PropertyArrayRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)pyrna_prop_array_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - (reprfunc)pyrna_prop_array_repr, /* tp_repr */ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_prop_array", /* tp_name */ + sizeof(BPy_PropertyArrayRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_array_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + (reprfunc)pyrna_prop_array_repr, /* tp_repr */ - /* Method suites for standard classes */ + /* Method suites for standard classes */ - &pyrna_prop_array_as_number, /* PyNumberMethods *tp_as_number; */ - &pyrna_prop_array_as_sequence, /* PySequenceMethods *tp_as_sequence; */ - &pyrna_prop_array_as_mapping, /* PyMappingMethods *tp_as_mapping; */ + &pyrna_prop_array_as_number, /* PyNumberMethods *tp_as_number; */ + &pyrna_prop_array_as_sequence, /* PySequenceMethods *tp_as_sequence; */ + &pyrna_prop_array_as_mapping, /* PyMappingMethods *tp_as_mapping; */ - /* More standard operations (here for binary compatibility) */ + /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ - /* will only use these if this is a subtype of a py class */ - (getattrofunc) pyrna_prop_array_getattro, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ + /* will only use these if this is a subtype of a py class */ + (getattrofunc)pyrna_prop_array_getattro, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons (subclassed) ***/ - NULL, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons (subclassed) ***/ + NULL, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_PropertyArrayRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_PropertyArrayRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - (getiterfunc)pyrna_prop_array_iter, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - pyrna_prop_array_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ - &pyrna_prop_Type, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + (getiterfunc)pyrna_prop_array_iter, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + pyrna_prop_array_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ + &pyrna_prop_Type, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; PyTypeObject pyrna_prop_collection_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_prop_collection", /* tp_name */ - sizeof(BPy_PropertyRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)pyrna_prop_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* subclassed */ /* tp_repr */ - - /* Method suites for standard classes */ - - &pyrna_prop_collection_as_number, /* PyNumberMethods *tp_as_number; */ - &pyrna_prop_collection_as_sequence, /* PySequenceMethods *tp_as_sequence; */ - &pyrna_prop_collection_as_mapping, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - - /* will only use these if this is a subtype of a py class */ - (getattrofunc) pyrna_prop_collection_getattro, /* getattrofunc tp_getattro; */ - (setattrofunc) pyrna_prop_collection_setattro, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons (subclassed) ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_prop_collection", /* tp_name */ + sizeof(BPy_PropertyRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + NULL, + /* subclassed */ /* tp_repr */ + + /* Method suites for standard classes */ + + &pyrna_prop_collection_as_number, /* PyNumberMethods *tp_as_number; */ + &pyrna_prop_collection_as_sequence, /* PySequenceMethods *tp_as_sequence; */ + &pyrna_prop_collection_as_mapping, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + + /* will only use these if this is a subtype of a py class */ + (getattrofunc)pyrna_prop_collection_getattro, /* getattrofunc tp_getattro; */ + (setattrofunc)pyrna_prop_collection_setattro, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons (subclassed) ***/ + NULL, /* richcmpfunc tp_richcompare; */ + +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - (getiterfunc)pyrna_prop_collection_iter, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - pyrna_prop_collection_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ - &pyrna_prop_Type, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + (getiterfunc)pyrna_prop_collection_iter, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + pyrna_prop_collection_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ + &pyrna_prop_Type, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; /* only for add/remove/move methods */ static PyTypeObject pyrna_prop_collection_idprop_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_prop_collection_idprop", /* tp_name */ - sizeof(BPy_PropertyRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)pyrna_prop_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* subclassed */ /* tp_repr */ - - /* Method suites for standard classes */ - - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - - /* will only use these if this is a subtype of a py class */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons (subclassed) ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_prop_collection_idprop", /* tp_name */ + sizeof(BPy_PropertyRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + NULL, + /* subclassed */ /* tp_repr */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + + /* will only use these if this is a subtype of a py class */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons (subclassed) ***/ + NULL, /* richcmpfunc tp_richcompare; */ + +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - pyrna_prop_collection_idprop_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ - &pyrna_prop_collection_Type, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + pyrna_prop_collection_idprop_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ + &pyrna_prop_collection_Type, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; /*-----------------------BPy_PropertyRNA method def------------------------------*/ PyTypeObject pyrna_func_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_func", /* tp_name */ - sizeof(BPy_FunctionRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - NULL, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - (reprfunc) pyrna_func_repr, /* tp_repr */ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_func", /* tp_name */ + sizeof(BPy_FunctionRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + NULL, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + (reprfunc)pyrna_func_repr, /* tp_repr */ - /* Method suites for standard classes */ + /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ - /* More standard operations (here for binary compatibility) */ + /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - (ternaryfunc)pyrna_func_call, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ + NULL, /* hashfunc tp_hash; */ + (ternaryfunc)pyrna_func_call, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ - /* will only use these if this is a subtype of a py class */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ + /* will only use these if this is a subtype of a py class */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - NULL, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - NULL, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - pyrna_func_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + pyrna_func_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; #ifdef USE_PYRNA_ITER @@ -6643,232 +6760,232 @@ static void pyrna_prop_collection_iter_dealloc(BPy_PropertyCollectionIterRNA *se static PyObject *pyrna_prop_collection_iter_next(BPy_PropertyCollectionIterRNA *self); static PyTypeObject pyrna_prop_collection_iter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_prop_collection_iter", /* tp_name */ - sizeof(BPy_PropertyCollectionIterRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)pyrna_prop_collection_iter_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* subclassed */ /* tp_repr */ - - /* Method suites for standard classes */ - - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - - /* will only use these if this is a subtype of a py class */ -#if defined(_MSC_VER) - NULL, /* defer assignment */ -#else - PyObject_GenericGetAttr, /* getattrofunc tp_getattro; */ -#endif - NULL, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons (subclassed) ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ -#ifdef USE_WEAKREFS - offsetof(BPy_PropertyCollectionIterRNA, in_weakreflist), /* long tp_weaklistoffset; */ -#else - 0, -#endif - /*** Added in release 2.2 ***/ - /* Iterators */ -#if defined(_MSC_VER) - NULL, /* defer assignment */ -#else - PyObject_SelfIter, /* getiterfunc tp_iter; */ -#endif - (iternextfunc) pyrna_prop_collection_iter_next, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - NULL, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + PyVarObject_HEAD_INIT(NULL, 0) "bpy_prop_collection_iter", /* tp_name */ + sizeof(BPy_PropertyCollectionIterRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_collection_iter_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + NULL, + /* subclassed */ /* tp_repr */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + +/* will only use these if this is a subtype of a py class */ +# if defined(_MSC_VER) + NULL, /* defer assignment */ +# else + PyObject_GenericGetAttr, /* getattrofunc tp_getattro; */ +# endif + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons (subclassed) ***/ + NULL, /* richcmpfunc tp_richcompare; */ + +/*** weak reference enabler ***/ +# ifdef USE_WEAKREFS + offsetof(BPy_PropertyCollectionIterRNA, in_weakreflist), /* long tp_weaklistoffset; */ +# else + 0, +# endif +/*** Added in release 2.2 ***/ +/* Iterators */ +# if defined(_MSC_VER) + NULL, /* defer assignment */ +# else + PyObject_SelfIter, /* getiterfunc tp_iter; */ +# endif + (iternextfunc)pyrna_prop_collection_iter_next, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; static PyObject *pyrna_prop_collection_iter_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop) { - BPy_PropertyCollectionIterRNA *self = PyObject_New(BPy_PropertyCollectionIterRNA, &pyrna_prop_collection_iter_Type); + BPy_PropertyCollectionIterRNA *self = PyObject_New(BPy_PropertyCollectionIterRNA, + &pyrna_prop_collection_iter_Type); -#ifdef USE_WEAKREFS - self->in_weakreflist = NULL; -#endif +# ifdef USE_WEAKREFS + self->in_weakreflist = NULL; +# endif - RNA_property_collection_begin(ptr, prop, &self->iter); + RNA_property_collection_begin(ptr, prop, &self->iter); - return (PyObject *)self; + return (PyObject *)self; } static PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self) { - return pyrna_prop_collection_iter_CreatePyObject(&self->ptr, self->prop); + return pyrna_prop_collection_iter_CreatePyObject(&self->ptr, self->prop); } static PyObject *pyrna_prop_collection_iter_next(BPy_PropertyCollectionIterRNA *self) { - if (self->iter.valid == false) { - PyErr_SetNone(PyExc_StopIteration); - return NULL; - } - else { - BPy_StructRNA *pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&self->iter.ptr); + if (self->iter.valid == false) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + else { + BPy_StructRNA *pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&self->iter.ptr); -#ifdef USE_PYRNA_STRUCT_REFERENCE - if (pyrna) { /* unlikely but may fail */ - if ((PyObject *)pyrna != Py_None) { - /* hold a reference to the iterator since it may have - * allocated memory 'pyrna' needs. eg: introspecting dynamic enum's */ - /* TODO, we could have an api call to know if this is needed since most collections don't */ - pyrna_struct_reference_set(pyrna, (PyObject *)self); - } - } -#endif /* !USE_PYRNA_STRUCT_REFERENCE */ +# ifdef USE_PYRNA_STRUCT_REFERENCE + if (pyrna) { /* unlikely but may fail */ + if ((PyObject *)pyrna != Py_None) { + /* hold a reference to the iterator since it may have + * allocated memory 'pyrna' needs. eg: introspecting dynamic enum's */ + /* TODO, we could have an api call to know if this is needed since most collections don't */ + pyrna_struct_reference_set(pyrna, (PyObject *)self); + } + } +# endif /* !USE_PYRNA_STRUCT_REFERENCE */ - RNA_property_collection_next(&self->iter); + RNA_property_collection_next(&self->iter); - return (PyObject *)pyrna; - } + return (PyObject *)pyrna; + } } - static void pyrna_prop_collection_iter_dealloc(BPy_PropertyCollectionIterRNA *self) { -#ifdef USE_WEAKREFS - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *)self); - } -#endif +# ifdef USE_WEAKREFS + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject *)self); + } +# endif - RNA_property_collection_end(&self->iter); + RNA_property_collection_end(&self->iter); - PyObject_DEL(self); + PyObject_DEL(self); } /* --- collection iterator: end --- */ #endif /* !USE_PYRNA_ITER */ - static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna) { - PointerRNA ptr; - PyObject *item; + PointerRNA ptr; + PyObject *item; - Py_INCREF(newclass); + Py_INCREF(newclass); - if (RNA_struct_py_type_get(srna)) { - PyC_ObSpit("RNA WAS SET - ", RNA_struct_py_type_get(srna)); - } + if (RNA_struct_py_type_get(srna)) { + PyC_ObSpit("RNA WAS SET - ", RNA_struct_py_type_get(srna)); + } - Py_XDECREF(((PyObject *)RNA_struct_py_type_get(srna))); + Py_XDECREF(((PyObject *)RNA_struct_py_type_get(srna))); - RNA_struct_py_type_set(srna, (void *)newclass); /* Store for later use */ + RNA_struct_py_type_set(srna, (void *)newclass); /* Store for later use */ - /* Not 100% needed but useful, - * having an instance within a type looks wrong however this instance IS an rna type */ + /* Not 100% needed but useful, + * having an instance within a type looks wrong however this instance IS an rna type */ - /* python deals with the circular ref */ - RNA_pointer_create(NULL, &RNA_Struct, srna, &ptr); - item = pyrna_struct_CreatePyObject(&ptr); + /* python deals with the circular ref */ + RNA_pointer_create(NULL, &RNA_Struct, srna, &ptr); + item = pyrna_struct_CreatePyObject(&ptr); - /* note, must set the class not the __dict__ else the internal slots are not updated correctly */ - PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item); - Py_DECREF(item); + /* note, must set the class not the __dict__ else the internal slots are not updated correctly */ + PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item); + Py_DECREF(item); - /* add staticmethods and classmethods */ - { - const PointerRNA func_ptr = {{NULL}, srna, NULL}; - const ListBase *lb; - Link *link; + /* add staticmethods and classmethods */ + { + const PointerRNA func_ptr = {{NULL}, srna, NULL}; + const ListBase *lb; + Link *link; - lb = RNA_struct_type_functions(srna); - for (link = lb->first; link; link = link->next) { - FunctionRNA *func = (FunctionRNA *)link; - const int flag = RNA_function_flag(func); - if ((flag & FUNC_NO_SELF) && /* is staticmethod or classmethod */ - (flag & FUNC_REGISTER) == false) /* is not for registration */ - { - /* we may want to set the type of this later */ - PyObject *func_py = pyrna_func_to_py(&func_ptr, func); - PyObject_SetAttrString(newclass, RNA_function_identifier(func), func_py); - Py_DECREF(func_py); - } - } - } + lb = RNA_struct_type_functions(srna); + for (link = lb->first; link; link = link->next) { + FunctionRNA *func = (FunctionRNA *)link; + const int flag = RNA_function_flag(func); + if ((flag & FUNC_NO_SELF) && /* is staticmethod or classmethod */ + (flag & FUNC_REGISTER) == false) /* is not for registration */ + { + /* we may want to set the type of this later */ + PyObject *func_py = pyrna_func_to_py(&func_ptr, func); + PyObject_SetAttrString(newclass, RNA_function_identifier(func), func_py); + Py_DECREF(func_py); + } + } + } - /* done with rna instance */ + /* done with rna instance */ } static PyObject *pyrna_srna_Subtype(StructRNA *srna); /* return a borrowed reference */ -static PyObject *pyrna_srna_PyBase(StructRNA *srna) //, PyObject *bpy_types_dict) +static PyObject *pyrna_srna_PyBase(StructRNA *srna) //, PyObject *bpy_types_dict) { - /* Assume RNA_struct_py_type_get(srna) was already checked */ - StructRNA *base; + /* Assume RNA_struct_py_type_get(srna) was already checked */ + StructRNA *base; - PyObject *py_base = NULL; + PyObject *py_base = NULL; - /* get the base type */ - base = RNA_struct_base(srna); + /* get the base type */ + base = RNA_struct_base(srna); - if (base && base != srna) { - /* printf("debug subtype %s %p\n", RNA_struct_identifier(srna), srna); */ - py_base = pyrna_srna_Subtype(base); //, bpy_types_dict); - Py_DECREF(py_base); /* srna owns, this is only to pass as an arg */ - } + if (base && base != srna) { + /* printf("debug subtype %s %p\n", RNA_struct_identifier(srna), srna); */ + py_base = pyrna_srna_Subtype(base); //, bpy_types_dict); + Py_DECREF(py_base); /* srna owns, this is only to pass as an arg */ + } - if (py_base == NULL) { - py_base = (PyObject *)&pyrna_struct_Type; - } + if (py_base == NULL) { + py_base = (PyObject *)&pyrna_struct_Type; + } - return py_base; + return py_base; } /* check if we have a native python subclass, use it when it exists @@ -6877,378 +6994,379 @@ static PyObject *bpy_types_dict = NULL; static PyObject *pyrna_srna_ExternalType(StructRNA *srna) { - const char *idname = RNA_struct_identifier(srna); - PyObject *newclass; - - if (bpy_types_dict == NULL) { - PyObject *bpy_types = PyImport_ImportModuleLevel("bpy_types", NULL, NULL, NULL, 0); - - if (bpy_types == NULL) { - PyErr_Print(); - PyErr_Clear(); - CLOG_ERROR(BPY_LOG_RNA, "failed to find 'bpy_types' module"); - return NULL; - } - bpy_types_dict = PyModule_GetDict(bpy_types); /* borrow */ - Py_DECREF(bpy_types); /* fairly safe to assume the dict is kept */ - } - - newclass = PyDict_GetItemString(bpy_types_dict, idname); - - /* sanity check, could skip this unless in debug mode */ - if (newclass) { - PyObject *base_compare = pyrna_srna_PyBase(srna); - //PyObject *slots = PyObject_GetAttrString(newclass, "__slots__"); // cant do this because it gets superclasses values! - //PyObject *bases = PyObject_GetAttrString(newclass, "__bases__"); // can do this but faster not to. - PyObject *tp_bases = ((PyTypeObject *)newclass)->tp_bases; - PyObject *tp_slots = PyDict_GetItem(((PyTypeObject *)newclass)->tp_dict, bpy_intern_str___slots__); - - if (tp_slots == NULL) { - CLOG_ERROR(BPY_LOG_RNA, "expected class '%s' to have __slots__ defined, see bpy_types.py", idname); - newclass = NULL; - } - else if (PyTuple_GET_SIZE(tp_bases)) { - PyObject *base = PyTuple_GET_ITEM(tp_bases, 0); - - if (base_compare != base) { - char pyob_info[256]; - PyC_ObSpitStr(pyob_info, sizeof(pyob_info), base_compare); - CLOG_ERROR(BPY_LOG_RNA, - "incorrect subclassing of SRNA '%s', expected '%s', see bpy_types.py", - idname, pyob_info); - newclass = NULL; - } - else { - CLOG_INFO(BPY_LOG_RNA, 2, "SRNA sub-classed: '%s'", idname); - } - } - } - - return newclass; + const char *idname = RNA_struct_identifier(srna); + PyObject *newclass; + + if (bpy_types_dict == NULL) { + PyObject *bpy_types = PyImport_ImportModuleLevel("bpy_types", NULL, NULL, NULL, 0); + + if (bpy_types == NULL) { + PyErr_Print(); + PyErr_Clear(); + CLOG_ERROR(BPY_LOG_RNA, "failed to find 'bpy_types' module"); + return NULL; + } + bpy_types_dict = PyModule_GetDict(bpy_types); /* borrow */ + Py_DECREF(bpy_types); /* fairly safe to assume the dict is kept */ + } + + newclass = PyDict_GetItemString(bpy_types_dict, idname); + + /* sanity check, could skip this unless in debug mode */ + if (newclass) { + PyObject *base_compare = pyrna_srna_PyBase(srna); + //PyObject *slots = PyObject_GetAttrString(newclass, "__slots__"); // cant do this because it gets superclasses values! + //PyObject *bases = PyObject_GetAttrString(newclass, "__bases__"); // can do this but faster not to. + PyObject *tp_bases = ((PyTypeObject *)newclass)->tp_bases; + PyObject *tp_slots = PyDict_GetItem(((PyTypeObject *)newclass)->tp_dict, + bpy_intern_str___slots__); + + if (tp_slots == NULL) { + CLOG_ERROR( + BPY_LOG_RNA, "expected class '%s' to have __slots__ defined, see bpy_types.py", idname); + newclass = NULL; + } + else if (PyTuple_GET_SIZE(tp_bases)) { + PyObject *base = PyTuple_GET_ITEM(tp_bases, 0); + + if (base_compare != base) { + char pyob_info[256]; + PyC_ObSpitStr(pyob_info, sizeof(pyob_info), base_compare); + CLOG_ERROR(BPY_LOG_RNA, + "incorrect subclassing of SRNA '%s', expected '%s', see bpy_types.py", + idname, + pyob_info); + newclass = NULL; + } + else { + CLOG_INFO(BPY_LOG_RNA, 2, "SRNA sub-classed: '%s'", idname); + } + } + } + + return newclass; } static PyObject *pyrna_srna_Subtype(StructRNA *srna) { - PyObject *newclass = NULL; - - /* stupid/simple case */ - if (srna == NULL) { - newclass = NULL; /* Nothing to do */ - } /* the class may have already been declared & allocated */ - else if ((newclass = RNA_struct_py_type_get(srna))) { - Py_INCREF(newclass); - } /* check if bpy_types.py module has the class defined in it */ - else if ((newclass = pyrna_srna_ExternalType(srna))) { - pyrna_subtype_set_rna(newclass, srna); - Py_INCREF(newclass); - } /* create a new class instance with the C api - * mainly for the purposing of matching the C/rna type hierarchy */ - else { - /* subclass equivalents - * - class myClass(myBase): - * some = 'value' # or ... - * - myClass = type(name='myClass', bases=(myBase,), dict={'__module__': 'bpy.types', '__slots__': ()}) - */ - - /* Assume RNA_struct_py_type_get(srna) was already checked */ - PyObject *py_base = pyrna_srna_PyBase(srna); - PyObject *metaclass; - const char *idname = RNA_struct_identifier(srna); - - /* remove __doc__ for now */ - // const char *descr = RNA_struct_ui_description(srna); - // if (!descr) descr = "(no docs)"; - // "__doc__", descr - - if (RNA_struct_idprops_check(srna) && - !PyObject_IsSubclass(py_base, (PyObject *)&pyrna_struct_meta_idprop_Type)) - { - metaclass = (PyObject *)&pyrna_struct_meta_idprop_Type; - } - else { - metaclass = (PyObject *)&PyType_Type; - } - - /* always use O not N when calling, N causes refcount errors */ + PyObject *newclass = NULL; + + /* stupid/simple case */ + if (srna == NULL) { + newclass = NULL; /* Nothing to do */ + } /* the class may have already been declared & allocated */ + else if ((newclass = RNA_struct_py_type_get(srna))) { + Py_INCREF(newclass); + } /* check if bpy_types.py module has the class defined in it */ + else if ((newclass = pyrna_srna_ExternalType(srna))) { + pyrna_subtype_set_rna(newclass, srna); + Py_INCREF(newclass); + } /* create a new class instance with the C api + * mainly for the purposing of matching the C/rna type hierarchy */ + else { + /* subclass equivalents + * - class myClass(myBase): + * some = 'value' # or ... + * - myClass = type(name='myClass', bases=(myBase,), dict={'__module__': 'bpy.types', '__slots__': ()}) + */ + + /* Assume RNA_struct_py_type_get(srna) was already checked */ + PyObject *py_base = pyrna_srna_PyBase(srna); + PyObject *metaclass; + const char *idname = RNA_struct_identifier(srna); + + /* remove __doc__ for now */ + // const char *descr = RNA_struct_ui_description(srna); + // if (!descr) descr = "(no docs)"; + // "__doc__", descr + + if (RNA_struct_idprops_check(srna) && + !PyObject_IsSubclass(py_base, (PyObject *)&pyrna_struct_meta_idprop_Type)) { + metaclass = (PyObject *)&pyrna_struct_meta_idprop_Type; + } + else { + metaclass = (PyObject *)&PyType_Type; + } + + /* always use O not N when calling, N causes refcount errors */ #if 0 - newclass = PyObject_CallFunction(metaclass, "s(O) {sss()}", - idname, py_base, "__module__", "bpy.types", "__slots__"); + newclass = PyObject_CallFunction(metaclass, "s(O) {sss()}", + idname, py_base, "__module__", "bpy.types", "__slots__"); #else - { - /* longhand of the call above */ - PyObject *args, *item, *value; - int ok; + { + /* longhand of the call above */ + PyObject *args, *item, *value; + int ok; - args = PyTuple_New(3); + args = PyTuple_New(3); - /* arg[0] (name=...) */ - PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(idname)); + /* arg[0] (name=...) */ + PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(idname)); + /* arg[1] (bases=...) */ + PyTuple_SET_ITEM(args, 1, item = PyTuple_New(1)); + PyTuple_SET_ITEM(item, 0, Py_INCREF_RET(py_base)); - /* arg[1] (bases=...) */ - PyTuple_SET_ITEM(args, 1, item = PyTuple_New(1)); - PyTuple_SET_ITEM(item, 0, Py_INCREF_RET(py_base)); + /* arg[2] (dict=...) */ + PyTuple_SET_ITEM(args, 2, item = PyDict_New()); + ok = PyDict_SetItem(item, bpy_intern_str___module__, bpy_intern_str_bpy_types); + BLI_assert(ok != -1); + ok = PyDict_SetItem(item, bpy_intern_str___slots__, value = PyTuple_New(0)); + Py_DECREF(value); + BLI_assert(ok != -1); + newclass = PyObject_CallObject(metaclass, args); + Py_DECREF(args); - /* arg[2] (dict=...) */ - PyTuple_SET_ITEM(args, 2, item = PyDict_New()); - ok = PyDict_SetItem(item, bpy_intern_str___module__, bpy_intern_str_bpy_types); - BLI_assert(ok != -1); - ok = PyDict_SetItem(item, bpy_intern_str___slots__, value = PyTuple_New(0)); Py_DECREF(value); - BLI_assert(ok != -1); - - newclass = PyObject_CallObject(metaclass, args); - Py_DECREF(args); - - (void)ok; - } + (void)ok; + } #endif - /* newclass will now have 2 ref's, ???, probably 1 is internal since decrefing here segfaults */ + /* newclass will now have 2 ref's, ???, probably 1 is internal since decrefing here segfaults */ - /* PyC_ObSpit("new class ref", newclass); */ + /* PyC_ObSpit("new class ref", newclass); */ - if (newclass) { - /* srna owns one, and the other is owned by the caller */ - pyrna_subtype_set_rna(newclass, srna); + if (newclass) { + /* srna owns one, and the other is owned by the caller */ + pyrna_subtype_set_rna(newclass, srna); - /* XXX, adding this back segfaults blender on load. */ - // Py_DECREF(newclass); /* let srna own */ - } - else { - /* this should not happen */ - CLOG_ERROR(BPY_LOG_RNA, "failed to register '%s'", idname); - PyErr_Print(); - PyErr_Clear(); - } - } + /* XXX, adding this back segfaults blender on load. */ + // Py_DECREF(newclass); /* let srna own */ + } + else { + /* this should not happen */ + CLOG_ERROR(BPY_LOG_RNA, "failed to register '%s'", idname); + PyErr_Print(); + PyErr_Clear(); + } + } - return newclass; + return newclass; } /* use for subtyping so we know which srna is used for a PointerRNA */ static StructRNA *srna_from_ptr(PointerRNA *ptr) { - if (ptr->type == &RNA_Struct) { - return ptr->data; - } - else { - return ptr->type; - } + if (ptr->type == &RNA_Struct) { + return ptr->data; + } + else { + return ptr->type; + } } /* always returns a new ref, be sure to decref when done */ static PyObject *pyrna_struct_Subtype(PointerRNA *ptr) { - return pyrna_srna_Subtype(srna_from_ptr(ptr)); + return pyrna_srna_Subtype(srna_from_ptr(ptr)); } /*-----------------------CreatePyObject---------------------------------*/ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr) { - BPy_StructRNA *pyrna = NULL; - - /* note: don't rely on this to return None since NULL data with a valid type can often crash */ - if (ptr->data == NULL && ptr->type == NULL) { /* Operator RNA has NULL data */ - Py_RETURN_NONE; - } - - /* New in 2.8x, since not many types support instancing - * we may want to use a flag to avoid looping over all classes. - campbell */ - void **instance = ptr->data ? RNA_struct_instance(ptr) : NULL; - if (instance && *instance) { - pyrna = *instance; - - /* Refine may have changed types after the first instance was created. */ - if (ptr->type == pyrna->ptr.type) { - Py_INCREF(pyrna); - return (PyObject *)pyrna; - } - else { - /* Existing users will need to use 'type_recast' method. */ - Py_DECREF(pyrna); - *instance = NULL; - /* Continue as if no instance was made */ -#if 0 /* no need to assign, will be written to next... */ - pyrna = NULL; + BPy_StructRNA *pyrna = NULL; + + /* note: don't rely on this to return None since NULL data with a valid type can often crash */ + if (ptr->data == NULL && ptr->type == NULL) { /* Operator RNA has NULL data */ + Py_RETURN_NONE; + } + + /* New in 2.8x, since not many types support instancing + * we may want to use a flag to avoid looping over all classes. - campbell */ + void **instance = ptr->data ? RNA_struct_instance(ptr) : NULL; + if (instance && *instance) { + pyrna = *instance; + + /* Refine may have changed types after the first instance was created. */ + if (ptr->type == pyrna->ptr.type) { + Py_INCREF(pyrna); + return (PyObject *)pyrna; + } + else { + /* Existing users will need to use 'type_recast' method. */ + Py_DECREF(pyrna); + *instance = NULL; + /* Continue as if no instance was made */ +#if 0 /* no need to assign, will be written to next... */ + pyrna = NULL; #endif - } - } - - { - PyTypeObject *tp = (PyTypeObject *)pyrna_struct_Subtype(ptr); - - if (tp) { - pyrna = (BPy_StructRNA *) tp->tp_alloc(tp, 0); - Py_DECREF(tp); /* srna owns, cant hold a ref */ - } - else { - CLOG_WARN(BPY_LOG_RNA, "could not make type '%s'", RNA_struct_identifier(ptr->type)); - pyrna = (BPy_StructRNA *) PyObject_GC_New(BPy_StructRNA, &pyrna_struct_Type); + } + } + + { + PyTypeObject *tp = (PyTypeObject *)pyrna_struct_Subtype(ptr); + + if (tp) { + pyrna = (BPy_StructRNA *)tp->tp_alloc(tp, 0); + Py_DECREF(tp); /* srna owns, cant hold a ref */ + } + else { + CLOG_WARN(BPY_LOG_RNA, "could not make type '%s'", RNA_struct_identifier(ptr->type)); + pyrna = (BPy_StructRNA *)PyObject_GC_New(BPy_StructRNA, &pyrna_struct_Type); #ifdef USE_WEAKREFS - pyrna->in_weakreflist = NULL; + pyrna->in_weakreflist = NULL; #endif - } - } + } + } - if (pyrna == NULL) { - PyErr_SetString(PyExc_MemoryError, "couldn't create bpy_struct object"); - return NULL; - } + if (pyrna == NULL) { + PyErr_SetString(PyExc_MemoryError, "couldn't create bpy_struct object"); + return NULL; + } - /* Blender's instance owns a reference (to avoid Python freeing it). */ - if (instance) { - *instance = pyrna; - Py_INCREF(pyrna); - } + /* Blender's instance owns a reference (to avoid Python freeing it). */ + if (instance) { + *instance = pyrna; + Py_INCREF(pyrna); + } - pyrna->ptr = *ptr; + pyrna->ptr = *ptr; #ifdef PYRNA_FREE_SUPPORT - pyrna->freeptr = false; + pyrna->freeptr = false; #endif #ifdef USE_PYRNA_STRUCT_REFERENCE - pyrna->reference = NULL; + pyrna->reference = NULL; #endif - // PyC_ObSpit("NewStructRNA: ", (PyObject *)pyrna); + // PyC_ObSpit("NewStructRNA: ", (PyObject *)pyrna); #ifdef USE_PYRNA_INVALIDATE_WEAKREF - if (ptr->id.data) { - id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna); - } + if (ptr->id.data) { + id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna); + } #endif - return (PyObject *)pyrna; + return (PyObject *)pyrna; } PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop) { - BPy_PropertyRNA *pyrna; + BPy_PropertyRNA *pyrna; - if (RNA_property_array_check(prop) == 0) { - PyTypeObject *type; + if (RNA_property_array_check(prop) == 0) { + PyTypeObject *type; - if (RNA_property_type(prop) != PROP_COLLECTION) { - type = &pyrna_prop_Type; - } - else { - if ((RNA_property_flag(prop) & PROP_IDPROPERTY) == 0) { - type = &pyrna_prop_collection_Type; - } - else { - type = &pyrna_prop_collection_idprop_Type; - } - } + if (RNA_property_type(prop) != PROP_COLLECTION) { + type = &pyrna_prop_Type; + } + else { + if ((RNA_property_flag(prop) & PROP_IDPROPERTY) == 0) { + type = &pyrna_prop_collection_Type; + } + else { + type = &pyrna_prop_collection_idprop_Type; + } + } - pyrna = (BPy_PropertyRNA *) PyObject_NEW(BPy_PropertyRNA, type); + pyrna = (BPy_PropertyRNA *)PyObject_NEW(BPy_PropertyRNA, type); #ifdef USE_WEAKREFS - pyrna->in_weakreflist = NULL; + pyrna->in_weakreflist = NULL; #endif - } - else { - pyrna = (BPy_PropertyRNA *) PyObject_NEW(BPy_PropertyArrayRNA, &pyrna_prop_array_Type); - ((BPy_PropertyArrayRNA *)pyrna)->arraydim = 0; - ((BPy_PropertyArrayRNA *)pyrna)->arrayoffset = 0; + } + else { + pyrna = (BPy_PropertyRNA *)PyObject_NEW(BPy_PropertyArrayRNA, &pyrna_prop_array_Type); + ((BPy_PropertyArrayRNA *)pyrna)->arraydim = 0; + ((BPy_PropertyArrayRNA *)pyrna)->arrayoffset = 0; #ifdef USE_WEAKREFS - ((BPy_PropertyArrayRNA *)pyrna)->in_weakreflist = NULL; + ((BPy_PropertyArrayRNA *)pyrna)->in_weakreflist = NULL; #endif - } + } - if (pyrna == NULL) { - PyErr_SetString(PyExc_MemoryError, "couldn't create BPy_rna object"); - return NULL; - } + if (pyrna == NULL) { + PyErr_SetString(PyExc_MemoryError, "couldn't create BPy_rna object"); + return NULL; + } - pyrna->ptr = *ptr; - pyrna->prop = prop; + pyrna->ptr = *ptr; + pyrna->prop = prop; #ifdef USE_PYRNA_INVALIDATE_WEAKREF - if (ptr->id.data) { - id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna); - } + if (ptr->id.data) { + id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna); + } #endif - return (PyObject *)pyrna; + return (PyObject *)pyrna; } /* utility func to be used by external modules, *sneaky!* */ PyObject *pyrna_id_CreatePyObject(ID *id) { - if (id) { - PointerRNA ptr; - RNA_id_pointer_create(id, &ptr); - return pyrna_struct_CreatePyObject(&ptr); - } - else { - Py_RETURN_NONE; - } + if (id) { + PointerRNA ptr; + RNA_id_pointer_create(id, &ptr); + return pyrna_struct_CreatePyObject(&ptr); + } + else { + Py_RETURN_NONE; + } } bool pyrna_id_FromPyObject(PyObject *obj, ID **id) { - if (pyrna_id_CheckPyObject(obj)) { - *id = ((BPy_StructRNA *)obj)->ptr.id.data; - return true; - } - else { - *id = NULL; - return false; - } + if (pyrna_id_CheckPyObject(obj)) { + *id = ((BPy_StructRNA *)obj)->ptr.id.data; + return true; + } + else { + *id = NULL; + return false; + } } bool pyrna_id_CheckPyObject(PyObject *obj) { - return BPy_StructRNA_Check(obj) && (RNA_struct_is_ID(((BPy_StructRNA *) obj)->ptr.type)); + return BPy_StructRNA_Check(obj) && (RNA_struct_is_ID(((BPy_StructRNA *)obj)->ptr.type)); } void BPY_rna_init(void) { -#ifdef USE_MATHUTILS /* register mathutils callbacks, ok to run more than once. */ - mathutils_rna_array_cb_index = Mathutils_RegisterCallback(&mathutils_rna_array_cb); - mathutils_rna_matrix_cb_index = Mathutils_RegisterCallback(&mathutils_rna_matrix_cb); +#ifdef USE_MATHUTILS /* register mathutils callbacks, ok to run more than once. */ + mathutils_rna_array_cb_index = Mathutils_RegisterCallback(&mathutils_rna_array_cb); + mathutils_rna_matrix_cb_index = Mathutils_RegisterCallback(&mathutils_rna_matrix_cb); #endif - /* for some reason MSVC complains of these */ + /* for some reason MSVC complains of these */ #if defined(_MSC_VER) - pyrna_struct_meta_idprop_Type.tp_base = &PyType_Type; + pyrna_struct_meta_idprop_Type.tp_base = &PyType_Type; - pyrna_prop_collection_iter_Type.tp_iter = PyObject_SelfIter; - pyrna_prop_collection_iter_Type.tp_getattro = PyObject_GenericGetAttr; + pyrna_prop_collection_iter_Type.tp_iter = PyObject_SelfIter; + pyrna_prop_collection_iter_Type.tp_getattro = PyObject_GenericGetAttr; #endif - /* metaclass */ - if (PyType_Ready(&pyrna_struct_meta_idprop_Type) < 0) { - return; - } + /* metaclass */ + if (PyType_Ready(&pyrna_struct_meta_idprop_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_struct_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_struct_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_prop_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_prop_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_prop_array_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_prop_array_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_prop_collection_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_prop_collection_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_prop_collection_idprop_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_prop_collection_idprop_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_func_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_func_Type) < 0) { + return; + } #ifdef USE_PYRNA_ITER - if (PyType_Ready(&pyrna_prop_collection_iter_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_prop_collection_iter_Type) < 0) { + return; + } #endif } @@ -7256,26 +7374,26 @@ void BPY_rna_init(void) static PointerRNA *rna_module_ptr = NULL; PyObject *BPY_rna_module(void) { - BPy_StructRNA *pyrna; - PointerRNA ptr; + BPy_StructRNA *pyrna; + PointerRNA ptr; - /* for now, return the base RNA type rather than a real module */ - RNA_main_pointer_create(G_MAIN, &ptr); - pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); + /* for now, return the base RNA type rather than a real module */ + RNA_main_pointer_create(G_MAIN, &ptr); + pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); - rna_module_ptr = &pyrna->ptr; - return (PyObject *)pyrna; + rna_module_ptr = &pyrna->ptr; + return (PyObject *)pyrna; } void BPY_update_rna_module(void) { - if (rna_module_ptr) { + if (rna_module_ptr) { #if 0 - RNA_main_pointer_create(G_MAIN, rna_module_ptr); + RNA_main_pointer_create(G_MAIN, rna_module_ptr); #else - rna_module_ptr->data = G_MAIN; /* just set data is enough */ + rna_module_ptr->data = G_MAIN; /* just set data is enough */ #endif - } + } } #if 0 @@ -7283,49 +7401,48 @@ void BPY_update_rna_module(void) * without having the datatypes in blender */ PyObject *BPY_rna_doc(void) { - PointerRNA ptr; + PointerRNA ptr; - /* for now, return the base RNA type rather than a real module */ - RNA_blender_rna_pointer_create(&ptr); + /* for now, return the base RNA type rather than a real module */ + RNA_blender_rna_pointer_create(&ptr); - return pyrna_struct_CreatePyObject(&ptr); + return pyrna_struct_CreatePyObject(&ptr); } #endif - /* pyrna_basetype_* - BPy_BaseTypeRNA is just a BPy_PropertyRNA struct with a different type * the self->ptr and self->prop are always set to the "structs" collection */ /* ---------------getattr-------------------------------------------- */ static PyObject *pyrna_basetype_getattro(BPy_BaseTypeRNA *self, PyObject *pyname) { - PointerRNA newptr; - PyObject *ret; - const char *name = _PyUnicode_AsString(pyname); - - if (name == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy.types: __getattr__ must be a string"); - ret = NULL; - } - else if (RNA_property_collection_lookup_string(&self->ptr, self->prop, name, &newptr)) { - ret = pyrna_struct_Subtype(&newptr); - if (ret == NULL) { - PyErr_Format(PyExc_RuntimeError, - "bpy.types.%.200s subtype could not be generated, this is a bug!", - _PyUnicode_AsString(pyname)); - } - } - else { + PointerRNA newptr; + PyObject *ret; + const char *name = _PyUnicode_AsString(pyname); + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy.types: __getattr__ must be a string"); + ret = NULL; + } + else if (RNA_property_collection_lookup_string(&self->ptr, self->prop, name, &newptr)) { + ret = pyrna_struct_Subtype(&newptr); + if (ret == NULL) { + PyErr_Format(PyExc_RuntimeError, + "bpy.types.%.200s subtype could not be generated, this is a bug!", + _PyUnicode_AsString(pyname)); + } + } + else { #if 0 - PyErr_Format(PyExc_AttributeError, - "bpy.types.%.200s RNA_Struct does not exist", - _PyUnicode_AsString(pyname)); - return NULL; + PyErr_Format(PyExc_AttributeError, + "bpy.types.%.200s RNA_Struct does not exist", + _PyUnicode_AsString(pyname)); + return NULL; #endif - /* The error raised here will be displayed */ - ret = PyObject_GenericGetAttr((PyObject *)self, pyname); - } + /* The error raised here will be displayed */ + ret = PyObject_GenericGetAttr((PyObject *)self, pyname); + } - return ret; + return ret; } static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self); @@ -7333,43 +7450,42 @@ static PyObject *pyrna_register_class(PyObject *self, PyObject *py_class); static PyObject *pyrna_unregister_class(PyObject *self, PyObject *py_class); static struct PyMethodDef pyrna_basetype_methods[] = { - {"__dir__", (PyCFunction)pyrna_basetype_dir, METH_NOARGS, ""}, - {NULL, NULL, 0, NULL}, + {"__dir__", (PyCFunction)pyrna_basetype_dir, METH_NOARGS, ""}, + {NULL, NULL, 0, NULL}, }; /* used to call ..._keys() direct, but we need to filter out operator subclasses */ #if 0 static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self) { - PyObject *list; -#if 0 - PyMethodDef *meth; -#endif + PyObject *list; +# if 0 + PyMethodDef *meth; +# endif - list = pyrna_prop_collection_keys(self); /* like calling structs.keys(), avoids looping here */ + list = pyrna_prop_collection_keys(self); /* like calling structs.keys(), avoids looping here */ -#if 0 /* for now only contains __dir__ */ - for (meth = pyrna_basetype_methods; meth->ml_name; meth++) { - PyList_APPEND(list, PyUnicode_FromString(meth->ml_name)); - } -#endif - return list; +# if 0 /* for now only contains __dir__ */ + for (meth = pyrna_basetype_methods; meth->ml_name; meth++) { + PyList_APPEND(list, PyUnicode_FromString(meth->ml_name)); + } +# endif + return list; } #else static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self) { - PyObject *ret = PyList_New(0); + PyObject *ret = PyList_New(0); - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - StructRNA *srna = itemptr.data; - PyList_APPEND(ret, PyUnicode_FromString(RNA_struct_identifier(srna))); - } - RNA_PROP_END; + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + StructRNA *srna = itemptr.data; + PyList_APPEND(ret, PyUnicode_FromString(RNA_struct_identifier(srna))); + } + RNA_PROP_END; - return ret; + return ret; } #endif @@ -7381,98 +7497,103 @@ static PyTypeObject pyrna_basetype_Type = BLANK_PYTHON_TYPE; */ PyObject *BPY_rna_types(void) { - BPy_BaseTypeRNA *self; - - if ((pyrna_basetype_Type.tp_flags & Py_TPFLAGS_READY) == 0) { - pyrna_basetype_Type.tp_name = "RNA_Types"; - pyrna_basetype_Type.tp_basicsize = sizeof(BPy_BaseTypeRNA); - pyrna_basetype_Type.tp_getattro = (getattrofunc) pyrna_basetype_getattro; - pyrna_basetype_Type.tp_flags = Py_TPFLAGS_DEFAULT; - pyrna_basetype_Type.tp_methods = pyrna_basetype_methods; - - if (PyType_Ready(&pyrna_basetype_Type) < 0) { - return NULL; - } - } - - /* static members for the base class */ - /* add __name__ since help() expects its */ - PyDict_SetItem(pyrna_basetype_Type.tp_dict, bpy_intern_str___name__, bpy_intern_str_bpy_types); - - /* internal base types we have no other accessors for */ - { - PyTypeObject *pyrna_types[] = { - &pyrna_struct_meta_idprop_Type, - &pyrna_struct_Type, - &pyrna_prop_Type, - &pyrna_prop_array_Type, - &pyrna_prop_collection_Type, - &pyrna_func_Type, - }; - - for (int i = 0; i < ARRAY_SIZE(pyrna_types); i += 1) { - PyDict_SetItemString(pyrna_basetype_Type.tp_dict, pyrna_types[i]->tp_name, (PyObject *)pyrna_types[i]); - } - } - - self = (BPy_BaseTypeRNA *)PyObject_NEW(BPy_BaseTypeRNA, &pyrna_basetype_Type); - - /* avoid doing this lookup for every getattr */ - RNA_blender_rna_pointer_create(&self->ptr); - self->prop = RNA_struct_find_property(&self->ptr, "structs"); + BPy_BaseTypeRNA *self; + + if ((pyrna_basetype_Type.tp_flags & Py_TPFLAGS_READY) == 0) { + pyrna_basetype_Type.tp_name = "RNA_Types"; + pyrna_basetype_Type.tp_basicsize = sizeof(BPy_BaseTypeRNA); + pyrna_basetype_Type.tp_getattro = (getattrofunc)pyrna_basetype_getattro; + pyrna_basetype_Type.tp_flags = Py_TPFLAGS_DEFAULT; + pyrna_basetype_Type.tp_methods = pyrna_basetype_methods; + + if (PyType_Ready(&pyrna_basetype_Type) < 0) { + return NULL; + } + } + + /* static members for the base class */ + /* add __name__ since help() expects its */ + PyDict_SetItem(pyrna_basetype_Type.tp_dict, bpy_intern_str___name__, bpy_intern_str_bpy_types); + + /* internal base types we have no other accessors for */ + { + PyTypeObject *pyrna_types[] = { + &pyrna_struct_meta_idprop_Type, + &pyrna_struct_Type, + &pyrna_prop_Type, + &pyrna_prop_array_Type, + &pyrna_prop_collection_Type, + &pyrna_func_Type, + }; + + for (int i = 0; i < ARRAY_SIZE(pyrna_types); i += 1) { + PyDict_SetItemString( + pyrna_basetype_Type.tp_dict, pyrna_types[i]->tp_name, (PyObject *)pyrna_types[i]); + } + } + + self = (BPy_BaseTypeRNA *)PyObject_NEW(BPy_BaseTypeRNA, &pyrna_basetype_Type); + + /* avoid doing this lookup for every getattr */ + RNA_blender_rna_pointer_create(&self->ptr); + self->prop = RNA_struct_find_property(&self->ptr, "structs"); #ifdef USE_WEAKREFS - self->in_weakreflist = NULL; + self->in_weakreflist = NULL; #endif - return (PyObject *)self; + return (PyObject *)self; } StructRNA *pyrna_struct_as_srna(PyObject *self, const bool parent, const char *error_prefix) { - BPy_StructRNA *py_srna = NULL; - StructRNA *srna; - - /* ack, PyObject_GetAttrString wont look up this types tp_dict first :/ */ - if (PyType_Check(self)) { - py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna); - Py_XINCREF(py_srna); - } - - if (parent) { - /* be very careful with this since it will return a parent classes srna. - * modifying this will do confusing stuff! */ - if (py_srna == NULL) { - py_srna = (BPy_StructRNA *)PyObject_GetAttr(self, bpy_intern_str_bl_rna); - } - } - - if (py_srna == NULL) { - PyErr_Format(PyExc_RuntimeError, - "%.200s, missing bl_rna attribute from '%.200s' instance (may not be registered)", - error_prefix, Py_TYPE(self)->tp_name); - return NULL; - } - - if (!BPy_StructRNA_Check(py_srna)) { - PyErr_Format(PyExc_TypeError, - "%.200s, bl_rna attribute wrong type '%.200s' on '%.200s'' instance", - error_prefix, Py_TYPE(py_srna)->tp_name, - Py_TYPE(self)->tp_name); - Py_DECREF(py_srna); - return NULL; - } - - if (py_srna->ptr.type != &RNA_Struct) { - PyErr_Format(PyExc_TypeError, - "%.200s, bl_rna attribute not a RNA_Struct, on '%.200s'' instance", - error_prefix, Py_TYPE(self)->tp_name); - Py_DECREF(py_srna); - return NULL; - } - - srna = py_srna->ptr.data; - Py_DECREF(py_srna); - - return srna; + BPy_StructRNA *py_srna = NULL; + StructRNA *srna; + + /* ack, PyObject_GetAttrString wont look up this types tp_dict first :/ */ + if (PyType_Check(self)) { + py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)self)->tp_dict, + bpy_intern_str_bl_rna); + Py_XINCREF(py_srna); + } + + if (parent) { + /* be very careful with this since it will return a parent classes srna. + * modifying this will do confusing stuff! */ + if (py_srna == NULL) { + py_srna = (BPy_StructRNA *)PyObject_GetAttr(self, bpy_intern_str_bl_rna); + } + } + + if (py_srna == NULL) { + PyErr_Format(PyExc_RuntimeError, + "%.200s, missing bl_rna attribute from '%.200s' instance (may not be registered)", + error_prefix, + Py_TYPE(self)->tp_name); + return NULL; + } + + if (!BPy_StructRNA_Check(py_srna)) { + PyErr_Format(PyExc_TypeError, + "%.200s, bl_rna attribute wrong type '%.200s' on '%.200s'' instance", + error_prefix, + Py_TYPE(py_srna)->tp_name, + Py_TYPE(self)->tp_name); + Py_DECREF(py_srna); + return NULL; + } + + if (py_srna->ptr.type != &RNA_Struct) { + PyErr_Format(PyExc_TypeError, + "%.200s, bl_rna attribute not a RNA_Struct, on '%.200s'' instance", + error_prefix, + Py_TYPE(self)->tp_name); + Py_DECREF(py_srna); + return NULL; + } + + srna = py_srna->ptr.data; + Py_DECREF(py_srna); + + return srna; } /* Orphan functions, not sure where they should go */ @@ -7482,755 +7603,791 @@ StructRNA *pyrna_struct_as_srna(PyObject *self, const bool parent, const char *e StructRNA *srna_from_self(PyObject *self, const char *error_prefix) { - if (self == NULL) { - return NULL; - } - else if (PyCapsule_CheckExact(self)) { - return PyCapsule_GetPointer(self, NULL); - } - else if (PyType_Check(self) == 0) { - return NULL; - } - else { - /* These cases above not errors, they just mean the type was not compatible - * After this any errors will be raised in the script */ + if (self == NULL) { + return NULL; + } + else if (PyCapsule_CheckExact(self)) { + return PyCapsule_GetPointer(self, NULL); + } + else if (PyType_Check(self) == 0) { + return NULL; + } + else { + /* These cases above not errors, they just mean the type was not compatible + * After this any errors will be raised in the script */ - PyObject *error_type, *error_value, *error_traceback; - StructRNA *srna; + PyObject *error_type, *error_value, *error_traceback; + StructRNA *srna; - PyErr_Fetch(&error_type, &error_value, &error_traceback); - PyErr_Clear(); + PyErr_Fetch(&error_type, &error_value, &error_traceback); + PyErr_Clear(); - srna = pyrna_struct_as_srna(self, false, error_prefix); + srna = pyrna_struct_as_srna(self, false, error_prefix); - if (!PyErr_Occurred()) { - PyErr_Restore(error_type, error_value, error_traceback); - } + if (!PyErr_Occurred()) { + PyErr_Restore(error_type, error_value, error_traceback); + } - return srna; - } + return srna; + } } static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item) { - /* We only care about results from C which - * are for sure types, save some time with error */ - if (pyrna_is_deferred_prop(item)) { - - PyObject *py_func, *py_kw, *py_srna_cobject, *py_ret; - - if (PyArg_ParseTuple(item, "OO!", &py_func, &PyDict_Type, &py_kw)) { - PyObject *args_fake; - - if (*_PyUnicode_AsString(key) == '_') { - PyErr_Format(PyExc_ValueError, - "bpy_struct \"%.200s\" registration error: " - "%.200s could not register because the property starts with an '_'\n", - RNA_struct_identifier(srna), _PyUnicode_AsString(key)); - return -1; - } - py_srna_cobject = PyCapsule_New(srna, NULL, NULL); - - /* not 100% nice :/, modifies the dict passed, should be ok */ - PyDict_SetItem(py_kw, bpy_intern_str_attr, key); - - args_fake = PyTuple_New(1); - PyTuple_SET_ITEM(args_fake, 0, py_srna_cobject); - - PyObject *type = PyDict_GetItemString(py_kw, "type"); - StructRNA *type_srna = srna_from_self(type, ""); - if (type_srna) { - if (!RNA_struct_idprops_datablock_allowed(srna) && - (*(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == BPy_PointerProperty || - *(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == BPy_CollectionProperty) && - RNA_struct_idprops_contains_datablock(type_srna)) - { - PyErr_Format(PyExc_ValueError, - "bpy_struct \"%.200s\" doesn't support datablock properties\n", - RNA_struct_identifier(srna)); - return -1; - } - } - - py_ret = PyObject_Call(py_func, args_fake, py_kw); - - if (py_ret) { - Py_DECREF(py_ret); - Py_DECREF(args_fake); /* free's py_srna_cobject too */ - } - else { - /* _must_ print before decreffing args_fake */ - PyErr_Print(); - PyErr_Clear(); - - Py_DECREF(args_fake); /* free's py_srna_cobject too */ - - // PyC_LineSpit(); - PyErr_Format(PyExc_ValueError, - "bpy_struct \"%.200s\" registration error: " - "%.200s could not register\n", - RNA_struct_identifier(srna), _PyUnicode_AsString(key)); - return -1; - } - } - else { - /* Since this is a class dict, ignore args that can't be passed */ - - /* for testing only */ + /* We only care about results from C which + * are for sure types, save some time with error */ + if (pyrna_is_deferred_prop(item)) { + + PyObject *py_func, *py_kw, *py_srna_cobject, *py_ret; + + if (PyArg_ParseTuple(item, "OO!", &py_func, &PyDict_Type, &py_kw)) { + PyObject *args_fake; + + if (*_PyUnicode_AsString(key) == '_') { + PyErr_Format(PyExc_ValueError, + "bpy_struct \"%.200s\" registration error: " + "%.200s could not register because the property starts with an '_'\n", + RNA_struct_identifier(srna), + _PyUnicode_AsString(key)); + return -1; + } + py_srna_cobject = PyCapsule_New(srna, NULL, NULL); + + /* not 100% nice :/, modifies the dict passed, should be ok */ + PyDict_SetItem(py_kw, bpy_intern_str_attr, key); + + args_fake = PyTuple_New(1); + PyTuple_SET_ITEM(args_fake, 0, py_srna_cobject); + + PyObject *type = PyDict_GetItemString(py_kw, "type"); + StructRNA *type_srna = srna_from_self(type, ""); + if (type_srna) { + if (!RNA_struct_idprops_datablock_allowed(srna) && + (*(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == BPy_PointerProperty || + *(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == + BPy_CollectionProperty) && + RNA_struct_idprops_contains_datablock(type_srna)) { + PyErr_Format(PyExc_ValueError, + "bpy_struct \"%.200s\" doesn't support datablock properties\n", + RNA_struct_identifier(srna)); + return -1; + } + } + + py_ret = PyObject_Call(py_func, args_fake, py_kw); + + if (py_ret) { + Py_DECREF(py_ret); + Py_DECREF(args_fake); /* free's py_srna_cobject too */ + } + else { + /* _must_ print before decreffing args_fake */ + PyErr_Print(); + PyErr_Clear(); + + Py_DECREF(args_fake); /* free's py_srna_cobject too */ + + // PyC_LineSpit(); + PyErr_Format(PyExc_ValueError, + "bpy_struct \"%.200s\" registration error: " + "%.200s could not register\n", + RNA_struct_identifier(srna), + _PyUnicode_AsString(key)); + return -1; + } + } + else { + /* Since this is a class dict, ignore args that can't be passed */ + + /* for testing only */ #if 0 - PyC_ObSpit("Why doesn't this work??", item); - PyErr_Print(); + PyC_ObSpit("Why doesn't this work??", item); + PyErr_Print(); #endif - PyErr_Clear(); - } - } + PyErr_Clear(); + } + } - return 0; + return 0; } static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict) { - PyObject *annotations_dict; - PyObject *item, *key; - Py_ssize_t pos = 0; - int ret = 0; - - /* in both cases PyDict_CheckExact(class_dict) will be true even - * though Operators have a metaclass dict namespace */ - if ((annotations_dict = PyDict_GetItem(class_dict, bpy_intern_str___annotations__)) && - PyDict_CheckExact(annotations_dict)) - { - while (PyDict_Next(annotations_dict, &pos, &key, &item)) { - ret = deferred_register_prop(srna, key, item); - - if (ret != 0) { - break; - } - } - } - - { - /* This block can be removed once 2.8x is released and annotations are in use. */ - bool has_warning = false; - while (PyDict_Next(class_dict, &pos, &key, &item)) { - if (pyrna_is_deferred_prop(item)) { - if (!has_warning) { - printf("Warning: class %.200s " - "contains a properties which should be an annotation!\n", - RNA_struct_identifier(srna)); - PyC_LineSpit(); - has_warning = true; - } - printf(" make annotation: %.200s.%.200s\n", - RNA_struct_identifier(srna), _PyUnicode_AsString(key)); - } - ret = deferred_register_prop(srna, key, item); - - if (ret != 0) { - break; - } - } - } - - return ret; + PyObject *annotations_dict; + PyObject *item, *key; + Py_ssize_t pos = 0; + int ret = 0; + + /* in both cases PyDict_CheckExact(class_dict) will be true even + * though Operators have a metaclass dict namespace */ + if ((annotations_dict = PyDict_GetItem(class_dict, bpy_intern_str___annotations__)) && + PyDict_CheckExact(annotations_dict)) { + while (PyDict_Next(annotations_dict, &pos, &key, &item)) { + ret = deferred_register_prop(srna, key, item); + + if (ret != 0) { + break; + } + } + } + + { + /* This block can be removed once 2.8x is released and annotations are in use. */ + bool has_warning = false; + while (PyDict_Next(class_dict, &pos, &key, &item)) { + if (pyrna_is_deferred_prop(item)) { + if (!has_warning) { + printf( + "Warning: class %.200s " + "contains a properties which should be an annotation!\n", + RNA_struct_identifier(srna)); + PyC_LineSpit(); + has_warning = true; + } + printf(" make annotation: %.200s.%.200s\n", + RNA_struct_identifier(srna), + _PyUnicode_AsString(key)); + } + ret = deferred_register_prop(srna, key, item); + + if (ret != 0) { + break; + } + } + } + + return ret; } static int pyrna_deferred_register_class_recursive(StructRNA *srna, PyTypeObject *py_class) { - const int len = PyTuple_GET_SIZE(py_class->tp_bases); - int i, ret; - - /* first scan base classes for registerable properties */ - for (i = 0; i < len; i++) { - PyTypeObject *py_superclass = (PyTypeObject *)PyTuple_GET_ITEM(py_class->tp_bases, i); - - /* the rules for using these base classes are not clear, - * 'object' is of course not worth looking into and - * existing subclasses of RNA would cause a lot more dictionary - * looping then is needed (SomeOperator would scan Operator.__dict__) - * which is harmless but not at all useful. - * - * So only scan base classes which are not subclasses if blender types. - * This best fits having 'mix-in' classes for operators and render engines. - */ - if (py_superclass != &PyBaseObject_Type && - !PyObject_IsSubclass((PyObject *)py_superclass, (PyObject *)&pyrna_struct_Type)) - { - ret = pyrna_deferred_register_class_recursive(srna, py_superclass); - - if (ret != 0) { - return ret; - } - } - } - - /* not register out own properties */ - return pyrna_deferred_register_props(srna, py_class->tp_dict); /* getattr(..., "__dict__") returns a proxy */ + const int len = PyTuple_GET_SIZE(py_class->tp_bases); + int i, ret; + + /* first scan base classes for registerable properties */ + for (i = 0; i < len; i++) { + PyTypeObject *py_superclass = (PyTypeObject *)PyTuple_GET_ITEM(py_class->tp_bases, i); + + /* the rules for using these base classes are not clear, + * 'object' is of course not worth looking into and + * existing subclasses of RNA would cause a lot more dictionary + * looping then is needed (SomeOperator would scan Operator.__dict__) + * which is harmless but not at all useful. + * + * So only scan base classes which are not subclasses if blender types. + * This best fits having 'mix-in' classes for operators and render engines. + */ + if (py_superclass != &PyBaseObject_Type && + !PyObject_IsSubclass((PyObject *)py_superclass, (PyObject *)&pyrna_struct_Type)) { + ret = pyrna_deferred_register_class_recursive(srna, py_superclass); + + if (ret != 0) { + return ret; + } + } + } + + /* not register out own properties */ + return pyrna_deferred_register_props( + srna, py_class->tp_dict); /* getattr(..., "__dict__") returns a proxy */ } int pyrna_deferred_register_class(StructRNA *srna, PyTypeObject *py_class) { - /* Panels and Menus don't need this - * save some time and skip the checks here */ - if (!RNA_struct_idprops_register_check(srna)) { - return 0; - } + /* Panels and Menus don't need this + * save some time and skip the checks here */ + if (!RNA_struct_idprops_register_check(srna)) { + return 0; + } - return pyrna_deferred_register_class_recursive(srna, py_class); + return pyrna_deferred_register_class_recursive(srna, py_class); } /*-------------------- Type Registration ------------------------*/ static int rna_function_arg_count(FunctionRNA *func, int *min_count) { - const ListBase *lb = RNA_function_defined_parameters(func); - PropertyRNA *parm; - Link *link; - int flag = RNA_function_flag(func); - const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); - int count = is_staticmethod ? 0 : 1; - bool done_min_count = false; - - for (link = lb->first; link; link = link->next) { - parm = (PropertyRNA *)link; - if (!(RNA_parameter_flag(parm) & PARM_OUTPUT)) { - if (!done_min_count && (RNA_parameter_flag(parm) & PARM_PYFUNC_OPTIONAL)) { - /* From now on, following parameters are optional in py func */ - if (min_count) { - *min_count = count; - } - done_min_count = true; - } - count++; - } - } - - if (!done_min_count && min_count) { - *min_count = count; - } - return count; -} - -static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, void *py_data, int *have_function) -{ - const ListBase *lb; - Link *link; - const char *class_type = RNA_struct_identifier(srna); - StructRNA *srna_base = RNA_struct_base(srna); - PyObject *py_class = (PyObject *)py_data; - PyObject *base_class = RNA_struct_py_type_get(srna); - PyObject *item; - int i, arg_count, func_arg_count, func_arg_min_count = 0; - const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */ - - if (srna_base) { - if (bpy_class_validate_recursive(dummyptr, srna_base, py_data, have_function) != 0) { - return -1; - } - } - - if (base_class) { - if (!PyObject_IsSubclass(py_class, base_class)) { - PyErr_Format(PyExc_TypeError, - "expected %.200s subclass of class \"%.200s\"", - class_type, py_class_name); - return -1; - } - } - - /* verify callback functions */ - lb = RNA_struct_type_functions(srna); - i = 0; - for (link = lb->first; link; link = link->next) { - FunctionRNA *func = (FunctionRNA *)link; - const int flag = RNA_function_flag(func); - /* TODO(campbell): this is used for classmethod's too, - * even though class methods should have 'FUNC_USE_SELF_TYPE' set, see Operator.poll for eg. - * Keep this as-is since its working but we should be using 'FUNC_USE_SELF_TYPE' for many functions. */ - const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); - - if (!(flag & FUNC_REGISTER)) { - continue; - } - - item = PyObject_GetAttrString(py_class, RNA_function_identifier(func)); - - have_function[i] = (item != NULL); - i++; - - if (item == NULL) { - if ((flag & (FUNC_REGISTER_OPTIONAL & ~FUNC_REGISTER)) == 0) { - PyErr_Format(PyExc_AttributeError, - "expected %.200s, %.200s class to have an \"%.200s\" attribute", - class_type, py_class_name, - RNA_function_identifier(func)); - return -1; - } - - PyErr_Clear(); - } - else { - Py_DECREF(item); /* no need to keep a ref, the class owns it (technically we should keep a ref but...) */ - if (is_staticmethod) { - if (PyMethod_Check(item) == 0) { - PyErr_Format(PyExc_TypeError, - "expected %.200s, %.200s class \"%.200s\" " - "attribute to be a static/class method, not a %.200s", - class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name); - return -1; - } - item = ((PyMethodObject *)item)->im_func; - } - else { - if (PyFunction_Check(item) == 0) { - PyErr_Format(PyExc_TypeError, - "expected %.200s, %.200s class \"%.200s\" " - "attribute to be a function, not a %.200s", - class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name); - return -1; - } - } - - func_arg_count = rna_function_arg_count(func, &func_arg_min_count); - - if (func_arg_count >= 0) { /* -1 if we don't care*/ - arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; - - /* note, the number of args we check for and the number of args we give to - * '@staticmethods' are different (quirk of python), - * this is why rna_function_arg_count() doesn't return the value -1*/ - if (is_staticmethod) { - func_arg_count++; - func_arg_min_count++; - } - - if (arg_count < func_arg_min_count || arg_count > func_arg_count) { - if (func_arg_min_count != func_arg_count) { - PyErr_Format(PyExc_ValueError, - "expected %.200s, %.200s class \"%.200s\" function to have between %d and %d " - "args, found %d", - class_type, py_class_name, RNA_function_identifier(func), - func_arg_count, func_arg_min_count, arg_count); - } - else { - PyErr_Format(PyExc_ValueError, - "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d", - class_type, py_class_name, RNA_function_identifier(func), - func_arg_count, arg_count); - } - return -1; - } - } - } - } - - /* verify properties */ - lb = RNA_struct_type_properties(srna); - for (link = lb->first; link; link = link->next) { - const char *identifier; - PropertyRNA *prop = (PropertyRNA *)link; - const int flag = RNA_property_flag(prop); - - if (!(flag & PROP_REGISTER)) { - continue; - } - - /* TODO(campbell): Use Python3.7x _PyObject_LookupAttr(), also in the macro below. */ - identifier = RNA_property_identifier(prop); - item = PyObject_GetAttrString(py_class, identifier); - - if (item == NULL) { - PyErr_Clear(); - /* Sneaky workaround to use the class name as the bl_idname */ - -#define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \ - else if (STREQ(identifier, rna_attr)) { \ - if ((item = PyObject_GetAttr(py_class, py_attr))) { \ - if (item != Py_None) { \ - if (pyrna_py_to_prop(dummyptr, prop, NULL, \ - item, "validating class:") != 0) \ - { \ - Py_DECREF(item); \ - return -1; \ - } \ - } \ - Py_DECREF(item); \ - } \ - else { \ - PyErr_Clear(); \ - } \ - } /* intentionally allow else here */ - - if (false) {} /* needed for macro */ - BPY_REPLACEMENT_STRING("bl_idname", bpy_intern_str___name__) - BPY_REPLACEMENT_STRING("bl_description", bpy_intern_str___doc__) - -#undef BPY_REPLACEMENT_STRING - - if (item == NULL && (((flag & PROP_REGISTER_OPTIONAL) != PROP_REGISTER_OPTIONAL))) { - PyErr_Format(PyExc_AttributeError, - "expected %.200s, %.200s class to have an \"%.200s\" attribute", - class_type, py_class_name, identifier); - return -1; - } - - PyErr_Clear(); - } - else { - if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) { - Py_DECREF(item); - return -1; - } - Py_DECREF(item); - } - } - - return 0; + const ListBase *lb = RNA_function_defined_parameters(func); + PropertyRNA *parm; + Link *link; + int flag = RNA_function_flag(func); + const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); + int count = is_staticmethod ? 0 : 1; + bool done_min_count = false; + + for (link = lb->first; link; link = link->next) { + parm = (PropertyRNA *)link; + if (!(RNA_parameter_flag(parm) & PARM_OUTPUT)) { + if (!done_min_count && (RNA_parameter_flag(parm) & PARM_PYFUNC_OPTIONAL)) { + /* From now on, following parameters are optional in py func */ + if (min_count) { + *min_count = count; + } + done_min_count = true; + } + count++; + } + } + + if (!done_min_count && min_count) { + *min_count = count; + } + return count; +} + +static int bpy_class_validate_recursive(PointerRNA *dummyptr, + StructRNA *srna, + void *py_data, + int *have_function) +{ + const ListBase *lb; + Link *link; + const char *class_type = RNA_struct_identifier(srna); + StructRNA *srna_base = RNA_struct_base(srna); + PyObject *py_class = (PyObject *)py_data; + PyObject *base_class = RNA_struct_py_type_get(srna); + PyObject *item; + int i, arg_count, func_arg_count, func_arg_min_count = 0; + const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */ + + if (srna_base) { + if (bpy_class_validate_recursive(dummyptr, srna_base, py_data, have_function) != 0) { + return -1; + } + } + + if (base_class) { + if (!PyObject_IsSubclass(py_class, base_class)) { + PyErr_Format(PyExc_TypeError, + "expected %.200s subclass of class \"%.200s\"", + class_type, + py_class_name); + return -1; + } + } + + /* verify callback functions */ + lb = RNA_struct_type_functions(srna); + i = 0; + for (link = lb->first; link; link = link->next) { + FunctionRNA *func = (FunctionRNA *)link; + const int flag = RNA_function_flag(func); + /* TODO(campbell): this is used for classmethod's too, + * even though class methods should have 'FUNC_USE_SELF_TYPE' set, see Operator.poll for eg. + * Keep this as-is since its working but we should be using 'FUNC_USE_SELF_TYPE' for many functions. */ + const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); + + if (!(flag & FUNC_REGISTER)) { + continue; + } + + item = PyObject_GetAttrString(py_class, RNA_function_identifier(func)); + + have_function[i] = (item != NULL); + i++; + + if (item == NULL) { + if ((flag & (FUNC_REGISTER_OPTIONAL & ~FUNC_REGISTER)) == 0) { + PyErr_Format(PyExc_AttributeError, + "expected %.200s, %.200s class to have an \"%.200s\" attribute", + class_type, + py_class_name, + RNA_function_identifier(func)); + return -1; + } + + PyErr_Clear(); + } + else { + Py_DECREF( + item); /* no need to keep a ref, the class owns it (technically we should keep a ref but...) */ + if (is_staticmethod) { + if (PyMethod_Check(item) == 0) { + PyErr_Format(PyExc_TypeError, + "expected %.200s, %.200s class \"%.200s\" " + "attribute to be a static/class method, not a %.200s", + class_type, + py_class_name, + RNA_function_identifier(func), + Py_TYPE(item)->tp_name); + return -1; + } + item = ((PyMethodObject *)item)->im_func; + } + else { + if (PyFunction_Check(item) == 0) { + PyErr_Format(PyExc_TypeError, + "expected %.200s, %.200s class \"%.200s\" " + "attribute to be a function, not a %.200s", + class_type, + py_class_name, + RNA_function_identifier(func), + Py_TYPE(item)->tp_name); + return -1; + } + } + + func_arg_count = rna_function_arg_count(func, &func_arg_min_count); + + if (func_arg_count >= 0) { /* -1 if we don't care*/ + arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; + + /* note, the number of args we check for and the number of args we give to + * '@staticmethods' are different (quirk of python), + * this is why rna_function_arg_count() doesn't return the value -1*/ + if (is_staticmethod) { + func_arg_count++; + func_arg_min_count++; + } + + if (arg_count < func_arg_min_count || arg_count > func_arg_count) { + if (func_arg_min_count != func_arg_count) { + PyErr_Format( + PyExc_ValueError, + "expected %.200s, %.200s class \"%.200s\" function to have between %d and %d " + "args, found %d", + class_type, + py_class_name, + RNA_function_identifier(func), + func_arg_count, + func_arg_min_count, + arg_count); + } + else { + PyErr_Format( + PyExc_ValueError, + "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d", + class_type, + py_class_name, + RNA_function_identifier(func), + func_arg_count, + arg_count); + } + return -1; + } + } + } + } + + /* verify properties */ + lb = RNA_struct_type_properties(srna); + for (link = lb->first; link; link = link->next) { + const char *identifier; + PropertyRNA *prop = (PropertyRNA *)link; + const int flag = RNA_property_flag(prop); + + if (!(flag & PROP_REGISTER)) { + continue; + } + + /* TODO(campbell): Use Python3.7x _PyObject_LookupAttr(), also in the macro below. */ + identifier = RNA_property_identifier(prop); + item = PyObject_GetAttrString(py_class, identifier); + + if (item == NULL) { + PyErr_Clear(); + /* Sneaky workaround to use the class name as the bl_idname */ + +#define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \ + else if (STREQ(identifier, rna_attr)) \ + { \ + if ((item = PyObject_GetAttr(py_class, py_attr))) { \ + if (item != Py_None) { \ + if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) { \ + Py_DECREF(item); \ + return -1; \ + } \ + } \ + Py_DECREF(item); \ + } \ + else { \ + PyErr_Clear(); \ + } \ + } /* intentionally allow else here */ + + if (false) { + } /* needed for macro */ + BPY_REPLACEMENT_STRING("bl_idname", bpy_intern_str___name__) + BPY_REPLACEMENT_STRING("bl_description", bpy_intern_str___doc__) + +#undef BPY_REPLACEMENT_STRING + + if (item == NULL && (((flag & PROP_REGISTER_OPTIONAL) != PROP_REGISTER_OPTIONAL))) { + PyErr_Format(PyExc_AttributeError, + "expected %.200s, %.200s class to have an \"%.200s\" attribute", + class_type, + py_class_name, + identifier); + return -1; + } + + PyErr_Clear(); + } + else { + if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) { + Py_DECREF(item); + return -1; + } + Py_DECREF(item); + } + } + + return 0; } static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_function) { - return bpy_class_validate_recursive(dummyptr, dummyptr->type, py_data, have_function); + return bpy_class_validate_recursive(dummyptr, dummyptr->type, py_data, have_function); } /* TODO - multiple return values like with rna functions */ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms) { - PyObject *args; - PyObject *ret = NULL, *py_srna = NULL, *py_class_instance = NULL, *parmitem; - PyTypeObject *py_class; - PropertyRNA *parm; - ParameterIterator iter; - PointerRNA funcptr; - int err = 0, i, ret_len = 0, arg_count; - int flag = RNA_function_flag(func); - const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); - const bool is_classmethod = (flag & FUNC_NO_SELF) && (flag & FUNC_USE_SELF_TYPE); + PyObject *args; + PyObject *ret = NULL, *py_srna = NULL, *py_class_instance = NULL, *parmitem; + PyTypeObject *py_class; + PropertyRNA *parm; + ParameterIterator iter; + PointerRNA funcptr; + int err = 0, i, ret_len = 0, arg_count; + int flag = RNA_function_flag(func); + const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); + const bool is_classmethod = (flag & FUNC_NO_SELF) && (flag & FUNC_USE_SELF_TYPE); - PropertyRNA *pret_single = NULL; - void *retdata_single = NULL; + PropertyRNA *pret_single = NULL; + void *retdata_single = NULL; - PyGILState_STATE gilstate; + PyGILState_STATE gilstate; #ifdef USE_PEDANTIC_WRITE - const bool is_readonly_init = !(RNA_struct_is_a(ptr->type, &RNA_Operator) || - RNA_struct_is_a(ptr->type, &RNA_Gizmo)); - // const char *func_id = RNA_function_identifier(func); /* UNUSED */ - /* testing, for correctness, not operator and not draw function */ - const bool is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE); + const bool is_readonly_init = !(RNA_struct_is_a(ptr->type, &RNA_Operator) || + RNA_struct_is_a(ptr->type, &RNA_Gizmo)); + // const char *func_id = RNA_function_identifier(func); /* UNUSED */ + /* testing, for correctness, not operator and not draw function */ + const bool is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE); #endif - py_class = RNA_struct_py_type_get(ptr->type); - /* rare case. can happen when registering subclasses */ - if (py_class == NULL) { - CLOG_WARN(BPY_LOG_RNA, "unable to get Python class for rna struct '%.200s'", RNA_struct_identifier(ptr->type)); - return -1; - } - - /* XXX, this is needed because render engine calls without a context - * this should be supported at some point but at the moment its not! */ - if (C == NULL) { - C = BPy_GetContext(); - } - - /* annoying!, need to check if the screen gets set to NULL which is a - * hint that the file was actually re-loaded. */ - const bool is_valid_wm = (CTX_wm_manager(C) != NULL); - - bpy_context_set(C, &gilstate); - - if (!(is_staticmethod || is_classmethod)) { - /* some datatypes (operator, render engine) can store PyObjects for re-use */ - if (ptr->data) { - void **instance = RNA_struct_instance(ptr); - - if (instance) { - if (*instance) { - py_class_instance = *instance; - Py_INCREF(py_class_instance); - } - } - } - /* end exception */ - - if (py_class_instance == NULL) { - py_srna = pyrna_struct_CreatePyObject(ptr); - } - - if (py_class_instance) { - /* special case, instance is cached */ - } - else if (py_srna == NULL) { - py_class_instance = NULL; - } - else if (py_srna == Py_None) { /* probably wont ever happen but possible */ - Py_DECREF(py_srna); - py_class_instance = NULL; - } - else { + py_class = RNA_struct_py_type_get(ptr->type); + /* rare case. can happen when registering subclasses */ + if (py_class == NULL) { + CLOG_WARN(BPY_LOG_RNA, + "unable to get Python class for rna struct '%.200s'", + RNA_struct_identifier(ptr->type)); + return -1; + } + + /* XXX, this is needed because render engine calls without a context + * this should be supported at some point but at the moment its not! */ + if (C == NULL) { + C = BPy_GetContext(); + } + + /* annoying!, need to check if the screen gets set to NULL which is a + * hint that the file was actually re-loaded. */ + const bool is_valid_wm = (CTX_wm_manager(C) != NULL); + + bpy_context_set(C, &gilstate); + + if (!(is_staticmethod || is_classmethod)) { + /* some datatypes (operator, render engine) can store PyObjects for re-use */ + if (ptr->data) { + void **instance = RNA_struct_instance(ptr); + + if (instance) { + if (*instance) { + py_class_instance = *instance; + Py_INCREF(py_class_instance); + } + } + } + /* end exception */ + + if (py_class_instance == NULL) { + py_srna = pyrna_struct_CreatePyObject(ptr); + } + + if (py_class_instance) { + /* special case, instance is cached */ + } + else if (py_srna == NULL) { + py_class_instance = NULL; + } + else if (py_srna == Py_None) { /* probably wont ever happen but possible */ + Py_DECREF(py_srna); + py_class_instance = NULL; + } + else { #if 1 - /* Skip the code below and call init directly on the allocated 'py_srna' - * otherwise __init__() always needs to take a second self argument, see pyrna_struct_new(). - * Although this is annoying to have to implement a part of pythons typeobject.c:type_call(). - */ - if (py_class->tp_init) { -#ifdef USE_PEDANTIC_WRITE - const int prev_write = rna_disallow_writes; - rna_disallow_writes = is_readonly_init ? false : true; /* only operators can write on __init__ */ -#endif - - /* true in most cases even when the class its self doesn't define an __init__ function. */ - args = PyTuple_New(0); - if (py_class->tp_init(py_srna, args, NULL) < 0) { - Py_DECREF(py_srna); - py_srna = NULL; - /* err set below */ - } - Py_DECREF(args); -#ifdef USE_PEDANTIC_WRITE - rna_disallow_writes = prev_write; -#endif - } - py_class_instance = py_srna; + /* Skip the code below and call init directly on the allocated 'py_srna' + * otherwise __init__() always needs to take a second self argument, see pyrna_struct_new(). + * Although this is annoying to have to implement a part of pythons typeobject.c:type_call(). + */ + if (py_class->tp_init) { +# ifdef USE_PEDANTIC_WRITE + const int prev_write = rna_disallow_writes; + rna_disallow_writes = is_readonly_init ? false : + true; /* only operators can write on __init__ */ +# endif + + /* true in most cases even when the class its self doesn't define an __init__ function. */ + args = PyTuple_New(0); + if (py_class->tp_init(py_srna, args, NULL) < 0) { + Py_DECREF(py_srna); + py_srna = NULL; + /* err set below */ + } + Py_DECREF(args); +# ifdef USE_PEDANTIC_WRITE + rna_disallow_writes = prev_write; +# endif + } + py_class_instance = py_srna; #else - const int prev_write = rna_disallow_writes; - rna_disallow_writes = true; - - /* 'almost' all the time calling the class isn't needed. - * We could just do... */ -#if 0 - py_class_instance = py_srna; - Py_INCREF(py_class_instance); -#endif - /* - * This would work fine but means __init__ functions wouldn't run. - * none of blenders default scripts use __init__ but its nice to call it - * for general correctness. just to note why this is here when it could be safely removed. - */ - args = PyTuple_New(1); - PyTuple_SET_ITEM(args, 0, py_srna); - py_class_instance = PyObject_Call(py_class, args, NULL); - Py_DECREF(args); - - rna_disallow_writes = prev_write; + const int prev_write = rna_disallow_writes; + rna_disallow_writes = true; + + /* 'almost' all the time calling the class isn't needed. + * We could just do... */ +# if 0 + py_class_instance = py_srna; + Py_INCREF(py_class_instance); +# endif + /* + * This would work fine but means __init__ functions wouldn't run. + * none of blenders default scripts use __init__ but its nice to call it + * for general correctness. just to note why this is here when it could be safely removed. + */ + args = PyTuple_New(1); + PyTuple_SET_ITEM(args, 0, py_srna); + py_class_instance = PyObject_Call(py_class, args, NULL); + Py_DECREF(args); + + rna_disallow_writes = prev_write; #endif - if (py_class_instance == NULL) { - err = -1; /* so the error is not overridden below */ - } - } - } - - /* Initializing the class worked, now run its invoke function */ - if (err != -1 && (is_staticmethod || is_classmethod || py_class_instance)) { - PyObject *item = PyObject_GetAttrString((PyObject *)py_class, RNA_function_identifier(func)); - - if (item) { - RNA_pointer_create(NULL, &RNA_Function, func, &funcptr); - - if (is_staticmethod) { - arg_count = ((PyCodeObject *)PyFunction_GET_CODE(((PyMethodObject *)item)->im_func))->co_argcount - 1; - } - else { - arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; - } -// args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */ - args = PyTuple_New(arg_count); /* first arg is included in 'item' */ - - - if (is_staticmethod) { - i = 0; - } - else if (is_classmethod) { - PyTuple_SET_ITEM(args, 0, (PyObject *)py_class); - i = 1; - } - else { - PyTuple_SET_ITEM(args, 0, py_class_instance); - i = 1; - } - - RNA_parameter_list_begin(parms, &iter); - - /* parse function parameters */ - for (; iter.valid; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - - /* only useful for single argument returns, we'll need another list loop for multiple */ - if (RNA_parameter_flag(parm) & PARM_OUTPUT) { - ret_len++; - if (pret_single == NULL) { - pret_single = parm; - retdata_single = iter.data; - } - - continue; - } - - if (i < arg_count) { - parmitem = pyrna_param_to_py(&funcptr, parm, iter.data); - PyTuple_SET_ITEM(args, i, parmitem); - i++; - } - } + if (py_class_instance == NULL) { + err = -1; /* so the error is not overridden below */ + } + } + } + + /* Initializing the class worked, now run its invoke function */ + if (err != -1 && (is_staticmethod || is_classmethod || py_class_instance)) { + PyObject *item = PyObject_GetAttrString((PyObject *)py_class, RNA_function_identifier(func)); + + if (item) { + RNA_pointer_create(NULL, &RNA_Function, func, &funcptr); + + if (is_staticmethod) { + arg_count = + ((PyCodeObject *)PyFunction_GET_CODE(((PyMethodObject *)item)->im_func))->co_argcount - + 1; + } + else { + arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; + } + // args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */ + args = PyTuple_New(arg_count); /* first arg is included in 'item' */ + + if (is_staticmethod) { + i = 0; + } + else if (is_classmethod) { + PyTuple_SET_ITEM(args, 0, (PyObject *)py_class); + i = 1; + } + else { + PyTuple_SET_ITEM(args, 0, py_class_instance); + i = 1; + } + + RNA_parameter_list_begin(parms, &iter); + + /* parse function parameters */ + for (; iter.valid; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + + /* only useful for single argument returns, we'll need another list loop for multiple */ + if (RNA_parameter_flag(parm) & PARM_OUTPUT) { + ret_len++; + if (pret_single == NULL) { + pret_single = parm; + retdata_single = iter.data; + } + + continue; + } + + if (i < arg_count) { + parmitem = pyrna_param_to_py(&funcptr, parm, iter.data); + PyTuple_SET_ITEM(args, i, parmitem); + i++; + } + } #ifdef USE_PEDANTIC_WRITE - rna_disallow_writes = is_readonly ? true : false; + rna_disallow_writes = is_readonly ? true : false; #endif - /* *** Main Caller *** */ + /* *** Main Caller *** */ - ret = PyObject_Call(item, args, NULL); + ret = PyObject_Call(item, args, NULL); - /* *** Done Calling *** */ + /* *** Done Calling *** */ #ifdef USE_PEDANTIC_WRITE - rna_disallow_writes = false; + rna_disallow_writes = false; #endif - RNA_parameter_list_end(&iter); - Py_DECREF(item); - Py_DECREF(args); - } - else { - PyErr_Print(); - PyErr_Clear(); - PyErr_Format(PyExc_TypeError, - "could not find function %.200s in %.200s to execute callback", - RNA_function_identifier(func), RNA_struct_identifier(ptr->type)); - err = -1; - } - } - else { - /* the error may be already set if the class instance couldn't be created */ - if (err != -1) { - PyErr_Format(PyExc_RuntimeError, - "could not create instance of %.200s to call callback function %.200s", - RNA_struct_identifier(ptr->type), RNA_function_identifier(func)); - err = -1; - } - } - - if (ret == NULL) { /* covers py_class_instance failing too */ - err = -1; - } - else { - if (ret_len == 0 && ret != Py_None) { - PyErr_Format(PyExc_RuntimeError, - "expected class %.200s, function %.200s to return None, not %.200s", - RNA_struct_identifier(ptr->type), RNA_function_identifier(func), - Py_TYPE(ret)->tp_name); - err = -1; - } - else if (ret_len == 1) { - err = pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, ""); - - /* when calling operator funcs only gives Function.result with - * no line number since the func has finished calling on error, - * re-raise the exception with more info since it would be slow to - * create prefix on every call (when there are no errors) */ - if (err == -1) { - PyC_Err_Format_Prefix(PyExc_RuntimeError, - "class %.200s, function %.200s: incompatible return value ", - RNA_struct_identifier(ptr->type), RNA_function_identifier(func)); - } - } - else if (ret_len > 1) { - - if (PyTuple_Check(ret) == 0) { - PyErr_Format(PyExc_RuntimeError, - "expected class %.200s, function %.200s to return a tuple of size %d, not %.200s", - RNA_struct_identifier(ptr->type), RNA_function_identifier(func), - ret_len, Py_TYPE(ret)->tp_name); - err = -1; - } - else if (PyTuple_GET_SIZE(ret) != ret_len) { - PyErr_Format(PyExc_RuntimeError, - "class %.200s, function %.200s to returned %d items, expected %d", - RNA_struct_identifier(ptr->type), RNA_function_identifier(func), - PyTuple_GET_SIZE(ret), ret_len); - err = -1; - } - else { - - RNA_parameter_list_begin(parms, &iter); - - /* parse function parameters */ - for (i = 0; iter.valid; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - - /* only useful for single argument returns, we'll need another list loop for multiple */ - if (RNA_parameter_flag(parm) & PARM_OUTPUT) { - err = pyrna_py_to_prop(&funcptr, parm, iter.data, - PyTuple_GET_ITEM(ret, i++), - "calling class function:"); - if (err) { - break; - } - } - } - - RNA_parameter_list_end(&iter); - } - } - Py_DECREF(ret); - } - - if (err != 0) { - ReportList *reports; - /* alert the user, else they wont know unless they see the console. */ - if ((!is_staticmethod) && (!is_classmethod) && - (ptr->data) && - (RNA_struct_is_a(ptr->type, &RNA_Operator)) && - (is_valid_wm == (CTX_wm_manager(C) != NULL))) - { - wmOperator *op = ptr->data; - reports = op->reports; - } - else { - /* wont alert users but they can view in 'info' space */ - reports = CTX_wm_reports(C); - } - - BPy_errors_to_report(reports); - - /* also print in the console for py */ - PyErr_Print(); - PyErr_Clear(); - } - - bpy_context_clear(C, &gilstate); - - return err; + RNA_parameter_list_end(&iter); + Py_DECREF(item); + Py_DECREF(args); + } + else { + PyErr_Print(); + PyErr_Clear(); + PyErr_Format(PyExc_TypeError, + "could not find function %.200s in %.200s to execute callback", + RNA_function_identifier(func), + RNA_struct_identifier(ptr->type)); + err = -1; + } + } + else { + /* the error may be already set if the class instance couldn't be created */ + if (err != -1) { + PyErr_Format(PyExc_RuntimeError, + "could not create instance of %.200s to call callback function %.200s", + RNA_struct_identifier(ptr->type), + RNA_function_identifier(func)); + err = -1; + } + } + + if (ret == NULL) { /* covers py_class_instance failing too */ + err = -1; + } + else { + if (ret_len == 0 && ret != Py_None) { + PyErr_Format(PyExc_RuntimeError, + "expected class %.200s, function %.200s to return None, not %.200s", + RNA_struct_identifier(ptr->type), + RNA_function_identifier(func), + Py_TYPE(ret)->tp_name); + err = -1; + } + else if (ret_len == 1) { + err = pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, ""); + + /* when calling operator funcs only gives Function.result with + * no line number since the func has finished calling on error, + * re-raise the exception with more info since it would be slow to + * create prefix on every call (when there are no errors) */ + if (err == -1) { + PyC_Err_Format_Prefix(PyExc_RuntimeError, + "class %.200s, function %.200s: incompatible return value ", + RNA_struct_identifier(ptr->type), + RNA_function_identifier(func)); + } + } + else if (ret_len > 1) { + + if (PyTuple_Check(ret) == 0) { + PyErr_Format( + PyExc_RuntimeError, + "expected class %.200s, function %.200s to return a tuple of size %d, not %.200s", + RNA_struct_identifier(ptr->type), + RNA_function_identifier(func), + ret_len, + Py_TYPE(ret)->tp_name); + err = -1; + } + else if (PyTuple_GET_SIZE(ret) != ret_len) { + PyErr_Format(PyExc_RuntimeError, + "class %.200s, function %.200s to returned %d items, expected %d", + RNA_struct_identifier(ptr->type), + RNA_function_identifier(func), + PyTuple_GET_SIZE(ret), + ret_len); + err = -1; + } + else { + + RNA_parameter_list_begin(parms, &iter); + + /* parse function parameters */ + for (i = 0; iter.valid; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + + /* only useful for single argument returns, we'll need another list loop for multiple */ + if (RNA_parameter_flag(parm) & PARM_OUTPUT) { + err = pyrna_py_to_prop( + &funcptr, parm, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:"); + if (err) { + break; + } + } + } + + RNA_parameter_list_end(&iter); + } + } + Py_DECREF(ret); + } + + if (err != 0) { + ReportList *reports; + /* alert the user, else they wont know unless they see the console. */ + if ((!is_staticmethod) && (!is_classmethod) && (ptr->data) && + (RNA_struct_is_a(ptr->type, &RNA_Operator)) && + (is_valid_wm == (CTX_wm_manager(C) != NULL))) { + wmOperator *op = ptr->data; + reports = op->reports; + } + else { + /* wont alert users but they can view in 'info' space */ + reports = CTX_wm_reports(C); + } + + BPy_errors_to_report(reports); + + /* also print in the console for py */ + PyErr_Print(); + PyErr_Clear(); + } + + bpy_context_clear(C, &gilstate); + + return err; } static void bpy_class_free(void *pyob_ptr) { - PyObject *self = (PyObject *)pyob_ptr; - PyGILState_STATE gilstate; + PyObject *self = (PyObject *)pyob_ptr; + PyGILState_STATE gilstate; - gilstate = PyGILState_Ensure(); + gilstate = PyGILState_Ensure(); - /* breaks re-registering classes */ - // PyDict_Clear(((PyTypeObject *)self)->tp_dict); + /* breaks re-registering classes */ + // PyDict_Clear(((PyTypeObject *)self)->tp_dict); - /* remove the rna attribute instead. */ - PyDict_DelItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna); - if (PyErr_Occurred()) { - PyErr_Clear(); - } + /* remove the rna attribute instead. */ + PyDict_DelItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna); + if (PyErr_Occurred()) { + PyErr_Clear(); + } #if 0 /* needs further investigation, too annoying so quiet for now */ - if (G.debug & G_DEBUG_PYTHON) { - if (self->ob_refcnt > 1) { - PyC_ObSpit("zombie class - ref should be 1", self); - } - } + if (G.debug & G_DEBUG_PYTHON) { + if (self->ob_refcnt > 1) { + PyC_ObSpit("zombie class - ref should be 1", self); + } + } #endif - Py_DECREF((PyObject *)pyob_ptr); + Py_DECREF((PyObject *)pyob_ptr); - PyGILState_Release(gilstate); + PyGILState_Release(gilstate); } /** @@ -8241,61 +8398,56 @@ static void bpy_class_free(void *pyob_ptr) void pyrna_alloc_types(void) { #ifdef DEBUG - PyGILState_STATE gilstate; + PyGILState_STATE gilstate; - PointerRNA ptr; - PropertyRNA *prop; + PointerRNA ptr; + PropertyRNA *prop; - gilstate = PyGILState_Ensure(); + gilstate = PyGILState_Ensure(); - /* avoid doing this lookup for every getattr */ - RNA_blender_rna_pointer_create(&ptr); - prop = RNA_struct_find_property(&ptr, "structs"); + /* avoid doing this lookup for every getattr */ + RNA_blender_rna_pointer_create(&ptr); + prop = RNA_struct_find_property(&ptr, "structs"); - RNA_PROP_BEGIN (&ptr, itemptr, prop) - { - PyObject *item = pyrna_struct_Subtype(&itemptr); - if (item == NULL) { - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } - } - else { - Py_DECREF(item); - } - } - RNA_PROP_END; + RNA_PROP_BEGIN (&ptr, itemptr, prop) { + PyObject *item = pyrna_struct_Subtype(&itemptr); + if (item == NULL) { + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + } + } + else { + Py_DECREF(item); + } + } + RNA_PROP_END; - PyGILState_Release(gilstate); -#endif /* DEBUG */ + PyGILState_Release(gilstate); +#endif /* DEBUG */ } - void pyrna_free_types(void) { - PointerRNA ptr; - PropertyRNA *prop; - - /* avoid doing this lookup for every getattr */ - RNA_blender_rna_pointer_create(&ptr); - prop = RNA_struct_find_property(&ptr, "structs"); + PointerRNA ptr; + PropertyRNA *prop; + /* avoid doing this lookup for every getattr */ + RNA_blender_rna_pointer_create(&ptr); + prop = RNA_struct_find_property(&ptr, "structs"); - RNA_PROP_BEGIN (&ptr, itemptr, prop) - { - StructRNA *srna = srna_from_ptr(&itemptr); - void *py_ptr = RNA_struct_py_type_get(srna); + RNA_PROP_BEGIN (&ptr, itemptr, prop) { + StructRNA *srna = srna_from_ptr(&itemptr); + void *py_ptr = RNA_struct_py_type_get(srna); - if (py_ptr) { -#if 0 /* XXX - should be able to do this but makes python crash on exit */ - bpy_class_free(py_ptr); + if (py_ptr) { +#if 0 /* XXX - should be able to do this but makes python crash on exit */ + bpy_class_free(py_ptr); #endif - RNA_struct_py_type_set(srna, NULL); - } - } - RNA_PROP_END; - + RNA_struct_py_type_set(srna, NULL); + } + } + RNA_PROP_END; } /* Note! MemLeak XXX @@ -8308,401 +8460,429 @@ void pyrna_free_types(void) * - Should still be fixed - Campbell * */ PyDoc_STRVAR(pyrna_register_class_doc, -".. method:: register_class(cls)\n" -"\n" -" Register a subclass of a blender type in (:class:`bpy.types.Panel`,\n" -" :class:`bpy.types.UIList`, :class:`bpy.types.Menu`, :class:`bpy.types.Header`,\n" -" :class:`bpy.types.Operator`, :class:`bpy.types.KeyingSetInfo`,\n" -" :class:`bpy.types.RenderEngine`).\n" -"\n" -" If the class has a *register* class method it will be called\n" -" before registration.\n" -"\n" -" .. note::\n" -"\n" -" :exc:`ValueError` exception is raised if the class is not a\n" -" subclass of a registerable blender class.\n" -"\n" -); -PyMethodDef meth_bpy_register_class = {"register_class", pyrna_register_class, METH_O, pyrna_register_class_doc}; + ".. method:: register_class(cls)\n" + "\n" + " Register a subclass of a blender type in (:class:`bpy.types.Panel`,\n" + " :class:`bpy.types.UIList`, :class:`bpy.types.Menu`, :class:`bpy.types.Header`,\n" + " :class:`bpy.types.Operator`, :class:`bpy.types.KeyingSetInfo`,\n" + " :class:`bpy.types.RenderEngine`).\n" + "\n" + " If the class has a *register* class method it will be called\n" + " before registration.\n" + "\n" + " .. note::\n" + "\n" + " :exc:`ValueError` exception is raised if the class is not a\n" + " subclass of a registerable blender class.\n" + "\n"); +PyMethodDef meth_bpy_register_class = { + "register_class", pyrna_register_class, METH_O, pyrna_register_class_doc}; static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class) { - bContext *C = NULL; - ReportList reports; - StructRegisterFunc reg; - StructRNA *srna; - StructRNA *srna_new; - const char *identifier; - PyObject *py_cls_meth; - const char *error_prefix = "register_class(...):"; - - if (!PyType_Check(py_class)) { - PyErr_Format(PyExc_ValueError, - "register_class(...): " - "expected a class argument, not '%.200s'", Py_TYPE(py_class)->tp_name); - return NULL; - } - - if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna)) { - PyErr_SetString(PyExc_ValueError, - "register_class(...): " - "already registered as a subclass"); - return NULL; - } - - if (!pyrna_write_check()) { - PyErr_Format(PyExc_RuntimeError, - "register_class(...): " - "can't run in readonly state '%.200s'", - ((PyTypeObject *)py_class)->tp_name); - return NULL; - } - - /* warning: gets parent classes srna, only for the register function */ - srna = pyrna_struct_as_srna(py_class, true, "register_class(...):"); - if (srna == NULL) { - return NULL; - } - - /* fails in cases, cant use this check but would like to :| */ + bContext *C = NULL; + ReportList reports; + StructRegisterFunc reg; + StructRNA *srna; + StructRNA *srna_new; + const char *identifier; + PyObject *py_cls_meth; + const char *error_prefix = "register_class(...):"; + + if (!PyType_Check(py_class)) { + PyErr_Format(PyExc_ValueError, + "register_class(...): " + "expected a class argument, not '%.200s'", + Py_TYPE(py_class)->tp_name); + return NULL; + } + + if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna)) { + PyErr_SetString(PyExc_ValueError, + "register_class(...): " + "already registered as a subclass"); + return NULL; + } + + if (!pyrna_write_check()) { + PyErr_Format(PyExc_RuntimeError, + "register_class(...): " + "can't run in readonly state '%.200s'", + ((PyTypeObject *)py_class)->tp_name); + return NULL; + } + + /* warning: gets parent classes srna, only for the register function */ + srna = pyrna_struct_as_srna(py_class, true, "register_class(...):"); + if (srna == NULL) { + return NULL; + } + + /* fails in cases, cant use this check but would like to :| */ #if 0 - if (RNA_struct_py_type_get(srna)) { - PyErr_Format(PyExc_ValueError, - "register_class(...): %.200s's parent class %.200s is already registered, this is not allowed", - ((PyTypeObject *)py_class)->tp_name, RNA_struct_identifier(srna)); - return NULL; - } + if (RNA_struct_py_type_get(srna)) { + PyErr_Format(PyExc_ValueError, + "register_class(...): %.200s's parent class %.200s is already registered, this is not allowed", + ((PyTypeObject *)py_class)->tp_name, RNA_struct_identifier(srna)); + return NULL; + } #endif - /* check that we have a register callback for this type */ - reg = RNA_struct_register(srna); - - if (!reg) { - PyErr_Format(PyExc_ValueError, - "register_class(...): expected a subclass of a registerable " - "rna type (%.200s does not support registration)", - RNA_struct_identifier(srna)); - return NULL; - } - - /* get the context, so register callback can do necessary refreshes */ - C = BPy_GetContext(); - - /* call the register callback with reports & identifier */ - BKE_reports_init(&reports, RPT_STORE); - - identifier = ((PyTypeObject *)py_class)->tp_name; - - srna_new = reg(CTX_data_main(C), &reports, py_class, identifier, - bpy_class_validate, bpy_class_call, bpy_class_free); - - if (!BLI_listbase_is_empty(&reports.list)) { - const bool has_error = BPy_reports_to_error(&reports, PyExc_RuntimeError, false); - if (!has_error) { - BPy_reports_write_stdout(&reports, error_prefix); - } - BKE_reports_clear(&reports); - if (has_error) { - return NULL; - } - } - - /* python errors validating are not converted into reports so the check above will fail. - * the cause for returning NULL will be printed as an error */ - if (srna_new == NULL) { - return NULL; - } - - pyrna_subtype_set_rna(py_class, srna_new); /* takes a ref to py_class */ - - /* old srna still references us, keep the check in case registering somehow can free it */ - if (RNA_struct_py_type_get(srna)) { - RNA_struct_py_type_set(srna, NULL); - // Py_DECREF(py_class); // should be able to do this XXX since the old rna adds a new ref. - } - - /* Can't use this because it returns a dict proxy - * - * item = PyObject_GetAttrString(py_class, "__dict__"); - */ - if (pyrna_deferred_register_class(srna_new, (PyTypeObject *)py_class) != 0) { - return NULL; - } - - /* call classed register method () */ - switch (_PyObject_LookupAttr(py_class, bpy_intern_str_register, &py_cls_meth)) { - case 1: - { - PyObject *ret = PyObject_CallObject(py_cls_meth, NULL); - if (ret) { - Py_DECREF(ret); - } - else { - return NULL; - } - break; - } - case -1: - { - return NULL; - } - } - - Py_RETURN_NONE; -} - - -static int pyrna_srna_contains_pointer_prop_srna( - StructRNA *srna_props, StructRNA *srna, - const char **r_prop_identifier) -{ - PropertyRNA *prop; - LinkData *link; - - /* verify properties */ - const ListBase *lb = RNA_struct_type_properties(srna); - - for (link = lb->first; link; link = link->next) { - prop = (PropertyRNA *)link; - if (RNA_property_type(prop) == PROP_POINTER && !RNA_property_builtin(prop)) { - PointerRNA tptr; - RNA_pointer_create(NULL, &RNA_Struct, srna_props, &tptr); - - if (RNA_property_pointer_type(&tptr, prop) == srna) { - *r_prop_identifier = RNA_property_identifier(prop); - return 1; - } - } - } - - return 0; + /* check that we have a register callback for this type */ + reg = RNA_struct_register(srna); + + if (!reg) { + PyErr_Format(PyExc_ValueError, + "register_class(...): expected a subclass of a registerable " + "rna type (%.200s does not support registration)", + RNA_struct_identifier(srna)); + return NULL; + } + + /* get the context, so register callback can do necessary refreshes */ + C = BPy_GetContext(); + + /* call the register callback with reports & identifier */ + BKE_reports_init(&reports, RPT_STORE); + + identifier = ((PyTypeObject *)py_class)->tp_name; + + srna_new = reg(CTX_data_main(C), + &reports, + py_class, + identifier, + bpy_class_validate, + bpy_class_call, + bpy_class_free); + + if (!BLI_listbase_is_empty(&reports.list)) { + const bool has_error = BPy_reports_to_error(&reports, PyExc_RuntimeError, false); + if (!has_error) { + BPy_reports_write_stdout(&reports, error_prefix); + } + BKE_reports_clear(&reports); + if (has_error) { + return NULL; + } + } + + /* python errors validating are not converted into reports so the check above will fail. + * the cause for returning NULL will be printed as an error */ + if (srna_new == NULL) { + return NULL; + } + + pyrna_subtype_set_rna(py_class, srna_new); /* takes a ref to py_class */ + + /* old srna still references us, keep the check in case registering somehow can free it */ + if (RNA_struct_py_type_get(srna)) { + RNA_struct_py_type_set(srna, NULL); + // Py_DECREF(py_class); // should be able to do this XXX since the old rna adds a new ref. + } + + /* Can't use this because it returns a dict proxy + * + * item = PyObject_GetAttrString(py_class, "__dict__"); + */ + if (pyrna_deferred_register_class(srna_new, (PyTypeObject *)py_class) != 0) { + return NULL; + } + + /* call classed register method () */ + switch (_PyObject_LookupAttr(py_class, bpy_intern_str_register, &py_cls_meth)) { + case 1: { + PyObject *ret = PyObject_CallObject(py_cls_meth, NULL); + if (ret) { + Py_DECREF(ret); + } + else { + return NULL; + } + break; + } + case -1: { + return NULL; + } + } + + Py_RETURN_NONE; +} + +static int pyrna_srna_contains_pointer_prop_srna(StructRNA *srna_props, + StructRNA *srna, + const char **r_prop_identifier) +{ + PropertyRNA *prop; + LinkData *link; + + /* verify properties */ + const ListBase *lb = RNA_struct_type_properties(srna); + + for (link = lb->first; link; link = link->next) { + prop = (PropertyRNA *)link; + if (RNA_property_type(prop) == PROP_POINTER && !RNA_property_builtin(prop)) { + PointerRNA tptr; + RNA_pointer_create(NULL, &RNA_Struct, srna_props, &tptr); + + if (RNA_property_pointer_type(&tptr, prop) == srna) { + *r_prop_identifier = RNA_property_identifier(prop); + return 1; + } + } + } + + return 0; } PyDoc_STRVAR(pyrna_unregister_class_doc, -".. method:: unregister_class(cls)\n" -"\n" -" Unload the python class from blender.\n" -"\n" -" If the class has an *unregister* class method it will be called\n" -" before unregistering.\n" -); + ".. method:: unregister_class(cls)\n" + "\n" + " Unload the python class from blender.\n" + "\n" + " If the class has an *unregister* class method it will be called\n" + " before unregistering.\n"); PyMethodDef meth_bpy_unregister_class = { - "unregister_class", pyrna_unregister_class, METH_O, pyrna_unregister_class_doc, + "unregister_class", + pyrna_unregister_class, + METH_O, + pyrna_unregister_class_doc, }; static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_class) { - bContext *C = NULL; - StructUnregisterFunc unreg; - StructRNA *srna; - PyObject *py_cls_meth; + bContext *C = NULL; + StructUnregisterFunc unreg; + StructRNA *srna; + PyObject *py_cls_meth; - if (!PyType_Check(py_class)) { - PyErr_Format(PyExc_ValueError, - "register_class(...): " - "expected a class argument, not '%.200s'", Py_TYPE(py_class)->tp_name); - return NULL; - } + if (!PyType_Check(py_class)) { + PyErr_Format(PyExc_ValueError, + "register_class(...): " + "expected a class argument, not '%.200s'", + Py_TYPE(py_class)->tp_name); + return NULL; + } #if 0 - if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna) == NULL) { - PWM_cursor_wait(0); - PyErr_SetString(PyExc_ValueError, "unregister_class(): not a registered as a subclass"); - return NULL; - } + if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna) == NULL) { + PWM_cursor_wait(0); + PyErr_SetString(PyExc_ValueError, "unregister_class(): not a registered as a subclass"); + return NULL; + } #endif - if (!pyrna_write_check()) { - PyErr_Format(PyExc_RuntimeError, - "unregister_class(...): " - "can't run in readonly state '%.200s'", - ((PyTypeObject *)py_class)->tp_name); - return NULL; - } - - srna = pyrna_struct_as_srna(py_class, false, "unregister_class(...):"); - if (srna == NULL) { - return NULL; - } - - /* check that we have a unregister callback for this type */ - unreg = RNA_struct_unregister(srna); - - if (!unreg) { - PyErr_SetString(PyExc_ValueError, - "unregister_class(...): " - "expected a Type subclassed from a registerable rna type (no unregister supported)"); - return NULL; - } - - /* call classed unregister method */ - switch (_PyObject_LookupAttr(py_class, bpy_intern_str_unregister, &py_cls_meth)) { - case 1: - { - PyObject *ret = PyObject_CallObject(py_cls_meth, NULL); - if (ret) { - Py_DECREF(ret); - } - else { - return NULL; - } - break; - } - case -1: - { - return NULL; - } - } - - /* should happen all the time but very slow */ - if (G.debug & G_DEBUG_PYTHON) { - /* remove all properties using this class */ - StructRNA *srna_iter; - PointerRNA ptr_rna; - PropertyRNA *prop_rna; - const char *prop_identifier = NULL; - - RNA_blender_rna_pointer_create(&ptr_rna); - prop_rna = RNA_struct_find_property(&ptr_rna, "structs"); - - - /* loop over all structs */ - RNA_PROP_BEGIN (&ptr_rna, itemptr, prop_rna) - { - srna_iter = itemptr.data; - if (pyrna_srna_contains_pointer_prop_srna(srna_iter, srna, &prop_identifier)) { - break; - } - } - RNA_PROP_END; - - if (prop_identifier) { - PyErr_Format(PyExc_RuntimeError, - "unregister_class(...): can't unregister %s because %s.%s pointer property is using this", - RNA_struct_identifier(srna), RNA_struct_identifier(srna_iter), prop_identifier); - return NULL; - } - } - - /* get the context, so register callback can do necessary refreshes */ - C = BPy_GetContext(); - - /* call unregister */ - unreg(CTX_data_main(C), srna); /* calls bpy_class_free, this decref's py_class */ - - PyDict_DelItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna); - if (PyErr_Occurred()) { - PyErr_Clear(); //return NULL; - } - - Py_RETURN_NONE; + if (!pyrna_write_check()) { + PyErr_Format(PyExc_RuntimeError, + "unregister_class(...): " + "can't run in readonly state '%.200s'", + ((PyTypeObject *)py_class)->tp_name); + return NULL; + } + + srna = pyrna_struct_as_srna(py_class, false, "unregister_class(...):"); + if (srna == NULL) { + return NULL; + } + + /* check that we have a unregister callback for this type */ + unreg = RNA_struct_unregister(srna); + + if (!unreg) { + PyErr_SetString( + PyExc_ValueError, + "unregister_class(...): " + "expected a Type subclassed from a registerable rna type (no unregister supported)"); + return NULL; + } + + /* call classed unregister method */ + switch (_PyObject_LookupAttr(py_class, bpy_intern_str_unregister, &py_cls_meth)) { + case 1: { + PyObject *ret = PyObject_CallObject(py_cls_meth, NULL); + if (ret) { + Py_DECREF(ret); + } + else { + return NULL; + } + break; + } + case -1: { + return NULL; + } + } + + /* should happen all the time but very slow */ + if (G.debug & G_DEBUG_PYTHON) { + /* remove all properties using this class */ + StructRNA *srna_iter; + PointerRNA ptr_rna; + PropertyRNA *prop_rna; + const char *prop_identifier = NULL; + + RNA_blender_rna_pointer_create(&ptr_rna); + prop_rna = RNA_struct_find_property(&ptr_rna, "structs"); + + /* loop over all structs */ + RNA_PROP_BEGIN (&ptr_rna, itemptr, prop_rna) { + srna_iter = itemptr.data; + if (pyrna_srna_contains_pointer_prop_srna(srna_iter, srna, &prop_identifier)) { + break; + } + } + RNA_PROP_END; + + if (prop_identifier) { + PyErr_Format(PyExc_RuntimeError, + "unregister_class(...): can't unregister %s because %s.%s pointer property is " + "using this", + RNA_struct_identifier(srna), + RNA_struct_identifier(srna_iter), + prop_identifier); + return NULL; + } + } + + /* get the context, so register callback can do necessary refreshes */ + C = BPy_GetContext(); + + /* call unregister */ + unreg(CTX_data_main(C), srna); /* calls bpy_class_free, this decref's py_class */ + + PyDict_DelItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna); + if (PyErr_Occurred()) { + PyErr_Clear(); //return NULL; + } + + Py_RETURN_NONE; } /* Access to 'owner_id' internal global. */ static PyObject *pyrna_bl_owner_id_get(PyObject *UNUSED(self)) { - const char *name = RNA_struct_state_owner_get(); - if (name) { - return PyUnicode_FromString(name); - } - Py_RETURN_NONE; + const char *name = RNA_struct_state_owner_get(); + if (name) { + return PyUnicode_FromString(name); + } + Py_RETURN_NONE; } static PyObject *pyrna_bl_owner_id_set(PyObject *UNUSED(self), PyObject *value) { - const char *name; - if (value == Py_None) { - name = NULL; - } - else if (PyUnicode_Check(value)) { - name = _PyUnicode_AsString(value); - } - else { - PyErr_Format(PyExc_ValueError, - "owner_set(...): " - "expected None or a string, not '%.200s'", Py_TYPE(value)->tp_name); - return NULL; - } - RNA_struct_state_owner_set(name); - Py_RETURN_NONE; + const char *name; + if (value == Py_None) { + name = NULL; + } + else if (PyUnicode_Check(value)) { + name = _PyUnicode_AsString(value); + } + else { + PyErr_Format(PyExc_ValueError, + "owner_set(...): " + "expected None or a string, not '%.200s'", + Py_TYPE(value)->tp_name); + return NULL; + } + RNA_struct_state_owner_set(name); + Py_RETURN_NONE; } PyMethodDef meth_bpy_owner_id_get = { - "_bl_owner_id_get", (PyCFunction)pyrna_bl_owner_id_get, METH_NOARGS, NULL, + "_bl_owner_id_get", + (PyCFunction)pyrna_bl_owner_id_get, + METH_NOARGS, + NULL, }; PyMethodDef meth_bpy_owner_id_set = { - "_bl_owner_id_set", (PyCFunction)pyrna_bl_owner_id_set, METH_O, NULL, + "_bl_owner_id_set", + (PyCFunction)pyrna_bl_owner_id_set, + METH_O, + NULL, }; /* currently this is fairly limited, we would need to make some way to split up * pyrna_callback_classmethod_... if we want more than one callback per type */ typedef struct BPyRNA_CallBack { - PyMethodDef py_method; - StructRNA *bpy_srna; + PyMethodDef py_method; + StructRNA *bpy_srna; } PyRNA_CallBack; -PyDoc_STRVAR(pyrna_draw_handler_add_doc, -".. method:: draw_handler_add(callback, args, region_type, draw_type)\n" -"\n" -" Add a new draw handler to this space type.\n" -" It will be called every time the specified region in the space type will be drawn.\n" -" Note: All arguments are positional only for now.\n" -"\n" -" :param callback:\n" -" A function that will be called when the region is drawn.\n" -" It gets the specified arguments as input.\n" -" :type callback: function\n" -" :param args: Arguments that will be passed to the callback.\n" -" :type args: tuple\n" -" :param region_type: The region type the callback draws in; usually `'WINDOW'`. (:class:`bpy.types.Region.type`)\n" -" :type region_type: str\n" -" :param draw_type: Usually `POST_PIXEL` for 2D drawing and `POST_VIEW` for 3D drawing. In some cases `PRE_VIEW` can be used.\n" -" :type draw_type: str\n" -" :return: Handler that can be removed later on.\n" -" :rtype: object" -); +PyDoc_STRVAR( + pyrna_draw_handler_add_doc, + ".. method:: draw_handler_add(callback, args, region_type, draw_type)\n" + "\n" + " Add a new draw handler to this space type.\n" + " It will be called every time the specified region in the space type will be drawn.\n" + " Note: All arguments are positional only for now.\n" + "\n" + " :param callback:\n" + " A function that will be called when the region is drawn.\n" + " It gets the specified arguments as input.\n" + " :type callback: function\n" + " :param args: Arguments that will be passed to the callback.\n" + " :type args: tuple\n" + " :param region_type: The region type the callback draws in; usually `'WINDOW'`. " + "(:class:`bpy.types.Region.type`)\n" + " :type region_type: str\n" + " :param draw_type: Usually `POST_PIXEL` for 2D drawing and `POST_VIEW` for 3D drawing. In " + "some cases `PRE_VIEW` can be used.\n" + " :type draw_type: str\n" + " :return: Handler that can be removed later on.\n" + " :rtype: object"); PyDoc_STRVAR(pyrna_draw_handler_remove_doc, -".. method:: draw_handler_remove(handler, region_type)\n" -"\n" -" Remove a draw handler that was added previously.\n" -"\n" -" :param handler: The draw handler that should be removed.\n" -" :type handler: object\n" -" :param region_type: Region type the callback was added to.\n" -" :type region_type: str\n" -); + ".. method:: draw_handler_remove(handler, region_type)\n" + "\n" + " Remove a draw handler that was added previously.\n" + "\n" + " :param handler: The draw handler that should be removed.\n" + " :type handler: object\n" + " :param region_type: Region type the callback was added to.\n" + " :type region_type: str\n"); static struct BPyRNA_CallBack pyrna_cb_methods[] = { - {{"draw_handler_add", (PyCFunction)pyrna_callback_classmethod_add, - METH_VARARGS | METH_STATIC, pyrna_draw_handler_add_doc}, &RNA_Space}, - {{"draw_handler_remove", (PyCFunction)pyrna_callback_classmethod_remove, - METH_VARARGS | METH_STATIC, pyrna_draw_handler_remove_doc}, &RNA_Space}, - - {{"draw_cursor_add", (PyCFunction)pyrna_callback_classmethod_add, METH_VARARGS | METH_STATIC, ""}, &RNA_WindowManager}, - {{"draw_cursor_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_STATIC, ""}, &RNA_WindowManager}, - {{NULL, NULL, 0, NULL}, NULL}, + {{"draw_handler_add", + (PyCFunction)pyrna_callback_classmethod_add, + METH_VARARGS | METH_STATIC, + pyrna_draw_handler_add_doc}, + &RNA_Space}, + {{"draw_handler_remove", + (PyCFunction)pyrna_callback_classmethod_remove, + METH_VARARGS | METH_STATIC, + pyrna_draw_handler_remove_doc}, + &RNA_Space}, + + {{"draw_cursor_add", + (PyCFunction)pyrna_callback_classmethod_add, + METH_VARARGS | METH_STATIC, + ""}, + &RNA_WindowManager}, + {{"draw_cursor_remove", + (PyCFunction)pyrna_callback_classmethod_remove, + METH_VARARGS | METH_STATIC, + ""}, + &RNA_WindowManager}, + {{NULL, NULL, 0, NULL}, NULL}, }; void BPY_rna_register_cb(void) { - int i; + int i; - for (i = 0; pyrna_cb_methods[i].bpy_srna; i++) { - PyObject *cls; - PyObject *func; - PyObject *classmethod; - PyObject *args = PyTuple_New(1); + for (i = 0; pyrna_cb_methods[i].bpy_srna; i++) { + PyObject *cls; + PyObject *func; + PyObject *classmethod; + PyObject *args = PyTuple_New(1); - cls = pyrna_srna_Subtype(pyrna_cb_methods[i].bpy_srna); - func = PyCFunction_New(&pyrna_cb_methods[i].py_method, NULL); - PyTuple_SET_ITEM(args, 0, func); - classmethod = PyObject_CallObject((PyObject *)&PyClassMethod_Type, args); + cls = pyrna_srna_Subtype(pyrna_cb_methods[i].bpy_srna); + func = PyCFunction_New(&pyrna_cb_methods[i].py_method, NULL); + PyTuple_SET_ITEM(args, 0, func); + classmethod = PyObject_CallObject((PyObject *)&PyClassMethod_Type, args); - PyObject_SetAttrString(cls, pyrna_cb_methods[i].py_method.ml_name, classmethod); + PyObject_SetAttrString(cls, pyrna_cb_methods[i].py_method.ml_name, classmethod); - Py_DECREF(classmethod); - Py_DECREF(args); /* clears 'func' too */ - Py_DECREF(cls); - } + Py_DECREF(classmethod); + Py_DECREF(args); /* clears 'func' too */ + Py_DECREF(cls); + } } diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index c4c6944d46d..588c3cbf171 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -25,31 +25,30 @@ #ifdef WITH_PYTHON_SAFETY /* play it safe and keep optional for now, need to test further now this affects looping on 10000's of verts for eg. */ -#define USE_WEAKREFS +# define USE_WEAKREFS /* method to invalidate removed py data, XXX, slow to remove objects, otherwise no overhead */ /* #define USE_PYRNA_INVALIDATE_GC */ /* different method */ -#define USE_PYRNA_INVALIDATE_WEAKREF +# define USE_PYRNA_INVALIDATE_WEAKREF /* support for inter references, currently only needed for corner case */ -#define USE_PYRNA_STRUCT_REFERENCE +# define USE_PYRNA_STRUCT_REFERENCE #else /* WITH_PYTHON_SAFETY */ - /* default, no defines! */ +/* default, no defines! */ #endif /* !WITH_PYTHON_SAFETY */ - /* sanity checks on above defs */ #if defined(USE_PYRNA_INVALIDATE_WEAKREF) && !defined(USE_WEAKREFS) -#define USE_WEAKREFS +# define USE_WEAKREFS #endif #if defined(USE_PYRNA_INVALIDATE_GC) && defined(USE_PYRNA_INVALIDATE_WEAKREF) -#error "Only 1 reference check method at a time!" +# error "Only 1 reference check method at a time!" #endif /* only used by operator introspection get_rna(), this is only used for doc gen @@ -72,86 +71,102 @@ extern PyTypeObject pyrna_prop_array_Type; extern PyTypeObject pyrna_prop_collection_Type; extern PyTypeObject pyrna_func_Type; -#define BPy_StructRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_struct_Type)) -#define BPy_StructRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_struct_Type) -#define BPy_PropertyRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_prop_Type)) -#define BPy_PropertyRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_prop_Type) - -#define PYRNA_STRUCT_CHECK_OBJ(obj) if (UNLIKELY(pyrna_struct_validity_check(obj) == -1)) { return NULL; } (void)0 -#define PYRNA_STRUCT_CHECK_INT(obj) if (UNLIKELY(pyrna_struct_validity_check(obj) == -1)) { return -1; } (void)0 - -#define PYRNA_PROP_CHECK_OBJ(obj) if (UNLIKELY(pyrna_prop_validity_check(obj) == -1)) { return NULL; } (void)0 -#define PYRNA_PROP_CHECK_INT(obj) if (UNLIKELY(pyrna_prop_validity_check(obj) == -1)) { return -1; } (void)0 +#define BPy_StructRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_struct_Type)) +#define BPy_StructRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_struct_Type) +#define BPy_PropertyRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_prop_Type)) +#define BPy_PropertyRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_prop_Type) + +#define PYRNA_STRUCT_CHECK_OBJ(obj) \ + if (UNLIKELY(pyrna_struct_validity_check(obj) == -1)) { \ + return NULL; \ + } \ + (void)0 +#define PYRNA_STRUCT_CHECK_INT(obj) \ + if (UNLIKELY(pyrna_struct_validity_check(obj) == -1)) { \ + return -1; \ + } \ + (void)0 + +#define PYRNA_PROP_CHECK_OBJ(obj) \ + if (UNLIKELY(pyrna_prop_validity_check(obj) == -1)) { \ + return NULL; \ + } \ + (void)0 +#define PYRNA_PROP_CHECK_INT(obj) \ + if (UNLIKELY(pyrna_prop_validity_check(obj) == -1)) { \ + return -1; \ + } \ + (void)0 #define PYRNA_STRUCT_IS_VALID(pysrna) (LIKELY(((BPy_StructRNA *)(pysrna))->ptr.type != NULL)) -#define PYRNA_PROP_IS_VALID(pysrna) (LIKELY(((BPy_PropertyRNA *)(pysrna))->ptr.type != NULL)) +#define PYRNA_PROP_IS_VALID(pysrna) (LIKELY(((BPy_PropertyRNA *)(pysrna))->ptr.type != NULL)) /* 'in_weakreflist' MUST be aligned */ typedef struct { - PyObject_HEAD /* required python macro */ + PyObject_HEAD /* required python macro */ #ifdef USE_WEAKREFS - PyObject *in_weakreflist; + PyObject *in_weakreflist; #endif - PointerRNA ptr; + PointerRNA ptr; } BPy_DummyPointerRNA; typedef struct { - PyObject_HEAD /* required python macro */ + PyObject_HEAD /* required python macro */ #ifdef USE_WEAKREFS - PyObject *in_weakreflist; + PyObject *in_weakreflist; #endif - PointerRNA ptr; + PointerRNA ptr; #ifdef USE_PYRNA_STRUCT_REFERENCE - /* generic PyObject we hold a reference to, example use: - * hold onto the collection iterator to prevent it from freeing allocated data we may use */ - PyObject *reference; + /* generic PyObject we hold a reference to, example use: + * hold onto the collection iterator to prevent it from freeing allocated data we may use */ + PyObject *reference; #endif /* !USE_PYRNA_STRUCT_REFERENCE */ #ifdef PYRNA_FREE_SUPPORT - bool freeptr; /* needed in some cases if ptr.data is created on the fly, free when deallocing */ -#endif /* PYRNA_FREE_SUPPORT */ + bool freeptr; /* needed in some cases if ptr.data is created on the fly, free when deallocing */ +#endif /* PYRNA_FREE_SUPPORT */ } BPy_StructRNA; typedef struct { - PyObject_HEAD /* required python macro */ + PyObject_HEAD /* required python macro */ #ifdef USE_WEAKREFS - PyObject *in_weakreflist; + PyObject *in_weakreflist; #endif - PointerRNA ptr; - PropertyRNA *prop; + PointerRNA ptr; + PropertyRNA *prop; } BPy_PropertyRNA; typedef struct { - PyObject_HEAD /* required python macro */ + PyObject_HEAD /* required python macro */ #ifdef USE_WEAKREFS - PyObject *in_weakreflist; + PyObject *in_weakreflist; #endif - PointerRNA ptr; - PropertyRNA *prop; + PointerRNA ptr; + PropertyRNA *prop; - /* Arystan: this is a hack to allow sub-item r/w access like: face.uv[n][m] */ - int arraydim; /* array dimension, e.g: 0 for face.uv, 2 for face.uv[n][m], etc. */ - int arrayoffset; /* array first item offset, e.g. if face.uv is [4][2], arrayoffset for face.uv[n] is 2n */ + /* Arystan: this is a hack to allow sub-item r/w access like: face.uv[n][m] */ + int arraydim; /* array dimension, e.g: 0 for face.uv, 2 for face.uv[n][m], etc. */ + int arrayoffset; /* array first item offset, e.g. if face.uv is [4][2], arrayoffset for face.uv[n] is 2n */ } BPy_PropertyArrayRNA; typedef struct { - PyObject_HEAD /* required python macro */ + PyObject_HEAD /* required python macro */ #ifdef USE_WEAKREFS - PyObject *in_weakreflist; + PyObject *in_weakreflist; #endif - /* collection iterator specific parts */ - CollectionPropertyIterator iter; + /* collection iterator specific parts */ + CollectionPropertyIterator iter; } BPy_PropertyCollectionIterRNA; typedef struct { - PyObject_HEAD /* required python macro */ + PyObject_HEAD /* required python macro */ #ifdef USE_WEAKREFS - PyObject *in_weakreflist; + PyObject *in_weakreflist; #endif - PointerRNA ptr; - FunctionRNA *func; + PointerRNA ptr; + FunctionRNA *func; } BPy_FunctionRNA; /* cheap trick */ @@ -160,37 +175,44 @@ typedef struct { StructRNA *srna_from_self(PyObject *self, const char *error_prefix); StructRNA *pyrna_struct_as_srna(PyObject *self, const bool parent, const char *error_prefix); -void BPY_rna_init(void); +void BPY_rna_init(void); PyObject *BPY_rna_module(void); -void BPY_update_rna_module(void); +void BPY_update_rna_module(void); /*PyObject *BPY_rna_doc(void);*/ PyObject *BPY_rna_types(void); -void BPY_rna_register_cb(void); +void BPY_rna_register_cb(void); PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr); PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop); /* extern'd by other modules which don't deal closely with RNA */ PyObject *pyrna_id_CreatePyObject(struct ID *id); -bool pyrna_id_FromPyObject(PyObject *obj, struct ID **id); -bool pyrna_id_CheckPyObject(PyObject *obj); +bool pyrna_id_FromPyObject(PyObject *obj, struct ID **id); +bool pyrna_id_CheckPyObject(PyObject *obj); /* operators also need this to set args */ -int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const bool all_args, const char *error_prefix); +int pyrna_pydict_to_props(PointerRNA *ptr, + PyObject *kw, + const bool all_args, + const char *error_prefix); PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop); -unsigned int *pyrna_set_to_enum_bitmap( - const struct EnumPropertyItem *items, PyObject *value, - int type_size, bool type_convert_sign, - int bitmap_size, - const char *error_prefix); -PyObject *pyrna_enum_bitfield_to_py( - const struct EnumPropertyItem *items, int value); -int pyrna_set_to_enum_bitfield( - const struct EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix); - -int pyrna_enum_value_from_id( - const EnumPropertyItem *item, const char *identifier, int *value, const char *error_prefix); +unsigned int *pyrna_set_to_enum_bitmap(const struct EnumPropertyItem *items, + PyObject *value, + int type_size, + bool type_convert_sign, + int bitmap_size, + const char *error_prefix); +PyObject *pyrna_enum_bitfield_to_py(const struct EnumPropertyItem *items, int value); +int pyrna_set_to_enum_bitfield(const struct EnumPropertyItem *items, + PyObject *value, + int *r_value, + const char *error_prefix); + +int pyrna_enum_value_from_id(const EnumPropertyItem *item, + const char *identifier, + int *value, + const char *error_prefix); int pyrna_deferred_register_class(struct StructRNA *srna, PyTypeObject *py_class); @@ -199,12 +221,22 @@ void pyrna_alloc_types(void); void pyrna_free_types(void); /* primitive type conversion */ -int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix); -int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, PyObject *py, const char *error_prefix); +int pyrna_py_to_array( + PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix); +int pyrna_py_to_array_index(PointerRNA *ptr, + PropertyRNA *prop, + int arraydim, + int arrayoffset, + int index, + PyObject *py, + const char *error_prefix); PyObject *pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index); PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop); -PyObject *pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, int index); +PyObject *pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, + PointerRNA *ptr, + PropertyRNA *prop, + int index); PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop); int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value); diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index a25906ac9a1..2cd8c8641bb 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -56,554 +56,596 @@ #include "../generic/python_utildefines.h" /* for keyframes and drivers */ -static int pyrna_struct_anim_args_parse_ex( - PointerRNA *ptr, const char *error_prefix, const char *path, - const char **r_path_full, int *r_index, bool *r_path_no_validate) +static int pyrna_struct_anim_args_parse_ex(PointerRNA *ptr, + const char *error_prefix, + const char *path, + const char **r_path_full, + int *r_index, + bool *r_path_no_validate) { - const bool is_idbase = RNA_struct_is_ID(ptr->type); - PropertyRNA *prop; - PointerRNA r_ptr; - - if (ptr->data == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s this struct has no data, can't be animated", - error_prefix); - return -1; - } - - /* full paths can only be given from ID base */ - if (is_idbase) { - int path_index = -1; - if (RNA_path_resolve_property_full(ptr, path, &r_ptr, &prop, &path_index) == false) { - prop = NULL; - } - else if (path_index != -1) { - PyErr_Format(PyExc_ValueError, - "%.200s path includes index, must be a separate argument", - error_prefix, path); - return -1; - } - else if (ptr->id.data != r_ptr.id.data) { - PyErr_Format(PyExc_ValueError, - "%.200s path spans ID blocks", - error_prefix, path); - return -1; - } - } - else { - prop = RNA_struct_find_property(ptr, path); - r_ptr = *ptr; - } - - if (prop == NULL) { - if (r_path_no_validate) { - *r_path_no_validate = true; - return -1; - } - PyErr_Format(PyExc_TypeError, - "%.200s property \"%s\" not found", - error_prefix, path); - return -1; - } - - if (r_path_no_validate) { - /* Don't touch the index. */ - } - else { - if (!RNA_property_animateable(&r_ptr, prop)) { - PyErr_Format(PyExc_TypeError, - "%.200s property \"%s\" not animatable", - error_prefix, path); - return -1; - } - - if (RNA_property_array_check(prop) == 0) { - if ((*r_index) == -1) { - *r_index = 0; - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s index %d was given while property \"%s\" is not an array", - error_prefix, *r_index, path); - return -1; - } - } - else { - int array_len = RNA_property_array_length(&r_ptr, prop); - if ((*r_index) < -1 || (*r_index) >= array_len) { - PyErr_Format(PyExc_TypeError, - "%.200s index out of range \"%s\", given %d, array length is %d", - error_prefix, path, *r_index, array_len); - return -1; - } - } - } - - if (is_idbase) { - *r_path_full = BLI_strdup(path); - } - else { - *r_path_full = RNA_path_from_ID_to_property(&r_ptr, prop); - - if (*r_path_full == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s could not make path to \"%s\"", - error_prefix, path); - return -1; - } - } - - return 0; + const bool is_idbase = RNA_struct_is_ID(ptr->type); + PropertyRNA *prop; + PointerRNA r_ptr; + + if (ptr->data == NULL) { + PyErr_Format( + PyExc_TypeError, "%.200s this struct has no data, can't be animated", error_prefix); + return -1; + } + + /* full paths can only be given from ID base */ + if (is_idbase) { + int path_index = -1; + if (RNA_path_resolve_property_full(ptr, path, &r_ptr, &prop, &path_index) == false) { + prop = NULL; + } + else if (path_index != -1) { + PyErr_Format(PyExc_ValueError, + "%.200s path includes index, must be a separate argument", + error_prefix, + path); + return -1; + } + else if (ptr->id.data != r_ptr.id.data) { + PyErr_Format(PyExc_ValueError, "%.200s path spans ID blocks", error_prefix, path); + return -1; + } + } + else { + prop = RNA_struct_find_property(ptr, path); + r_ptr = *ptr; + } + + if (prop == NULL) { + if (r_path_no_validate) { + *r_path_no_validate = true; + return -1; + } + PyErr_Format(PyExc_TypeError, "%.200s property \"%s\" not found", error_prefix, path); + return -1; + } + + if (r_path_no_validate) { + /* Don't touch the index. */ + } + else { + if (!RNA_property_animateable(&r_ptr, prop)) { + PyErr_Format(PyExc_TypeError, "%.200s property \"%s\" not animatable", error_prefix, path); + return -1; + } + + if (RNA_property_array_check(prop) == 0) { + if ((*r_index) == -1) { + *r_index = 0; + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s index %d was given while property \"%s\" is not an array", + error_prefix, + *r_index, + path); + return -1; + } + } + else { + int array_len = RNA_property_array_length(&r_ptr, prop); + if ((*r_index) < -1 || (*r_index) >= array_len) { + PyErr_Format(PyExc_TypeError, + "%.200s index out of range \"%s\", given %d, array length is %d", + error_prefix, + path, + *r_index, + array_len); + return -1; + } + } + } + + if (is_idbase) { + *r_path_full = BLI_strdup(path); + } + else { + *r_path_full = RNA_path_from_ID_to_property(&r_ptr, prop); + + if (*r_path_full == NULL) { + PyErr_Format(PyExc_TypeError, "%.200s could not make path to \"%s\"", error_prefix, path); + return -1; + } + } + + return 0; } -static int pyrna_struct_anim_args_parse( - PointerRNA *ptr, const char *error_prefix, const char *path, - const char **r_path_full, int *r_index) +static int pyrna_struct_anim_args_parse(PointerRNA *ptr, + const char *error_prefix, + const char *path, + const char **r_path_full, + int *r_index) { - return pyrna_struct_anim_args_parse_ex(ptr, error_prefix, path, r_path_full, r_index, NULL); + return pyrna_struct_anim_args_parse_ex(ptr, error_prefix, path, r_path_full, r_index, NULL); } /** * Unlike #pyrna_struct_anim_args_parse \a r_path_full may be copied from \a path. */ -static int pyrna_struct_anim_args_parse_no_resolve( - PointerRNA *ptr, const char *error_prefix, const char *path, - const char **r_path_full) +static int pyrna_struct_anim_args_parse_no_resolve(PointerRNA *ptr, + const char *error_prefix, + const char *path, + const char **r_path_full) { - const bool is_idbase = RNA_struct_is_ID(ptr->type); - if (is_idbase) { - *r_path_full = path; - return 0; - } - else { - char *path_prefix = RNA_path_from_ID_to_struct(ptr); - if (path_prefix == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s could not make path for type %s", - error_prefix, RNA_struct_identifier(ptr->type)); - return -1; - } - - if (*path == '[') { - *r_path_full = BLI_string_joinN(path_prefix, path); - } - else { - *r_path_full = BLI_string_join_by_sep_charN('.', path_prefix, path); - } - MEM_freeN(path_prefix); - } - return 0; + const bool is_idbase = RNA_struct_is_ID(ptr->type); + if (is_idbase) { + *r_path_full = path; + return 0; + } + else { + char *path_prefix = RNA_path_from_ID_to_struct(ptr); + if (path_prefix == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s could not make path for type %s", + error_prefix, + RNA_struct_identifier(ptr->type)); + return -1; + } + + if (*path == '[') { + *r_path_full = BLI_string_joinN(path_prefix, path); + } + else { + *r_path_full = BLI_string_join_by_sep_charN('.', path_prefix, path); + } + MEM_freeN(path_prefix); + } + return 0; } -static int pyrna_struct_anim_args_parse_no_resolve_fallback( - PointerRNA *ptr, const char *error_prefix, const char *path, - const char **r_path_full, int *r_index) +static int pyrna_struct_anim_args_parse_no_resolve_fallback(PointerRNA *ptr, + const char *error_prefix, + const char *path, + const char **r_path_full, + int *r_index) { - bool path_unresolved = false; - if (pyrna_struct_anim_args_parse_ex( - ptr, error_prefix, path, - r_path_full, r_index, &path_unresolved) == -1) - { - if (path_unresolved == true) { - if (pyrna_struct_anim_args_parse_no_resolve( - ptr, error_prefix, path, r_path_full) == -1) - { - return -1; - } - } - else { - return -1; - } - } - return 0; + bool path_unresolved = false; + if (pyrna_struct_anim_args_parse_ex( + ptr, error_prefix, path, r_path_full, r_index, &path_unresolved) == -1) { + if (path_unresolved == true) { + if (pyrna_struct_anim_args_parse_no_resolve(ptr, error_prefix, path, r_path_full) == -1) { + return -1; + } + } + else { + return -1; + } + } + return 0; } /* internal use for insert and delete */ -static int pyrna_struct_keyframe_parse( - PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix, - /* return values */ - const char **r_path_full, int *r_index, float *r_cfra, const char **r_group_name, int *r_options) +static int pyrna_struct_keyframe_parse(PointerRNA *ptr, + PyObject *args, + PyObject *kw, + const char *parse_str, + const char *error_prefix, + /* return values */ + const char **r_path_full, + int *r_index, + float *r_cfra, + const char **r_group_name, + int *r_options) { - static const char *kwlist[] = {"data_path", "index", "frame", "group", "options", NULL}; - PyObject *pyoptions = NULL; - const char *path; - - /* note, parse_str MUST start with 's|ifsO!' */ - if (!PyArg_ParseTupleAndKeywords( - args, kw, parse_str, (char **)kwlist, &path, r_index, r_cfra, r_group_name, - &PySet_Type, &pyoptions)) - { - return -1; - } - - if (pyrna_struct_anim_args_parse( - ptr, error_prefix, path, - r_path_full, r_index) == -1) - { - return -1; - } - - if (*r_cfra == FLT_MAX) { - *r_cfra = CTX_data_scene(BPy_GetContext())->r.cfra; - } - - /* flag may be null (no option currently for remove keyframes e.g.). */ - if (r_options) { - if (pyoptions && - (pyrna_set_to_enum_bitfield( - rna_enum_keying_flag_items, pyoptions, r_options, error_prefix) == -1)) - { - return -1; - } - - *r_options |= INSERTKEY_NO_USERPREF; - } - - return 0; /* success */ + static const char *kwlist[] = {"data_path", "index", "frame", "group", "options", NULL}; + PyObject *pyoptions = NULL; + const char *path; + + /* note, parse_str MUST start with 's|ifsO!' */ + if (!PyArg_ParseTupleAndKeywords(args, + kw, + parse_str, + (char **)kwlist, + &path, + r_index, + r_cfra, + r_group_name, + &PySet_Type, + &pyoptions)) { + return -1; + } + + if (pyrna_struct_anim_args_parse(ptr, error_prefix, path, r_path_full, r_index) == -1) { + return -1; + } + + if (*r_cfra == FLT_MAX) { + *r_cfra = CTX_data_scene(BPy_GetContext())->r.cfra; + } + + /* flag may be null (no option currently for remove keyframes e.g.). */ + if (r_options) { + if (pyoptions && (pyrna_set_to_enum_bitfield( + rna_enum_keying_flag_items, pyoptions, r_options, error_prefix) == -1)) { + return -1; + } + + *r_options |= INSERTKEY_NO_USERPREF; + } + + return 0; /* success */ } char pyrna_struct_keyframe_insert_doc[] = -".. method:: keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, group=\"\")\n" -"\n" -" Insert a keyframe on the property given, adding fcurves and animation data when necessary.\n" -"\n" -" :arg data_path: path to the property to key, analogous to the fcurve's data path.\n" -" :type data_path: string\n" -" :arg index: array index of the property to key.\n" -" Defaults to -1 which will key all indices or a single channel if the property is not an array.\n" -" :type index: int\n" -" :arg frame: The frame on which the keyframe is inserted, defaulting to the current frame.\n" -" :type frame: float\n" -" :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n" -" :type group: str\n" -" :arg options: Optional flags:\n" -"\n" -" - ``INSERTKEY_NEEDED`` Only insert keyframes where they're needed in the relevant F-Curves.\n" -" - ``INSERTKEY_VISUAL`` Insert keyframes based on 'visual transforms'.\n" -" - ``INSERTKEY_XYZ_TO_RGB`` Color for newly added transformation F-Curves (Location, Rotation, Scale)\n" -" and also Color is based on the transform axis.\n" -" :type flag: set\n" -" :return: Success of keyframe insertion.\n" -" :rtype: boolean\n" -; + ".. method:: keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, " + "group=\"\")\n" + "\n" + " Insert a keyframe on the property given, adding fcurves and animation data when " + "necessary.\n" + "\n" + " :arg data_path: path to the property to key, analogous to the fcurve's data path.\n" + " :type data_path: string\n" + " :arg index: array index of the property to key.\n" + " Defaults to -1 which will key all indices or a single channel if the property is not " + "an array.\n" + " :type index: int\n" + " :arg frame: The frame on which the keyframe is inserted, defaulting to the current " + "frame.\n" + " :type frame: float\n" + " :arg group: The name of the group the F-Curve should be added to if it doesn't exist " + "yet.\n" + " :type group: str\n" + " :arg options: Optional flags:\n" + "\n" + " - ``INSERTKEY_NEEDED`` Only insert keyframes where they're needed in the relevant " + "F-Curves.\n" + " - ``INSERTKEY_VISUAL`` Insert keyframes based on 'visual transforms'.\n" + " - ``INSERTKEY_XYZ_TO_RGB`` Color for newly added transformation F-Curves (Location, " + "Rotation, Scale)\n" + " and also Color is based on the transform axis.\n" + " :type flag: set\n" + " :return: Success of keyframe insertion.\n" + " :rtype: boolean\n"; PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw) { - /* args, pyrna_struct_keyframe_parse handles these */ - const char *path_full = NULL; - int index = -1; - float cfra = FLT_MAX; - const char *group_name = NULL; - char keytype = BEZT_KEYTYPE_KEYFRAME; /* XXX: Expose this as a one-off option... */ - int options = 0; - - PYRNA_STRUCT_CHECK_OBJ(self); - - if (pyrna_struct_keyframe_parse( - &self->ptr, args, kw, - "s|ifsO!:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()", - &path_full, &index, &cfra, &group_name, &options) == -1) - { - return NULL; - } - else if (self->ptr.type == &RNA_NlaStrip) { - /* Handle special properties for NLA Strips, whose F-Curves are stored on the - * strips themselves. These are stored separately or else the properties will - * not have any effect. - */ - struct Depsgraph *depsgraph = CTX_data_depsgraph(BPy_GetContext()); - ReportList reports; - short result = 0; - - PointerRNA ptr = self->ptr; - PropertyRNA *prop = NULL; - const char *prop_name; - - BKE_reports_init(&reports, RPT_STORE); - - /* Retrieve the property identifier from the full path, since we can't get it any other way */ - prop_name = strrchr(path_full, '.'); - if ((prop_name >= path_full) && - (prop_name + 1 < path_full + strlen(path_full))) - { - prop = RNA_struct_find_property(&ptr, prop_name + 1); - } - - if (prop) { - NlaStrip *strip = (NlaStrip *)ptr.data; - FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index); - - result = insert_keyframe_direct(depsgraph, &reports, ptr, prop, fcu, cfra, keytype, NULL, options); - } - else { - BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full); - } - MEM_freeN((void *)path_full); - - if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { - return NULL; - } - - return PyBool_FromLong(result); - } - else { - ID *id = self->ptr.id.data; - struct Depsgraph *depsgraph = CTX_data_depsgraph(BPy_GetContext()); - ReportList reports; - short result; - - BKE_reports_init(&reports, RPT_STORE); - - BLI_assert(BKE_id_is_in_global_main(id)); - result = insert_keyframe(G_MAIN, depsgraph, &reports, id, NULL, group_name, path_full, index, cfra, keytype, NULL, options); - MEM_freeN((void *)path_full); - - if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { - return NULL; - } - - return PyBool_FromLong(result); - } + /* args, pyrna_struct_keyframe_parse handles these */ + const char *path_full = NULL; + int index = -1; + float cfra = FLT_MAX; + const char *group_name = NULL; + char keytype = BEZT_KEYTYPE_KEYFRAME; /* XXX: Expose this as a one-off option... */ + int options = 0; + + PYRNA_STRUCT_CHECK_OBJ(self); + + if (pyrna_struct_keyframe_parse(&self->ptr, + args, + kw, + "s|ifsO!:bpy_struct.keyframe_insert()", + "bpy_struct.keyframe_insert()", + &path_full, + &index, + &cfra, + &group_name, + &options) == -1) { + return NULL; + } + else if (self->ptr.type == &RNA_NlaStrip) { + /* Handle special properties for NLA Strips, whose F-Curves are stored on the + * strips themselves. These are stored separately or else the properties will + * not have any effect. + */ + struct Depsgraph *depsgraph = CTX_data_depsgraph(BPy_GetContext()); + ReportList reports; + short result = 0; + + PointerRNA ptr = self->ptr; + PropertyRNA *prop = NULL; + const char *prop_name; + + BKE_reports_init(&reports, RPT_STORE); + + /* Retrieve the property identifier from the full path, since we can't get it any other way */ + prop_name = strrchr(path_full, '.'); + if ((prop_name >= path_full) && (prop_name + 1 < path_full + strlen(path_full))) { + prop = RNA_struct_find_property(&ptr, prop_name + 1); + } + + if (prop) { + NlaStrip *strip = (NlaStrip *)ptr.data; + FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index); + + result = insert_keyframe_direct( + depsgraph, &reports, ptr, prop, fcu, cfra, keytype, NULL, options); + } + else { + BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full); + } + MEM_freeN((void *)path_full); + + if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { + return NULL; + } + + return PyBool_FromLong(result); + } + else { + ID *id = self->ptr.id.data; + struct Depsgraph *depsgraph = CTX_data_depsgraph(BPy_GetContext()); + ReportList reports; + short result; + + BKE_reports_init(&reports, RPT_STORE); + + BLI_assert(BKE_id_is_in_global_main(id)); + result = insert_keyframe(G_MAIN, + depsgraph, + &reports, + id, + NULL, + group_name, + path_full, + index, + cfra, + keytype, + NULL, + options); + MEM_freeN((void *)path_full); + + if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { + return NULL; + } + + return PyBool_FromLong(result); + } } char pyrna_struct_keyframe_delete_doc[] = -".. method:: keyframe_delete(data_path, index=-1, frame=bpy.context.scene.frame_current, group=\"\")\n" -"\n" -" Remove a keyframe from this properties fcurve.\n" -"\n" -" :arg data_path: path to the property to remove a key, analogous to the fcurve's data path.\n" -" :type data_path: string\n" -" :arg index: array index of the property to remove a key. Defaults to -1 removing all indices or a single channel if the property is not an array.\n" -" :type index: int\n" -" :arg frame: The frame on which the keyframe is deleted, defaulting to the current frame.\n" -" :type frame: float\n" -" :arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.\n" -" :type group: str\n" -" :return: Success of keyframe deleation.\n" -" :rtype: boolean\n" -; + ".. method:: keyframe_delete(data_path, index=-1, frame=bpy.context.scene.frame_current, " + "group=\"\")\n" + "\n" + " Remove a keyframe from this properties fcurve.\n" + "\n" + " :arg data_path: path to the property to remove a key, analogous to the fcurve's data " + "path.\n" + " :type data_path: string\n" + " :arg index: array index of the property to remove a key. Defaults to -1 removing all " + "indices or a single channel if the property is not an array.\n" + " :type index: int\n" + " :arg frame: The frame on which the keyframe is deleted, defaulting to the current frame.\n" + " :type frame: float\n" + " :arg group: The name of the group the F-Curve should be added to if it doesn't exist " + "yet.\n" + " :type group: str\n" + " :return: Success of keyframe deleation.\n" + " :rtype: boolean\n"; PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw) { - /* args, pyrna_struct_keyframe_parse handles these */ - const char *path_full = NULL; - int index = -1; - float cfra = FLT_MAX; - const char *group_name = NULL; - - PYRNA_STRUCT_CHECK_OBJ(self); - - if (pyrna_struct_keyframe_parse(&self->ptr, args, kw, - "s|ifsO!:bpy_struct.keyframe_delete()", - "bpy_struct.keyframe_insert()", - &path_full, &index, &cfra, &group_name, NULL) == -1) - { - return NULL; - } - else if (self->ptr.type == &RNA_NlaStrip) { - /* Handle special properties for NLA Strips, whose F-Curves are stored on the - * strips themselves. These are stored separately or else the properties will - * not have any effect. - */ - ReportList reports; - short result = 0; - - PointerRNA ptr = self->ptr; - PropertyRNA *prop = NULL; - const char *prop_name; - - BKE_reports_init(&reports, RPT_STORE); - - /* Retrieve the property identifier from the full path, since we can't get it any other way */ - prop_name = strrchr(path_full, '.'); - if ((prop_name >= path_full) && - (prop_name + 1 < path_full + strlen(path_full))) - { - prop = RNA_struct_find_property(&ptr, prop_name + 1); - } - - if (prop) { - ID *id = ptr.id.data; - NlaStrip *strip = (NlaStrip *)ptr.data; - FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index); - - BLI_assert(fcu != NULL); /* NOTE: This should be true, or else we wouldn't be able to get here */ - - if (BKE_fcurve_is_protected(fcu)) { - BKE_reportf(&reports, RPT_WARNING, - "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'", - strip->name, BKE_idcode_to_name(GS(id->name)), id->name + 2); - } - else { - /* remove the keyframe directly - * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve, - * and delete_keyframe() expects the FCurve to be part of an action - */ - bool found = false; - int i; - - /* try to find index of beztriple to get rid of */ - i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found); - if (found) { - /* delete the key at the index (will sanity check + do recalc afterwards) */ - delete_fcurve_key(fcu, i, 1); - result = true; - } - } - } - else { - BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full); - } - MEM_freeN((void *)path_full); - - if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { - return NULL; - } - - return PyBool_FromLong(result); - } - else { - short result; - ReportList reports; - - BKE_reports_init(&reports, RPT_STORE); - - result = delete_keyframe(G.main, &reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0); - MEM_freeN((void *)path_full); - - if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { - return NULL; - } - - return PyBool_FromLong(result); - } - + /* args, pyrna_struct_keyframe_parse handles these */ + const char *path_full = NULL; + int index = -1; + float cfra = FLT_MAX; + const char *group_name = NULL; + + PYRNA_STRUCT_CHECK_OBJ(self); + + if (pyrna_struct_keyframe_parse(&self->ptr, + args, + kw, + "s|ifsO!:bpy_struct.keyframe_delete()", + "bpy_struct.keyframe_insert()", + &path_full, + &index, + &cfra, + &group_name, + NULL) == -1) { + return NULL; + } + else if (self->ptr.type == &RNA_NlaStrip) { + /* Handle special properties for NLA Strips, whose F-Curves are stored on the + * strips themselves. These are stored separately or else the properties will + * not have any effect. + */ + ReportList reports; + short result = 0; + + PointerRNA ptr = self->ptr; + PropertyRNA *prop = NULL; + const char *prop_name; + + BKE_reports_init(&reports, RPT_STORE); + + /* Retrieve the property identifier from the full path, since we can't get it any other way */ + prop_name = strrchr(path_full, '.'); + if ((prop_name >= path_full) && (prop_name + 1 < path_full + strlen(path_full))) { + prop = RNA_struct_find_property(&ptr, prop_name + 1); + } + + if (prop) { + ID *id = ptr.id.data; + NlaStrip *strip = (NlaStrip *)ptr.data; + FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index); + + BLI_assert(fcu != + NULL); /* NOTE: This should be true, or else we wouldn't be able to get here */ + + if (BKE_fcurve_is_protected(fcu)) { + BKE_reportf( + &reports, + RPT_WARNING, + "Not deleting keyframe for locked F-Curve for NLA Strip influence on %s - %s '%s'", + strip->name, + BKE_idcode_to_name(GS(id->name)), + id->name + 2); + } + else { + /* remove the keyframe directly + * NOTE: cannot use delete_keyframe_fcurve(), as that will free the curve, + * and delete_keyframe() expects the FCurve to be part of an action + */ + bool found = false; + int i; + + /* try to find index of beztriple to get rid of */ + i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found); + if (found) { + /* delete the key at the index (will sanity check + do recalc afterwards) */ + delete_fcurve_key(fcu, i, 1); + result = true; + } + } + } + else { + BKE_reportf(&reports, RPT_ERROR, "Could not resolve path (%s)", path_full); + } + MEM_freeN((void *)path_full); + + if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { + return NULL; + } + + return PyBool_FromLong(result); + } + else { + short result; + ReportList reports; + + BKE_reports_init(&reports, RPT_STORE); + + result = delete_keyframe( + G.main, &reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0); + MEM_freeN((void *)path_full); + + if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { + return NULL; + } + + return PyBool_FromLong(result); + } } char pyrna_struct_driver_add_doc[] = -".. method:: driver_add(path, index=-1)\n" -"\n" -" Adds driver(s) to the given property\n" -"\n" -" :arg path: path to the property to drive, analogous to the fcurve's data path.\n" -" :type path: string\n" -" :arg index: array index of the property drive. Defaults to -1 for all indices or a single channel if the property is not an array.\n" -" :type index: int\n" -" :return: The driver(s) added.\n" -" :rtype: :class:`bpy.types.FCurve` or list if index is -1 with an array property.\n" -; + ".. method:: driver_add(path, index=-1)\n" + "\n" + " Adds driver(s) to the given property\n" + "\n" + " :arg path: path to the property to drive, analogous to the fcurve's data path.\n" + " :type path: string\n" + " :arg index: array index of the property drive. Defaults to -1 for all indices or a single " + "channel if the property is not an array.\n" + " :type index: int\n" + " :return: The driver(s) added.\n" + " :rtype: :class:`bpy.types.FCurve` or list if index is -1 with an array property.\n"; PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) { - const char *path, *path_full; - int index = -1; - - PYRNA_STRUCT_CHECK_OBJ(self); - - if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index)) { - return NULL; - } - - if (pyrna_struct_anim_args_parse( - &self->ptr, "bpy_struct.driver_add():", path, - &path_full, &index) == -1) - { - return NULL; - } - else { - PyObject *ret = NULL; - ReportList reports; - int result; - - BKE_reports_init(&reports, RPT_STORE); - - result = ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, - CREATEDRIVER_WITH_FMODIFIER, DRIVER_TYPE_PYTHON); - - if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { - return NULL; - } - - if (result) { - ID *id = self->ptr.id.data; - AnimData *adt = BKE_animdata_from_id(id); - FCurve *fcu; - - PointerRNA tptr; - - if (index == -1) { /* all, use a list */ - int i = 0; - ret = PyList_New(0); - while ((fcu = list_find_fcurve(&adt->drivers, path_full, i++))) { - RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); - PyList_APPEND(ret, pyrna_struct_CreatePyObject(&tptr)); - } - } - else { - fcu = list_find_fcurve(&adt->drivers, path_full, index); - RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); - ret = pyrna_struct_CreatePyObject(&tptr); - } - - WM_event_add_notifier(BPy_GetContext(), NC_ANIMATION | ND_FCURVES_ORDER, NULL); - } - else { - /* XXX, should be handled by reports, */ - PyErr_SetString(PyExc_TypeError, "bpy_struct.driver_add(): failed because of an internal error"); - return NULL; - } - - MEM_freeN((void *)path_full); - - return ret; - } + const char *path, *path_full; + int index = -1; + + PYRNA_STRUCT_CHECK_OBJ(self); + + if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index)) { + return NULL; + } + + if (pyrna_struct_anim_args_parse( + &self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) == -1) { + return NULL; + } + else { + PyObject *ret = NULL; + ReportList reports; + int result; + + BKE_reports_init(&reports, RPT_STORE); + + result = ANIM_add_driver(&reports, + (ID *)self->ptr.id.data, + path_full, + index, + CREATEDRIVER_WITH_FMODIFIER, + DRIVER_TYPE_PYTHON); + + if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { + return NULL; + } + + if (result) { + ID *id = self->ptr.id.data; + AnimData *adt = BKE_animdata_from_id(id); + FCurve *fcu; + + PointerRNA tptr; + + if (index == -1) { /* all, use a list */ + int i = 0; + ret = PyList_New(0); + while ((fcu = list_find_fcurve(&adt->drivers, path_full, i++))) { + RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); + PyList_APPEND(ret, pyrna_struct_CreatePyObject(&tptr)); + } + } + else { + fcu = list_find_fcurve(&adt->drivers, path_full, index); + RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); + ret = pyrna_struct_CreatePyObject(&tptr); + } + + WM_event_add_notifier(BPy_GetContext(), NC_ANIMATION | ND_FCURVES_ORDER, NULL); + } + else { + /* XXX, should be handled by reports, */ + PyErr_SetString(PyExc_TypeError, + "bpy_struct.driver_add(): failed because of an internal error"); + return NULL; + } + + MEM_freeN((void *)path_full); + + return ret; + } } - char pyrna_struct_driver_remove_doc[] = -".. method:: driver_remove(path, index=-1)\n" -"\n" -" Remove driver(s) from the given property\n" -"\n" -" :arg path: path to the property to drive, analogous to the fcurve's data path.\n" -" :type path: string\n" -" :arg index: array index of the property drive. Defaults to -1 for all indices or a single channel if the property is not an array.\n" -" :type index: int\n" -" :return: Success of driver removal.\n" -" :rtype: boolean\n" -; + ".. method:: driver_remove(path, index=-1)\n" + "\n" + " Remove driver(s) from the given property\n" + "\n" + " :arg path: path to the property to drive, analogous to the fcurve's data path.\n" + " :type path: string\n" + " :arg index: array index of the property drive. Defaults to -1 for all indices or a single " + "channel if the property is not an array.\n" + " :type index: int\n" + " :return: Success of driver removal.\n" + " :rtype: boolean\n"; PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args) { - const char *path, *path_full; - int index = -1; + const char *path, *path_full; + int index = -1; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index)) { + return NULL; + } - if (pyrna_struct_anim_args_parse_no_resolve_fallback( - &self->ptr, "bpy_struct.driver_remove():", path, - &path_full, &index) == -1) - { - return NULL; - } - else { - short result; - ReportList reports; + if (pyrna_struct_anim_args_parse_no_resolve_fallback( + &self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) == -1) { + return NULL; + } + else { + short result; + ReportList reports; - BKE_reports_init(&reports, RPT_STORE); + BKE_reports_init(&reports, RPT_STORE); - result = ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0); + result = ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0); - if (path != path_full) { - MEM_freeN((void *)path_full); - } + if (path != path_full) { + MEM_freeN((void *)path_full); + } - if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { - return NULL; - } + if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) { + return NULL; + } - WM_event_add_notifier(BPy_GetContext(), NC_ANIMATION | ND_FCURVES_ORDER, NULL); + WM_event_add_notifier(BPy_GetContext(), NC_ANIMATION | ND_FCURVES_ORDER, NULL); - return PyBool_FromLong(result); - } + return PyBool_FromLong(result); + } } diff --git a/source/blender/python/intern/bpy_rna_anim.h b/source/blender/python/intern/bpy_rna_anim.h index 5145d16eafb..7630c268bbe 100644 --- a/source/blender/python/intern/bpy_rna_anim.h +++ b/source/blender/python/intern/bpy_rna_anim.h @@ -31,4 +31,4 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args); PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args); -#endif /* __BPY_RNA_ANIM_H__ */ +#endif /* __BPY_RNA_ANIM_H__ */ diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index 4cc3c4c0fae..7097999201a 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -54,22 +54,22 @@ typedef void (*RNA_SetArrayFunc)(PointerRNA *, PropertyRNA *, const char *); typedef void (*RNA_SetIndexFunc)(PointerRNA *, PropertyRNA *, int index, void *); struct ItemConvertArgData { - union { - struct { - int range[2]; - } int_data; - struct { - float range[2]; - } float_data; - }; + union { + struct { + int range[2]; + } int_data; + struct { + float range[2]; + } float_data; + }; }; /** * Callback and args needed to apply the value (clamp range for now) */ typedef struct ItemConvert_FuncArg { - ItemConvertFunc func; - struct ItemConvertArgData arg; + ItemConvertFunc func; + struct ItemConvertArgData arg; } ItemConvert_FuncArg; /* @@ -87,655 +87,797 @@ typedef struct ItemConvert_FuncArg { /* arr[3] = x, self->arraydim is 0, lvalue_dim is 1 */ /* Ensures that a python sequence has expected number of items/sub-items and items are of desired type. */ -static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[], const bool is_dynamic, - ItemTypeCheckFunc check_item_type, const char *item_type_str, const char *error_prefix) +static int validate_array_type(PyObject *seq, + int dim, + int totdim, + int dimsize[], + const bool is_dynamic, + ItemTypeCheckFunc check_item_type, + const char *item_type_str, + const char *error_prefix) { - Py_ssize_t i; - - /* not the last dimension */ - if (dim + 1 < totdim) { - /* check that a sequence contains dimsize[dim] items */ - const int seq_size = PySequence_Size(seq); - if (seq_size == -1) { - PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'", - error_prefix, dim + 1, Py_TYPE(seq)->tp_name); - return -1; - } - for (i = 0; i < seq_size; i++) { - Py_ssize_t item_seq_size; - PyObject *item; - bool ok = true; - item = PySequence_GetItem(seq, i); - - if (item == NULL) { - PyErr_Format(PyExc_TypeError, "%s sequence type '%s' failed to retrieve index %d", - error_prefix, Py_TYPE(seq)->tp_name, i); - ok = 0; - } - else if ((item_seq_size = PySequence_Size(item)) == -1) { - /* BLI_snprintf(error_str, error_str_size, "expected a sequence of %s", item_type_str); */ - PyErr_Format(PyExc_TypeError, "%s expected a sequence of %s, not %s", - error_prefix, item_type_str, Py_TYPE(item)->tp_name); - ok = 0; - } - /* arr[3][4][5] - * dimsize[1] = 4 - * dimsize[2] = 5 - * - * dim = 0 */ - else if (item_seq_size != dimsize[dim + 1]) { - /* BLI_snprintf(error_str, error_str_size, - * "sequences of dimension %d should contain %d items", - * dim + 1, dimsize[dim + 1]); */ - PyErr_Format(PyExc_ValueError, "%s sequences of dimension %d should contain %d items, not %d", - error_prefix, dim + 1, dimsize[dim + 1], item_seq_size); - ok = 0; - } - else if (validate_array_type(item, dim + 1, totdim, dimsize, is_dynamic, - check_item_type, item_type_str, error_prefix) == -1) - { - ok = 0; - } - - Py_XDECREF(item); - - if (!ok) { - return -1; - } - } - } - else { - /* check that items are of correct type */ - const int seq_size = PySequence_Size(seq); - if (seq_size == -1) { - PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'", - error_prefix, dim + 1, Py_TYPE(seq)->tp_name); - return -1; - } - else if ((seq_size != dimsize[dim]) && (is_dynamic == false)) { - PyErr_Format(PyExc_ValueError, "%s sequences of dimension %d should contain %d items, not %d", - error_prefix, dim, dimsize[dim], seq_size); - return -1; - } - - for (i = 0; i < seq_size; i++) { - PyObject *item = PySequence_GetItem(seq, i); - - if (item == NULL) { - PyErr_Format(PyExc_TypeError, "%s sequence type '%s' failed to retrieve index %d", - error_prefix, Py_TYPE(seq)->tp_name, i); - return -1; - } - else if (!check_item_type(item)) { - Py_DECREF(item); - - /* BLI_snprintf(error_str, error_str_size, "sequence items should be of type %s", item_type_str); */ - PyErr_Format(PyExc_TypeError, "%s expected sequence items of type %s, not %s", - error_prefix, item_type_str, Py_TYPE(item)->tp_name); - return -1; - } - - Py_DECREF(item); - } - } - - return 0; /* ok */ + Py_ssize_t i; + + /* not the last dimension */ + if (dim + 1 < totdim) { + /* check that a sequence contains dimsize[dim] items */ + const int seq_size = PySequence_Size(seq); + if (seq_size == -1) { + PyErr_Format(PyExc_ValueError, + "%s sequence expected at dimension %d, not '%s'", + error_prefix, + dim + 1, + Py_TYPE(seq)->tp_name); + return -1; + } + for (i = 0; i < seq_size; i++) { + Py_ssize_t item_seq_size; + PyObject *item; + bool ok = true; + item = PySequence_GetItem(seq, i); + + if (item == NULL) { + PyErr_Format(PyExc_TypeError, + "%s sequence type '%s' failed to retrieve index %d", + error_prefix, + Py_TYPE(seq)->tp_name, + i); + ok = 0; + } + else if ((item_seq_size = PySequence_Size(item)) == -1) { + /* BLI_snprintf(error_str, error_str_size, "expected a sequence of %s", item_type_str); */ + PyErr_Format(PyExc_TypeError, + "%s expected a sequence of %s, not %s", + error_prefix, + item_type_str, + Py_TYPE(item)->tp_name); + ok = 0; + } + /* arr[3][4][5] + * dimsize[1] = 4 + * dimsize[2] = 5 + * + * dim = 0 */ + else if (item_seq_size != dimsize[dim + 1]) { + /* BLI_snprintf(error_str, error_str_size, + * "sequences of dimension %d should contain %d items", + * dim + 1, dimsize[dim + 1]); */ + PyErr_Format(PyExc_ValueError, + "%s sequences of dimension %d should contain %d items, not %d", + error_prefix, + dim + 1, + dimsize[dim + 1], + item_seq_size); + ok = 0; + } + else if (validate_array_type(item, + dim + 1, + totdim, + dimsize, + is_dynamic, + check_item_type, + item_type_str, + error_prefix) == -1) { + ok = 0; + } + + Py_XDECREF(item); + + if (!ok) { + return -1; + } + } + } + else { + /* check that items are of correct type */ + const int seq_size = PySequence_Size(seq); + if (seq_size == -1) { + PyErr_Format(PyExc_ValueError, + "%s sequence expected at dimension %d, not '%s'", + error_prefix, + dim + 1, + Py_TYPE(seq)->tp_name); + return -1; + } + else if ((seq_size != dimsize[dim]) && (is_dynamic == false)) { + PyErr_Format(PyExc_ValueError, + "%s sequences of dimension %d should contain %d items, not %d", + error_prefix, + dim, + dimsize[dim], + seq_size); + return -1; + } + + for (i = 0; i < seq_size; i++) { + PyObject *item = PySequence_GetItem(seq, i); + + if (item == NULL) { + PyErr_Format(PyExc_TypeError, + "%s sequence type '%s' failed to retrieve index %d", + error_prefix, + Py_TYPE(seq)->tp_name, + i); + return -1; + } + else if (!check_item_type(item)) { + Py_DECREF(item); + + /* BLI_snprintf(error_str, error_str_size, "sequence items should be of type %s", item_type_str); */ + PyErr_Format(PyExc_TypeError, + "%s expected sequence items of type %s, not %s", + error_prefix, + item_type_str, + Py_TYPE(item)->tp_name); + return -1; + } + + Py_DECREF(item); + } + } + + return 0; /* ok */ } /* Returns the number of items in a single- or multi-dimensional sequence. */ static int count_items(PyObject *seq, int dim) { - int totitem = 0; - - if (dim > 1) { - const Py_ssize_t seq_size = PySequence_Size(seq); - Py_ssize_t i; - for (i = 0; i < seq_size; i++) { - PyObject *item = PySequence_GetItem(seq, i); - if (item) { - const int tot = count_items(item, dim - 1); - Py_DECREF(item); - if (tot != -1) { - totitem += tot; - } - else { - totitem = -1; - break; - } - } - else { - totitem = -1; - break; - } - } - } - else { - totitem = PySequence_Size(seq); - } - - return totitem; + int totitem = 0; + + if (dim > 1) { + const Py_ssize_t seq_size = PySequence_Size(seq); + Py_ssize_t i; + for (i = 0; i < seq_size; i++) { + PyObject *item = PySequence_GetItem(seq, i); + if (item) { + const int tot = count_items(item, dim - 1); + Py_DECREF(item); + if (tot != -1) { + totitem += tot; + } + else { + totitem = -1; + break; + } + } + else { + totitem = -1; + break; + } + } + } + else { + totitem = PySequence_Size(seq); + } + + return totitem; } /* Modifies property array length if needed and PROP_DYNAMIC flag is set. */ -static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, - int lvalue_dim, int *totitem, const char *error_prefix) +static int validate_array_length(PyObject *rvalue, + PointerRNA *ptr, + PropertyRNA *prop, + int lvalue_dim, + int *totitem, + const char *error_prefix) { - int dimsize[MAX_ARRAY_DIMENSION]; - int tot, totdim, len; - - totdim = RNA_property_array_dimension(ptr, prop, dimsize); - tot = count_items(rvalue, totdim - lvalue_dim); - - if (tot == -1) { - PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, error validating the sequence length", - error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop)); - return -1; - } - else if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) { - if (RNA_property_array_length(ptr, prop) != tot) { + int dimsize[MAX_ARRAY_DIMENSION]; + int tot, totdim, len; + + totdim = RNA_property_array_dimension(ptr, prop, dimsize); + tot = count_items(rvalue, totdim - lvalue_dim); + + if (tot == -1) { + PyErr_Format(PyExc_ValueError, + "%s %.200s.%.200s, error validating the sequence length", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + return -1; + } + else if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) { + if (RNA_property_array_length(ptr, prop) != tot) { #if 0 - /* length is flexible */ - if (!RNA_property_dynamic_array_set_length(ptr, prop, tot)) { - /* BLI_snprintf(error_str, error_str_size, - * "%s.%s: array length cannot be changed to %d", - * RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); */ - PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d", - error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); - return -1; - } + /* length is flexible */ + if (!RNA_property_dynamic_array_set_length(ptr, prop, tot)) { + /* BLI_snprintf(error_str, error_str_size, + * "%s.%s: array length cannot be changed to %d", + * RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); */ + PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d", + error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); + return -1; + } #else - *totitem = tot; - return 0; + *totitem = tot; + return 0; #endif - } - - len = tot; - } - else { - /* length is a constraint */ - if (!lvalue_dim) { - len = RNA_property_array_length(ptr, prop); - } - /* array item assignment */ - else { - int i; - - len = 1; - - /* arr[3][4][5] - * - * arr[2] = x - * dimsize = {4, 5} - * dimsize[1] = 4 - * dimsize[2] = 5 - * lvalue_dim = 0, totdim = 3 - * - * arr[2][3] = x - * lvalue_dim = 1 - * - * arr[2][3][4] = x - * lvalue_dim = 2 */ - for (i = lvalue_dim; i < totdim; i++) { - len *= dimsize[i]; - } - } - - if (tot != len) { - /* BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len); */ - PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, sequence must have %d items total, not %d", - error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), len, tot); - return -1; - } - } - - *totitem = len; - - return 0; + } + + len = tot; + } + else { + /* length is a constraint */ + if (!lvalue_dim) { + len = RNA_property_array_length(ptr, prop); + } + /* array item assignment */ + else { + int i; + + len = 1; + + /* arr[3][4][5] + * + * arr[2] = x + * dimsize = {4, 5} + * dimsize[1] = 4 + * dimsize[2] = 5 + * lvalue_dim = 0, totdim = 3 + * + * arr[2][3] = x + * lvalue_dim = 1 + * + * arr[2][3][4] = x + * lvalue_dim = 2 */ + for (i = lvalue_dim; i < totdim; i++) { + len *= dimsize[i]; + } + } + + if (tot != len) { + /* BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len); */ + PyErr_Format(PyExc_ValueError, + "%s %.200s.%.200s, sequence must have %d items total, not %d", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + len, + tot); + return -1; + } + } + + *totitem = len; + + return 0; } -static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, - int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, int *totitem, +static int validate_array(PyObject *rvalue, + PointerRNA *ptr, + PropertyRNA *prop, + int lvalue_dim, + ItemTypeCheckFunc check_item_type, + const char *item_type_str, + int *totitem, const char *error_prefix) { - int dimsize[MAX_ARRAY_DIMENSION]; - int totdim = RNA_property_array_dimension(ptr, prop, dimsize); - - /* validate type first because length validation may modify property array length */ + int dimsize[MAX_ARRAY_DIMENSION]; + int totdim = RNA_property_array_dimension(ptr, prop, dimsize); + /* validate type first because length validation may modify property array length */ #ifdef USE_MATHUTILS - if (lvalue_dim == 0) { /* only valid for first level array */ - if (MatrixObject_Check(rvalue)) { - MatrixObject *pymat = (MatrixObject *)rvalue; - - if (BaseMath_ReadCallback(pymat) == -1) { - return -1; - } - - if (RNA_property_type(prop) != PROP_FLOAT) { - PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, matrix assign to non float array", - error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop)); - return -1; - } - else if (totdim != 2) { - PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, matrix assign array with %d dimensions", - error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), totdim); - return -1; - } - else if (pymat->num_col != dimsize[0] || pymat->num_row != dimsize[1]) { - PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, matrix assign dimension size mismatch, " - "is %dx%d, expected be %dx%d", - error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), - pymat->num_col, pymat->num_row, dimsize[0], dimsize[1]); - return -1; - } - else { - *totitem = dimsize[0] * dimsize[1]; - return 0; - } - } - } + if (lvalue_dim == 0) { /* only valid for first level array */ + if (MatrixObject_Check(rvalue)) { + MatrixObject *pymat = (MatrixObject *)rvalue; + + if (BaseMath_ReadCallback(pymat) == -1) { + return -1; + } + + if (RNA_property_type(prop) != PROP_FLOAT) { + PyErr_Format(PyExc_ValueError, + "%s %.200s.%.200s, matrix assign to non float array", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + return -1; + } + else if (totdim != 2) { + PyErr_Format(PyExc_ValueError, + "%s %.200s.%.200s, matrix assign array with %d dimensions", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + totdim); + return -1; + } + else if (pymat->num_col != dimsize[0] || pymat->num_row != dimsize[1]) { + PyErr_Format(PyExc_ValueError, + "%s %.200s.%.200s, matrix assign dimension size mismatch, " + "is %dx%d, expected be %dx%d", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + pymat->num_col, + pymat->num_row, + dimsize[0], + dimsize[1]); + return -1; + } + else { + *totitem = dimsize[0] * dimsize[1]; + return 0; + } + } + } #endif /* USE_MATHUTILS */ - - { - const int prop_flag = RNA_property_flag(prop); - if (validate_array_type(rvalue, lvalue_dim, totdim, dimsize, (prop_flag & PROP_DYNAMIC) != 0, - check_item_type, item_type_str, error_prefix) == -1) - { - return -1; - } - - return validate_array_length(rvalue, ptr, prop, lvalue_dim, totitem, error_prefix); - } + { + const int prop_flag = RNA_property_flag(prop); + if (validate_array_type(rvalue, + lvalue_dim, + totdim, + dimsize, + (prop_flag & PROP_DYNAMIC) != 0, + check_item_type, + item_type_str, + error_prefix) == -1) { + return -1; + } + + return validate_array_length(rvalue, ptr, prop, lvalue_dim, totitem, error_prefix); + } } -static char *copy_value_single( - PyObject *item, PointerRNA *ptr, PropertyRNA *prop, - char *data, unsigned int item_size, int *index, - const ItemConvert_FuncArg *convert_item, RNA_SetIndexFunc rna_set_index) +static char *copy_value_single(PyObject *item, + PointerRNA *ptr, + PropertyRNA *prop, + char *data, + unsigned int item_size, + int *index, + const ItemConvert_FuncArg *convert_item, + RNA_SetIndexFunc rna_set_index) { - if (!data) { - union { float fl; int i; } value_buf; - char *value = (void *)&value_buf; - - convert_item->func(&convert_item->arg, item, value); - rna_set_index(ptr, prop, *index, value); - (*index) += 1; - } - else { - convert_item->func(&convert_item->arg, item, data); - data += item_size; - } - - return data; + if (!data) { + union { + float fl; + int i; + } value_buf; + char *value = (void *)&value_buf; + + convert_item->func(&convert_item->arg, item, value); + rna_set_index(ptr, prop, *index, value); + (*index) += 1; + } + else { + convert_item->func(&convert_item->arg, item, data); + data += item_size; + } + + return data; } -static char *copy_values( - PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, - int dim, char *data, unsigned int item_size, int *index, - const ItemConvert_FuncArg *convert_item, RNA_SetIndexFunc rna_set_index) +static char *copy_values(PyObject *seq, + PointerRNA *ptr, + PropertyRNA *prop, + int dim, + char *data, + unsigned int item_size, + int *index, + const ItemConvert_FuncArg *convert_item, + RNA_SetIndexFunc rna_set_index) { - int totdim = RNA_property_array_dimension(ptr, prop, NULL); - const Py_ssize_t seq_size = PySequence_Size(seq); - Py_ssize_t i; - - /* Regarding PySequence_GetItem() failing. - * - * This should never be NULL since we validated it, _but_ some tricky python - * developer could write their own sequence type which succeeds on - * validating but fails later somehow, so include checks for safety. - */ + int totdim = RNA_property_array_dimension(ptr, prop, NULL); + const Py_ssize_t seq_size = PySequence_Size(seq); + Py_ssize_t i; - /* Note that 'data can be NULL' */ + /* Regarding PySequence_GetItem() failing. + * + * This should never be NULL since we validated it, _but_ some tricky python + * developer could write their own sequence type which succeeds on + * validating but fails later somehow, so include checks for safety. + */ - if (seq_size == -1) { - return NULL; - } + /* Note that 'data can be NULL' */ + if (seq_size == -1) { + return NULL; + } #ifdef USE_MATHUTILS - if (dim == 0) { - if (MatrixObject_Check(seq)) { - MatrixObject *pymat = (MatrixObject *)seq; - size_t allocsize = pymat->num_col * pymat->num_row * sizeof(float); + if (dim == 0) { + if (MatrixObject_Check(seq)) { + MatrixObject *pymat = (MatrixObject *)seq; + size_t allocsize = pymat->num_col * pymat->num_row * sizeof(float); - /* read callback already done by validate */ - /* since this is the first iteration we can assume data is allocated */ - memcpy(data, pymat->matrix, allocsize); + /* read callback already done by validate */ + /* since this is the first iteration we can assume data is allocated */ + memcpy(data, pymat->matrix, allocsize); - /* not really needed but do for completeness */ - data += allocsize; + /* not really needed but do for completeness */ + data += allocsize; - return data; - } - } + return data; + } + } #endif /* USE_MATHUTILS */ - - for (i = 0; i < seq_size; i++) { - PyObject *item = PySequence_GetItem(seq, i); - if (item) { - if (dim + 1 < totdim) { - data = copy_values(item, ptr, prop, dim + 1, data, item_size, index, convert_item, rna_set_index); - } - else { - data = copy_value_single(item, ptr, prop, data, item_size, index, convert_item, rna_set_index); - } - - Py_DECREF(item); - - /* data may be NULL, but the for loop checks */ - } - else { - return NULL; - } - } - - return data; + for (i = 0; i < seq_size; i++) { + PyObject *item = PySequence_GetItem(seq, i); + if (item) { + if (dim + 1 < totdim) { + data = copy_values( + item, ptr, prop, dim + 1, data, item_size, index, convert_item, rna_set_index); + } + else { + data = copy_value_single( + item, ptr, prop, data, item_size, index, convert_item, rna_set_index); + } + + Py_DECREF(item); + + /* data may be NULL, but the for loop checks */ + } + else { + return NULL; + } + } + + return data; } -static int py_to_array( - PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, - char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, - const ItemConvert_FuncArg *convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix) +static int py_to_array(PyObject *seq, + PointerRNA *ptr, + PropertyRNA *prop, + char *param_data, + ItemTypeCheckFunc check_item_type, + const char *item_type_str, + int item_size, + const ItemConvert_FuncArg *convert_item, + RNA_SetArrayFunc rna_set_array, + const char *error_prefix) { - /*int totdim, dim_size[MAX_ARRAY_DIMENSION];*/ - int totitem; - char *data = NULL; - - /*totdim = RNA_property_array_dimension(ptr, prop, dim_size);*/ /*UNUSED*/ - - if (validate_array(seq, ptr, prop, 0, check_item_type, item_type_str, &totitem, error_prefix) == -1) { - return -1; - } - - if (totitem) { - /* note: this code is confusing */ - if (param_data && RNA_property_flag(prop) & PROP_DYNAMIC) { - /* not freeing allocated mem, RNA_parameter_list_free() will do this */ - ParameterDynAlloc *param_alloc = (ParameterDynAlloc *)param_data; - param_alloc->array_tot = (int)totitem; - param_alloc->array = MEM_callocN(item_size * totitem, "py_to_array dyn"); /* freeing param list will free */ - - data = param_alloc->array; - } - else if (param_data) { - data = param_data; - } - else { - data = PyMem_MALLOC(item_size * totitem); - } - - /* will only fail in very rare cases since we already validated the - * python data, the check here is mainly for completeness. */ - if (copy_values(seq, ptr, prop, 0, data, item_size, NULL, convert_item, NULL) != NULL) { - if (param_data == NULL) { - /* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */ - rna_set_array(ptr, prop, data); - PyMem_FREE(data); - } - } - else { - if (param_data == NULL) { - PyMem_FREE(data); - } - - PyErr_Format(PyExc_TypeError, "%s internal error parsing sequence of type '%s' after successful validation", - error_prefix, Py_TYPE(seq)->tp_name); - return -1; - } - } - - return 0; + /*int totdim, dim_size[MAX_ARRAY_DIMENSION];*/ + int totitem; + char *data = NULL; + + /*totdim = RNA_property_array_dimension(ptr, prop, dim_size);*/ /*UNUSED*/ + + if (validate_array(seq, ptr, prop, 0, check_item_type, item_type_str, &totitem, error_prefix) == + -1) { + return -1; + } + + if (totitem) { + /* note: this code is confusing */ + if (param_data && RNA_property_flag(prop) & PROP_DYNAMIC) { + /* not freeing allocated mem, RNA_parameter_list_free() will do this */ + ParameterDynAlloc *param_alloc = (ParameterDynAlloc *)param_data; + param_alloc->array_tot = (int)totitem; + param_alloc->array = MEM_callocN(item_size * totitem, + "py_to_array dyn"); /* freeing param list will free */ + + data = param_alloc->array; + } + else if (param_data) { + data = param_data; + } + else { + data = PyMem_MALLOC(item_size * totitem); + } + + /* will only fail in very rare cases since we already validated the + * python data, the check here is mainly for completeness. */ + if (copy_values(seq, ptr, prop, 0, data, item_size, NULL, convert_item, NULL) != NULL) { + if (param_data == NULL) { + /* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */ + rna_set_array(ptr, prop, data); + PyMem_FREE(data); + } + } + else { + if (param_data == NULL) { + PyMem_FREE(data); + } + + PyErr_Format(PyExc_TypeError, + "%s internal error parsing sequence of type '%s' after successful validation", + error_prefix, + Py_TYPE(seq)->tp_name); + return -1; + } + } + + return 0; } -static int py_to_array_index( - PyObject *py, PointerRNA *ptr, PropertyRNA *prop, - int lvalue_dim, int arrayoffset, int index, - ItemTypeCheckFunc check_item_type, const char *item_type_str, - const ItemConvert_FuncArg *convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix) +static int py_to_array_index(PyObject *py, + PointerRNA *ptr, + PropertyRNA *prop, + int lvalue_dim, + int arrayoffset, + int index, + ItemTypeCheckFunc check_item_type, + const char *item_type_str, + const ItemConvert_FuncArg *convert_item, + RNA_SetIndexFunc rna_set_index, + const char *error_prefix) { - int totdim, dimsize[MAX_ARRAY_DIMENSION]; - int totitem, i; - - totdim = RNA_property_array_dimension(ptr, prop, dimsize); - - /* convert index */ - - /* arr[3][4][5] - * - * arr[2] = x - * lvalue_dim = 0, index = 0 + 2 * 4 * 5 - * - * arr[2][3] = x - * lvalue_dim = 1, index = 40 + 3 * 5 */ - - lvalue_dim++; - - for (i = lvalue_dim; i < totdim; i++) { - index *= dimsize[i]; - } - - index += arrayoffset; - - if (lvalue_dim == totdim) { /* single item, assign directly */ - if (!check_item_type(py)) { - PyErr_Format(PyExc_TypeError, "%s %.200s.%.200s, expected a %s type, not %s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), item_type_str, - Py_TYPE(py)->tp_name); - return -1; - } - copy_value_single(py, ptr, prop, NULL, 0, &index, convert_item, rna_set_index); - } - else { - if (validate_array(py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix) == -1) { - return -1; - } - - if (totitem) { - copy_values(py, ptr, prop, lvalue_dim, NULL, 0, &index, convert_item, rna_set_index); - } - } - return 0; + int totdim, dimsize[MAX_ARRAY_DIMENSION]; + int totitem, i; + + totdim = RNA_property_array_dimension(ptr, prop, dimsize); + + /* convert index */ + + /* arr[3][4][5] + * + * arr[2] = x + * lvalue_dim = 0, index = 0 + 2 * 4 * 5 + * + * arr[2][3] = x + * lvalue_dim = 1, index = 40 + 3 * 5 */ + + lvalue_dim++; + + for (i = lvalue_dim; i < totdim; i++) { + index *= dimsize[i]; + } + + index += arrayoffset; + + if (lvalue_dim == totdim) { /* single item, assign directly */ + if (!check_item_type(py)) { + PyErr_Format(PyExc_TypeError, + "%s %.200s.%.200s, expected a %s type, not %s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + item_type_str, + Py_TYPE(py)->tp_name); + return -1; + } + copy_value_single(py, ptr, prop, NULL, 0, &index, convert_item, rna_set_index); + } + else { + if (validate_array( + py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix) == + -1) { + return -1; + } + + if (totitem) { + copy_values(py, ptr, prop, lvalue_dim, NULL, 0, &index, convert_item, rna_set_index); + } + } + return 0; } static void py_to_float(const struct ItemConvertArgData *arg, PyObject *py, char *data) { - const float *range = arg->float_data.range; - float value = (float)PyFloat_AsDouble(py); - CLAMP(value, range[0], range[1]); - *(float *)data = value; + const float *range = arg->float_data.range; + float value = (float)PyFloat_AsDouble(py); + CLAMP(value, range[0], range[1]); + *(float *)data = value; } static void py_to_int(const struct ItemConvertArgData *arg, PyObject *py, char *data) { - const int *range = arg->int_data.range; - int value = PyC_Long_AsI32(py); - CLAMP(value, range[0], range[1]); - *(int *)data = value; + const int *range = arg->int_data.range; + int value = PyC_Long_AsI32(py); + CLAMP(value, range[0], range[1]); + *(int *)data = value; } static void py_to_bool(const struct ItemConvertArgData *UNUSED(arg), PyObject *py, char *data) { - *(bool *)data = (bool)PyObject_IsTrue(py); + *(bool *)data = (bool)PyObject_IsTrue(py); } static int py_float_check(PyObject *py) { - /* accept both floats and integers */ - return PyNumber_Check(py); + /* accept both floats and integers */ + return PyNumber_Check(py); } static int py_int_check(PyObject *py) { - /* accept only integers */ - return PyLong_Check(py); + /* accept only integers */ + return PyLong_Check(py); } static int py_bool_check(PyObject *py) { - return PyBool_Check(py); + return PyBool_Check(py); } static void float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value) { - RNA_property_float_set_index(ptr, prop, index, *(float *)value); + RNA_property_float_set_index(ptr, prop, index, *(float *)value); } static void int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value) { - RNA_property_int_set_index(ptr, prop, index, *(int *)value); + RNA_property_int_set_index(ptr, prop, index, *(int *)value); } static void bool_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, void *value) { - RNA_property_boolean_set_index(ptr, prop, index, *(bool *)value); + RNA_property_boolean_set_index(ptr, prop, index, *(bool *)value); } -static void convert_item_init_float( - PointerRNA *ptr, PropertyRNA *prop, - ItemConvert_FuncArg *convert_item) +static void convert_item_init_float(PointerRNA *ptr, + PropertyRNA *prop, + ItemConvert_FuncArg *convert_item) { - float *range = convert_item->arg.float_data.range; - convert_item->func = py_to_float; - RNA_property_float_range(ptr, prop, &range[0], &range[1]); + float *range = convert_item->arg.float_data.range; + convert_item->func = py_to_float; + RNA_property_float_range(ptr, prop, &range[0], &range[1]); } -static void convert_item_init_int( - PointerRNA *ptr, PropertyRNA *prop, - ItemConvert_FuncArg *convert_item) +static void convert_item_init_int(PointerRNA *ptr, + PropertyRNA *prop, + ItemConvert_FuncArg *convert_item) { - int *range = convert_item->arg.int_data.range; - convert_item->func = py_to_int; - RNA_property_int_range(ptr, prop, &range[0], &range[1]); + int *range = convert_item->arg.int_data.range; + convert_item->func = py_to_int; + RNA_property_int_range(ptr, prop, &range[0], &range[1]); } -static void convert_item_init_bool( - PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), - ItemConvert_FuncArg *convert_item) +static void convert_item_init_bool(PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + ItemConvert_FuncArg *convert_item) { - convert_item->func = py_to_bool; + convert_item->func = py_to_bool; } -int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, - PyObject *py, const char *error_prefix) +int pyrna_py_to_array( + PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyObject *py, const char *error_prefix) { - int ret; - switch (RNA_property_type(prop)) { - case PROP_FLOAT: - { - ItemConvert_FuncArg convert_item; - convert_item_init_float(ptr, prop, &convert_item); - - ret = py_to_array( - py, ptr, prop, param_data, py_float_check, "float", sizeof(float), - &convert_item, (RNA_SetArrayFunc)RNA_property_float_set_array, error_prefix); - break; - } - case PROP_INT: - { - ItemConvert_FuncArg convert_item; - convert_item_init_int(ptr, prop, &convert_item); - - ret = py_to_array( - py, ptr, prop, param_data, py_int_check, "int", sizeof(int), - &convert_item, (RNA_SetArrayFunc)RNA_property_int_set_array, error_prefix); - break; - } - case PROP_BOOLEAN: - { - ItemConvert_FuncArg convert_item; - convert_item_init_bool(ptr, prop, &convert_item); - - ret = py_to_array( - py, ptr, prop, param_data, py_bool_check, "boolean", sizeof(bool), - &convert_item, (RNA_SetArrayFunc)RNA_property_boolean_set_array, error_prefix); - break; - } - default: - { - PyErr_SetString(PyExc_TypeError, "not an array type"); - ret = -1; - break; - } - } - - return ret; + int ret; + switch (RNA_property_type(prop)) { + case PROP_FLOAT: { + ItemConvert_FuncArg convert_item; + convert_item_init_float(ptr, prop, &convert_item); + + ret = py_to_array(py, + ptr, + prop, + param_data, + py_float_check, + "float", + sizeof(float), + &convert_item, + (RNA_SetArrayFunc)RNA_property_float_set_array, + error_prefix); + break; + } + case PROP_INT: { + ItemConvert_FuncArg convert_item; + convert_item_init_int(ptr, prop, &convert_item); + + ret = py_to_array(py, + ptr, + prop, + param_data, + py_int_check, + "int", + sizeof(int), + &convert_item, + (RNA_SetArrayFunc)RNA_property_int_set_array, + error_prefix); + break; + } + case PROP_BOOLEAN: { + ItemConvert_FuncArg convert_item; + convert_item_init_bool(ptr, prop, &convert_item); + + ret = py_to_array(py, + ptr, + prop, + param_data, + py_bool_check, + "boolean", + sizeof(bool), + &convert_item, + (RNA_SetArrayFunc)RNA_property_boolean_set_array, + error_prefix); + break; + } + default: { + PyErr_SetString(PyExc_TypeError, "not an array type"); + ret = -1; + break; + } + } + + return ret; } -int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, int index, - PyObject *py, const char *error_prefix) +int pyrna_py_to_array_index(PointerRNA *ptr, + PropertyRNA *prop, + int arraydim, + int arrayoffset, + int index, + PyObject *py, + const char *error_prefix) { - int ret; - switch (RNA_property_type(prop)) { - case PROP_FLOAT: - { - ItemConvert_FuncArg convert_item; - convert_item_init_float(ptr, prop, &convert_item); - - ret = py_to_array_index( - py, ptr, prop, arraydim, arrayoffset, index, - py_float_check, "float", - &convert_item, float_set_index, error_prefix); - break; - } - case PROP_INT: - { - ItemConvert_FuncArg convert_item; - convert_item_init_int(ptr, prop, &convert_item); - - ret = py_to_array_index( - py, ptr, prop, arraydim, arrayoffset, index, - py_int_check, "int", - &convert_item, int_set_index, error_prefix); - break; - } - case PROP_BOOLEAN: - { - ItemConvert_FuncArg convert_item; - convert_item_init_bool(ptr, prop, &convert_item); - - ret = py_to_array_index( - py, ptr, prop, arraydim, arrayoffset, index, - py_bool_check, "boolean", - &convert_item, bool_set_index, error_prefix); - break; - } - default: - { - PyErr_SetString(PyExc_TypeError, "not an array type"); - ret = -1; - break; - } - } - - return ret; + int ret; + switch (RNA_property_type(prop)) { + case PROP_FLOAT: { + ItemConvert_FuncArg convert_item; + convert_item_init_float(ptr, prop, &convert_item); + + ret = py_to_array_index(py, + ptr, + prop, + arraydim, + arrayoffset, + index, + py_float_check, + "float", + &convert_item, + float_set_index, + error_prefix); + break; + } + case PROP_INT: { + ItemConvert_FuncArg convert_item; + convert_item_init_int(ptr, prop, &convert_item); + + ret = py_to_array_index(py, + ptr, + prop, + arraydim, + arrayoffset, + index, + py_int_check, + "int", + &convert_item, + int_set_index, + error_prefix); + break; + } + case PROP_BOOLEAN: { + ItemConvert_FuncArg convert_item; + convert_item_init_bool(ptr, prop, &convert_item); + + ret = py_to_array_index(py, + ptr, + prop, + arraydim, + arrayoffset, + index, + py_bool_check, + "boolean", + &convert_item, + bool_set_index, + error_prefix); + break; + } + default: { + PyErr_SetString(PyExc_TypeError, "not an array type"); + ret = -1; + break; + } + } + + return ret; } PyObject *pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index) { - PyObject *item; - - switch (RNA_property_type(prop)) { - case PROP_FLOAT: - item = PyFloat_FromDouble(RNA_property_float_get_index(ptr, prop, index)); - break; - case PROP_BOOLEAN: - item = PyBool_FromLong(RNA_property_boolean_get_index(ptr, prop, index)); - break; - case PROP_INT: - item = PyLong_FromLong(RNA_property_int_get_index(ptr, prop, index)); - break; - default: - PyErr_SetString(PyExc_TypeError, "not an array type"); - item = NULL; - break; - } - - return item; + PyObject *item; + + switch (RNA_property_type(prop)) { + case PROP_FLOAT: + item = PyFloat_FromDouble(RNA_property_float_get_index(ptr, prop, index)); + break; + case PROP_BOOLEAN: + item = PyBool_FromLong(RNA_property_boolean_get_index(ptr, prop, index)); + break; + case PROP_INT: + item = PyLong_FromLong(RNA_property_int_get_index(ptr, prop, index)); + break; + default: + PyErr_SetString(PyExc_TypeError, "not an array type"); + item = NULL; + break; + } + + return item; } #if 0 @@ -743,222 +885,222 @@ PyObject *pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index) /* Given an array property, creates an N-dimensional tuple of values. */ static PyObject *pyrna_py_from_array_internal(PointerRNA *ptr, PropertyRNA *prop, int dim, int *index) { - PyObject *tuple; - int i, len; - int totdim = RNA_property_array_dimension(ptr, prop, NULL); + PyObject *tuple; + int i, len; + int totdim = RNA_property_array_dimension(ptr, prop, NULL); - len = RNA_property_multi_array_length(ptr, prop, dim); + len = RNA_property_multi_array_length(ptr, prop, dim); - tuple = PyTuple_New(len); + tuple = PyTuple_New(len); - for (i = 0; i < len; i++) { - PyObject *item; + for (i = 0; i < len; i++) { + PyObject *item; - if (dim + 1 < totdim) { - item = pyrna_py_from_array_internal(ptr, prop, dim + 1, index); - } - else { - item = pyrna_array_index(ptr, prop, *index); - *index = *index + 1; - } + if (dim + 1 < totdim) { + item = pyrna_py_from_array_internal(ptr, prop, dim + 1, index); + } + else { + item = pyrna_array_index(ptr, prop, *index); + *index = *index + 1; + } - if (!item) { - Py_DECREF(tuple); - return NULL; - } + if (!item) { + Py_DECREF(tuple); + return NULL; + } - PyTuple_SET_ITEM(tuple, i, item); - } + PyTuple_SET_ITEM(tuple, i, item); + } - return tuple; + return tuple; } #endif -PyObject *pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, int index) +PyObject *pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, + PointerRNA *ptr, + PropertyRNA *prop, + int index) { - int totdim, arraydim, arrayoffset, dimsize[MAX_ARRAY_DIMENSION], i, len; - BPy_PropertyArrayRNA *ret = NULL; - - arraydim = self ? self->arraydim : 0; - arrayoffset = self ? self->arrayoffset : 0; - - /* just in case check */ - len = RNA_property_multi_array_length(ptr, prop, arraydim); - if (index >= len || index < 0) { - /* this shouldn't happen because higher level funcs must check for invalid index */ - CLOG_WARN(BPY_LOG_RNA, "invalid index %d for array with length=%d", index, len); - - PyErr_SetString(PyExc_IndexError, "out of range"); - return NULL; - } - - totdim = RNA_property_array_dimension(ptr, prop, dimsize); - - if (arraydim + 1 < totdim) { - ret = (BPy_PropertyArrayRNA *)pyrna_prop_CreatePyObject(ptr, prop); - ret->arraydim = arraydim + 1; - - /* arr[3][4][5] - * - * x = arr[2] - * index = 0 + 2 * 4 * 5 - * - * x = arr[2][3] - * index = offset + 3 * 5 */ - - for (i = arraydim + 1; i < totdim; i++) { - index *= dimsize[i]; - } - - ret->arrayoffset = arrayoffset + index; - } - else { - index = arrayoffset + index; - ret = (BPy_PropertyArrayRNA *)pyrna_array_index(ptr, prop, index); - } - - return (PyObject *)ret; + int totdim, arraydim, arrayoffset, dimsize[MAX_ARRAY_DIMENSION], i, len; + BPy_PropertyArrayRNA *ret = NULL; + + arraydim = self ? self->arraydim : 0; + arrayoffset = self ? self->arrayoffset : 0; + + /* just in case check */ + len = RNA_property_multi_array_length(ptr, prop, arraydim); + if (index >= len || index < 0) { + /* this shouldn't happen because higher level funcs must check for invalid index */ + CLOG_WARN(BPY_LOG_RNA, "invalid index %d for array with length=%d", index, len); + + PyErr_SetString(PyExc_IndexError, "out of range"); + return NULL; + } + + totdim = RNA_property_array_dimension(ptr, prop, dimsize); + + if (arraydim + 1 < totdim) { + ret = (BPy_PropertyArrayRNA *)pyrna_prop_CreatePyObject(ptr, prop); + ret->arraydim = arraydim + 1; + + /* arr[3][4][5] + * + * x = arr[2] + * index = 0 + 2 * 4 * 5 + * + * x = arr[2][3] + * index = offset + 3 * 5 */ + + for (i = arraydim + 1; i < totdim; i++) { + index *= dimsize[i]; + } + + ret->arrayoffset = arrayoffset + index; + } + else { + index = arrayoffset + index; + ret = (BPy_PropertyArrayRNA *)pyrna_array_index(ptr, prop, index); + } + + return (PyObject *)ret; } PyObject *pyrna_py_from_array(PointerRNA *ptr, PropertyRNA *prop) { - PyObject *ret; + PyObject *ret; - ret = pyrna_math_object_from_array(ptr, prop); + ret = pyrna_math_object_from_array(ptr, prop); - /* is this a maths object? */ - if (ret) { - return ret; - } + /* is this a maths object? */ + if (ret) { + return ret; + } - return pyrna_prop_CreatePyObject(ptr, prop); + return pyrna_prop_CreatePyObject(ptr, prop); } /* TODO, multi-dimensional arrays */ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) { - int len = RNA_property_array_length(ptr, prop); - int type; - int i; - - if (len == 0) { - /* possible with dynamic arrays */ - return 0; - } - - if (RNA_property_array_dimension(ptr, prop, NULL) > 1) { - PyErr_SetString(PyExc_TypeError, "PropertyRNA - multi dimensional arrays not supported yet"); - return -1; - } - - type = RNA_property_type(prop); - - switch (type) { - case PROP_FLOAT: - { - float value_f = PyFloat_AsDouble(value); - if (value_f == -1 && PyErr_Occurred()) { - PyErr_Clear(); - return 0; - } - else { - float tmp[32]; - float *tmp_arr; - - if (len * sizeof(float) > sizeof(tmp)) { - tmp_arr = PyMem_MALLOC(len * sizeof(float)); - } - else { - tmp_arr = tmp; - } - - RNA_property_float_get_array(ptr, prop, tmp_arr); - - for (i = 0; i < len; i++) { - if (tmp_arr[i] == value_f) { - break; - } - } - - if (tmp_arr != tmp) { - PyMem_FREE(tmp_arr); - } - - return i < len ? 1 : 0; - } - break; - } - case PROP_INT: - { - int value_i = PyC_Long_AsI32(value); - if (value_i == -1 && PyErr_Occurred()) { - PyErr_Clear(); - return 0; - } - else { - int tmp[32]; - int *tmp_arr; - - if (len * sizeof(int) > sizeof(tmp)) { - tmp_arr = PyMem_MALLOC(len * sizeof(int)); - } - else { - tmp_arr = tmp; - } - - RNA_property_int_get_array(ptr, prop, tmp_arr); - - for (i = 0; i < len; i++) { - if (tmp_arr[i] == value_i) { - break; - } - } - - if (tmp_arr != tmp) { - PyMem_FREE(tmp_arr); - } - - return i < len ? 1 : 0; - } - break; - } - case PROP_BOOLEAN: - { - int value_i = PyC_Long_AsBool(value); - if (value_i == -1 && PyErr_Occurred()) { - PyErr_Clear(); - return 0; - } - else { - bool tmp[32]; - bool *tmp_arr; - - if (len * sizeof(bool) > sizeof(tmp)) { - tmp_arr = PyMem_MALLOC(len * sizeof(bool)); - } - else { - tmp_arr = tmp; - } - - RNA_property_boolean_get_array(ptr, prop, tmp_arr); - - for (i = 0; i < len; i++) { - if (tmp_arr[i] == value_i) { - break; - } - } - - if (tmp_arr != tmp) { - PyMem_FREE(tmp_arr); - } - - return i < len ? 1 : 0; - } - break; - } - } - - /* should never reach this */ - PyErr_SetString(PyExc_TypeError, "PropertyRNA - type not in float/bool/int"); - return -1; + int len = RNA_property_array_length(ptr, prop); + int type; + int i; + + if (len == 0) { + /* possible with dynamic arrays */ + return 0; + } + + if (RNA_property_array_dimension(ptr, prop, NULL) > 1) { + PyErr_SetString(PyExc_TypeError, "PropertyRNA - multi dimensional arrays not supported yet"); + return -1; + } + + type = RNA_property_type(prop); + + switch (type) { + case PROP_FLOAT: { + float value_f = PyFloat_AsDouble(value); + if (value_f == -1 && PyErr_Occurred()) { + PyErr_Clear(); + return 0; + } + else { + float tmp[32]; + float *tmp_arr; + + if (len * sizeof(float) > sizeof(tmp)) { + tmp_arr = PyMem_MALLOC(len * sizeof(float)); + } + else { + tmp_arr = tmp; + } + + RNA_property_float_get_array(ptr, prop, tmp_arr); + + for (i = 0; i < len; i++) { + if (tmp_arr[i] == value_f) { + break; + } + } + + if (tmp_arr != tmp) { + PyMem_FREE(tmp_arr); + } + + return i < len ? 1 : 0; + } + break; + } + case PROP_INT: { + int value_i = PyC_Long_AsI32(value); + if (value_i == -1 && PyErr_Occurred()) { + PyErr_Clear(); + return 0; + } + else { + int tmp[32]; + int *tmp_arr; + + if (len * sizeof(int) > sizeof(tmp)) { + tmp_arr = PyMem_MALLOC(len * sizeof(int)); + } + else { + tmp_arr = tmp; + } + + RNA_property_int_get_array(ptr, prop, tmp_arr); + + for (i = 0; i < len; i++) { + if (tmp_arr[i] == value_i) { + break; + } + } + + if (tmp_arr != tmp) { + PyMem_FREE(tmp_arr); + } + + return i < len ? 1 : 0; + } + break; + } + case PROP_BOOLEAN: { + int value_i = PyC_Long_AsBool(value); + if (value_i == -1 && PyErr_Occurred()) { + PyErr_Clear(); + return 0; + } + else { + bool tmp[32]; + bool *tmp_arr; + + if (len * sizeof(bool) > sizeof(tmp)) { + tmp_arr = PyMem_MALLOC(len * sizeof(bool)); + } + else { + tmp_arr = tmp; + } + + RNA_property_boolean_get_array(ptr, prop, tmp_arr); + + for (i = 0; i < len; i++) { + if (tmp_arr[i] == value_i) { + break; + } + } + + if (tmp_arr != tmp) { + PyMem_FREE(tmp_arr); + } + + return i < len ? 1 : 0; + } + break; + } + } + + /* should never reach this */ + PyErr_SetString(PyExc_TypeError, "PropertyRNA - type not in float/bool/int"); + return -1; } diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c index 30ea657200c..b24a28229aa 100644 --- a/source/blender/python/intern/bpy_rna_callback.c +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -21,7 +21,6 @@ * extended later. */ - #include <Python.h> #include "RNA_types.h" @@ -52,396 +51,429 @@ static const char *rna_capsual_id = "RNA_HANDLE"; static const char *rna_capsual_id_invalid = "RNA_HANDLE_REMOVED"; static const EnumPropertyItem region_draw_mode_items[] = { - {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""}, - {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Post View", ""}, - {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""}, - {0, NULL, 0, NULL, NULL}, + {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""}, + {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Post View", ""}, + {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""}, + {0, NULL, 0, NULL, NULL}, }; static void cb_region_draw(const bContext *C, ARegion *UNUSED(ar), void *customdata) { - PyObject *cb_func, *cb_args, *result; - PyGILState_STATE gilstate; + PyObject *cb_func, *cb_args, *result; + PyGILState_STATE gilstate; - bpy_context_set((bContext *)C, &gilstate); + bpy_context_set((bContext *)C, &gilstate); - cb_func = PyTuple_GET_ITEM((PyObject *)customdata, 1); - cb_args = PyTuple_GET_ITEM((PyObject *)customdata, 2); - result = PyObject_CallObject(cb_func, cb_args); + cb_func = PyTuple_GET_ITEM((PyObject *)customdata, 1); + cb_args = PyTuple_GET_ITEM((PyObject *)customdata, 2); + result = PyObject_CallObject(cb_func, cb_args); - if (result) { - Py_DECREF(result); - } - else { - PyErr_Print(); - PyErr_Clear(); - } + if (result) { + Py_DECREF(result); + } + else { + PyErr_Print(); + PyErr_Clear(); + } - bpy_context_clear((bContext *)C, &gilstate); + bpy_context_clear((bContext *)C, &gilstate); } /* We could make generic utility */ static PyObject *PyC_Tuple_CopySized(PyObject *src, int len_dst) { - PyObject *dst = PyTuple_New(len_dst); - int len_src = PyTuple_GET_SIZE(src); - BLI_assert(len_src <= len_dst); - for (int i = 0; i < len_src; i++) { - PyObject *item = PyTuple_GET_ITEM(src, i); - PyTuple_SET_ITEM(dst, i, item); - Py_INCREF(item); - } - return dst; + PyObject *dst = PyTuple_New(len_dst); + int len_src = PyTuple_GET_SIZE(src); + BLI_assert(len_src <= len_dst); + for (int i = 0; i < len_src; i++) { + PyObject *item = PyTuple_GET_ITEM(src, i); + PyTuple_SET_ITEM(dst, i, item); + Py_INCREF(item); + } + return dst; } static void cb_wm_cursor_draw(bContext *C, int x, int y, void *customdata) { - PyObject *cb_func, *cb_args, *result; - PyGILState_STATE gilstate; + PyObject *cb_func, *cb_args, *result; + PyGILState_STATE gilstate; - bpy_context_set((bContext *)C, &gilstate); + bpy_context_set((bContext *)C, &gilstate); - cb_func = PyTuple_GET_ITEM((PyObject *)customdata, 1); - cb_args = PyTuple_GET_ITEM((PyObject *)customdata, 2); + cb_func = PyTuple_GET_ITEM((PyObject *)customdata, 1); + cb_args = PyTuple_GET_ITEM((PyObject *)customdata, 2); - const int cb_args_len = PyTuple_GET_SIZE(cb_args); + const int cb_args_len = PyTuple_GET_SIZE(cb_args); - PyObject *cb_args_xy = PyTuple_New(2); - PyTuple_SET_ITEMS(cb_args_xy, PyLong_FromLong(x), PyLong_FromLong(y)); + PyObject *cb_args_xy = PyTuple_New(2); + PyTuple_SET_ITEMS(cb_args_xy, PyLong_FromLong(x), PyLong_FromLong(y)); - PyObject *cb_args_with_xy = PyC_Tuple_CopySized(cb_args, cb_args_len + 1); - PyTuple_SET_ITEM(cb_args_with_xy, cb_args_len, cb_args_xy); + PyObject *cb_args_with_xy = PyC_Tuple_CopySized(cb_args, cb_args_len + 1); + PyTuple_SET_ITEM(cb_args_with_xy, cb_args_len, cb_args_xy); - result = PyObject_CallObject(cb_func, cb_args_with_xy); + result = PyObject_CallObject(cb_func, cb_args_with_xy); - Py_DECREF(cb_args_with_xy); + Py_DECREF(cb_args_with_xy); - if (result) { - Py_DECREF(result); - } - else { - PyErr_Print(); - PyErr_Clear(); - } + if (result) { + Py_DECREF(result); + } + else { + PyErr_Print(); + PyErr_Clear(); + } - bpy_context_clear((bContext *)C, &gilstate); + bpy_context_clear((bContext *)C, &gilstate); } #if 0 PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args) { - void *handle; - - PyObject *cb_func, *cb_args; - char *cb_event_str = NULL; - int cb_event; - - if (!PyArg_ParseTuple(args, "OO!|s:bpy_struct.callback_add", &cb_func, &PyTuple_Type, &cb_args, &cb_event_str)) { - return NULL; - } - - if (!PyCallable_Check(cb_func)) { - PyErr_SetString(PyExc_TypeError, "callback_add(): first argument isn't callable"); - return NULL; - } - - if (RNA_struct_is_a(self->ptr.type, &RNA_Region)) { - if (cb_event_str) { - if (pyrna_enum_value_from_id( - region_draw_mode_items, cb_event_str, - &cb_event, "bpy_struct.callback_add()") == -1) - { - return NULL; - } - } - else { - cb_event = REGION_DRAW_POST_PIXEL; - } - - handle = ED_region_draw_cb_activate(((ARegion *)self->ptr.data)->type, cb_region_draw, (void *)args, cb_event); - Py_INCREF(args); - } - else { - PyErr_SetString(PyExc_TypeError, "callback_add(): type does not support callbacks"); - return NULL; - } - - return PyCapsule_New((void *)handle, rna_capsual_id, NULL); + void *handle; + + PyObject *cb_func, *cb_args; + char *cb_event_str = NULL; + int cb_event; + + if (!PyArg_ParseTuple(args, "OO!|s:bpy_struct.callback_add", &cb_func, &PyTuple_Type, &cb_args, &cb_event_str)) { + return NULL; + } + + if (!PyCallable_Check(cb_func)) { + PyErr_SetString(PyExc_TypeError, "callback_add(): first argument isn't callable"); + return NULL; + } + + if (RNA_struct_is_a(self->ptr.type, &RNA_Region)) { + if (cb_event_str) { + if (pyrna_enum_value_from_id( + region_draw_mode_items, cb_event_str, + &cb_event, "bpy_struct.callback_add()") == -1) + { + return NULL; + } + } + else { + cb_event = REGION_DRAW_POST_PIXEL; + } + + handle = ED_region_draw_cb_activate(((ARegion *)self->ptr.data)->type, cb_region_draw, (void *)args, cb_event); + Py_INCREF(args); + } + else { + PyErr_SetString(PyExc_TypeError, "callback_add(): type does not support callbacks"); + return NULL; + } + + return PyCapsule_New((void *)handle, rna_capsual_id, NULL); } PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args) { - PyObject *py_handle; - void *handle; - void *customdata; + PyObject *py_handle; + void *handle; + void *customdata; - if (!PyArg_ParseTuple(args, "O!:callback_remove", &PyCapsule_Type, &py_handle)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "O!:callback_remove", &PyCapsule_Type, &py_handle)) { + return NULL; + } - handle = PyCapsule_GetPointer(py_handle, rna_capsual_id); + handle = PyCapsule_GetPointer(py_handle, rna_capsual_id); - if (handle == NULL) { - PyErr_SetString(PyExc_ValueError, "callback_remove(handle): NULL handle given, invalid or already removed"); - return NULL; - } + if (handle == NULL) { + PyErr_SetString(PyExc_ValueError, "callback_remove(handle): NULL handle given, invalid or already removed"); + return NULL; + } - if (RNA_struct_is_a(self->ptr.type, &RNA_Region)) { - customdata = ED_region_draw_cb_customdata(handle); - Py_DECREF((PyObject *)customdata); + if (RNA_struct_is_a(self->ptr.type, &RNA_Region)) { + customdata = ED_region_draw_cb_customdata(handle); + Py_DECREF((PyObject *)customdata); - ED_region_draw_cb_exit(((ARegion *)self->ptr.data)->type, handle); - } - else { - PyErr_SetString(PyExc_TypeError, "callback_remove(): type does not support callbacks"); - return NULL; - } + ED_region_draw_cb_exit(((ARegion *)self->ptr.data)->type, handle); + } + else { + PyErr_SetString(PyExc_TypeError, "callback_remove(): type does not support callbacks"); + return NULL; + } - /* don't allow reuse */ - PyCapsule_SetName(py_handle, rna_capsual_id_invalid); + /* don't allow reuse */ + PyCapsule_SetName(py_handle, rna_capsual_id_invalid); - Py_RETURN_NONE; + Py_RETURN_NONE; } #endif /* reverse of rna_Space_refine() */ static eSpace_Type rna_Space_refine_reverse(StructRNA *srna) { - if (srna == &RNA_SpaceView3D) { return SPACE_VIEW3D; } - if (srna == &RNA_SpaceGraphEditor) { return SPACE_GRAPH; } - if (srna == &RNA_SpaceOutliner) { return SPACE_OUTLINER; } - if (srna == &RNA_SpaceProperties) { return SPACE_PROPERTIES; } - if (srna == &RNA_SpaceFileBrowser) { return SPACE_FILE; } - if (srna == &RNA_SpaceImageEditor) { return SPACE_IMAGE; } - if (srna == &RNA_SpaceInfo) { return SPACE_INFO; } - if (srna == &RNA_SpaceSequenceEditor) { return SPACE_SEQ; } - if (srna == &RNA_SpaceTextEditor) { return SPACE_TEXT; } - if (srna == &RNA_SpaceDopeSheetEditor) { return SPACE_ACTION; } - if (srna == &RNA_SpaceNLA) { return SPACE_NLA; } - if (srna == &RNA_SpaceNodeEditor) { return SPACE_NODE; } - if (srna == &RNA_SpaceConsole) { return SPACE_CONSOLE; } - if (srna == &RNA_SpacePreferences) { return SPACE_USERPREF; } - if (srna == &RNA_SpaceClipEditor) { return SPACE_CLIP; } - return SPACE_EMPTY; + if (srna == &RNA_SpaceView3D) { + return SPACE_VIEW3D; + } + if (srna == &RNA_SpaceGraphEditor) { + return SPACE_GRAPH; + } + if (srna == &RNA_SpaceOutliner) { + return SPACE_OUTLINER; + } + if (srna == &RNA_SpaceProperties) { + return SPACE_PROPERTIES; + } + if (srna == &RNA_SpaceFileBrowser) { + return SPACE_FILE; + } + if (srna == &RNA_SpaceImageEditor) { + return SPACE_IMAGE; + } + if (srna == &RNA_SpaceInfo) { + return SPACE_INFO; + } + if (srna == &RNA_SpaceSequenceEditor) { + return SPACE_SEQ; + } + if (srna == &RNA_SpaceTextEditor) { + return SPACE_TEXT; + } + if (srna == &RNA_SpaceDopeSheetEditor) { + return SPACE_ACTION; + } + if (srna == &RNA_SpaceNLA) { + return SPACE_NLA; + } + if (srna == &RNA_SpaceNodeEditor) { + return SPACE_NODE; + } + if (srna == &RNA_SpaceConsole) { + return SPACE_CONSOLE; + } + if (srna == &RNA_SpacePreferences) { + return SPACE_USERPREF; + } + if (srna == &RNA_SpaceClipEditor) { + return SPACE_CLIP; + } + return SPACE_EMPTY; } PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args) { - void *handle; - PyObject *cls; - PyObject *cb_func, *cb_args; - StructRNA *srna; - - if (PyTuple_GET_SIZE(args) < 2) { - PyErr_SetString(PyExc_ValueError, "handler_add(handler): expected at least 2 args"); - return NULL; - } - - cls = PyTuple_GET_ITEM(args, 0); - if (!(srna = pyrna_struct_as_srna(cls, false, "handler_add"))) { - return NULL; - } - cb_func = PyTuple_GET_ITEM(args, 1); - if (!PyCallable_Check(cb_func)) { - PyErr_SetString(PyExc_TypeError, "first argument isn't callable"); - return NULL; - } - - /* class specific callbacks */ - - if (srna == &RNA_WindowManager) { - const char *error_prefix = "WindowManager.draw_cursor_add"; - struct { - const char *space_type_str; - const char *region_type_str; - - int space_type; - int region_type; - } params = { - .space_type_str = NULL, - .region_type_str = NULL, - .space_type = SPACE_TYPE_ANY, - .region_type = RGN_TYPE_ANY, - }; - - if (!PyArg_ParseTuple( - args, "OOO!|ss:WindowManager.draw_cursor_add", - &cls, &cb_func, /* already assigned, no matter */ - &PyTuple_Type, &cb_args, ¶ms.space_type_str, ¶ms.region_type_str)) - { - return NULL; - } - - if (params.space_type_str && pyrna_enum_value_from_id( - rna_enum_space_type_items, params.space_type_str, - ¶ms.space_type, error_prefix) == -1) - { - return NULL; - } - else if (params.region_type_str && pyrna_enum_value_from_id( - rna_enum_region_type_items, params.region_type_str, - ¶ms.region_type, error_prefix) == -1) - { - return NULL; - } - - bContext *C = BPy_GetContext(); - struct wmWindowManager *wm = CTX_wm_manager(C); - handle = WM_paint_cursor_activate( - wm, - params.space_type, params.region_type, - NULL, cb_wm_cursor_draw, (void *)args); - } - else if (RNA_struct_is_a(srna, &RNA_Space)) { - const char *error_prefix = "Space.draw_handler_add"; - struct { - const char *region_type_str; - const char *event_str; - - int region_type; - int event; - } params; - - if (!PyArg_ParseTuple( - args, "OOO!ss:Space.draw_handler_add", - &cls, &cb_func, /* already assigned, no matter */ - &PyTuple_Type, &cb_args, - ¶ms.region_type_str, ¶ms.event_str)) - { - return NULL; - } - - if (pyrna_enum_value_from_id( - region_draw_mode_items, params.event_str, - ¶ms.event, error_prefix) == -1) - { - return NULL; - } - else if (pyrna_enum_value_from_id( - rna_enum_region_type_items, params.region_type_str, - ¶ms.region_type, error_prefix) == -1) - { - return NULL; - } - else { - const eSpace_Type spaceid = rna_Space_refine_reverse(srna); - if (spaceid == SPACE_EMPTY) { - PyErr_Format(PyExc_TypeError, "unknown space type '%.200s'", RNA_struct_identifier(srna)); - return NULL; - } - else { - SpaceType *st = BKE_spacetype_from_id(spaceid); - ARegionType *art = BKE_regiontype_from_id(st, params.region_type); - if (art == NULL) { - PyErr_Format(PyExc_TypeError, "region type '%.200s' not in space", params.region_type_str); - return NULL; - } - handle = ED_region_draw_cb_activate(art, cb_region_draw, (void *)args, params.event); - } - } - } - else { - PyErr_SetString(PyExc_TypeError, "callback_add(): type does not support callbacks"); - return NULL; - } - - PyObject *ret = PyCapsule_New((void *)handle, rna_capsual_id, NULL); - - /* Store 'args' in context as well as the handler custom-data, - * because the handle may be freed by Blender (new file, new window... etc) */ - PyCapsule_SetContext(ret, args); - Py_INCREF(args); - - return ret; + void *handle; + PyObject *cls; + PyObject *cb_func, *cb_args; + StructRNA *srna; + + if (PyTuple_GET_SIZE(args) < 2) { + PyErr_SetString(PyExc_ValueError, "handler_add(handler): expected at least 2 args"); + return NULL; + } + + cls = PyTuple_GET_ITEM(args, 0); + if (!(srna = pyrna_struct_as_srna(cls, false, "handler_add"))) { + return NULL; + } + cb_func = PyTuple_GET_ITEM(args, 1); + if (!PyCallable_Check(cb_func)) { + PyErr_SetString(PyExc_TypeError, "first argument isn't callable"); + return NULL; + } + + /* class specific callbacks */ + + if (srna == &RNA_WindowManager) { + const char *error_prefix = "WindowManager.draw_cursor_add"; + struct { + const char *space_type_str; + const char *region_type_str; + + int space_type; + int region_type; + } params = { + .space_type_str = NULL, + .region_type_str = NULL, + .space_type = SPACE_TYPE_ANY, + .region_type = RGN_TYPE_ANY, + }; + + if (!PyArg_ParseTuple(args, + "OOO!|ss:WindowManager.draw_cursor_add", + &cls, + &cb_func, /* already assigned, no matter */ + &PyTuple_Type, + &cb_args, + ¶ms.space_type_str, + ¶ms.region_type_str)) { + return NULL; + } + + if (params.space_type_str && pyrna_enum_value_from_id(rna_enum_space_type_items, + params.space_type_str, + ¶ms.space_type, + error_prefix) == -1) { + return NULL; + } + else if (params.region_type_str && pyrna_enum_value_from_id(rna_enum_region_type_items, + params.region_type_str, + ¶ms.region_type, + error_prefix) == -1) { + return NULL; + } + + bContext *C = BPy_GetContext(); + struct wmWindowManager *wm = CTX_wm_manager(C); + handle = WM_paint_cursor_activate( + wm, params.space_type, params.region_type, NULL, cb_wm_cursor_draw, (void *)args); + } + else if (RNA_struct_is_a(srna, &RNA_Space)) { + const char *error_prefix = "Space.draw_handler_add"; + struct { + const char *region_type_str; + const char *event_str; + + int region_type; + int event; + } params; + + if (!PyArg_ParseTuple(args, + "OOO!ss:Space.draw_handler_add", + &cls, + &cb_func, /* already assigned, no matter */ + &PyTuple_Type, + &cb_args, + ¶ms.region_type_str, + ¶ms.event_str)) { + return NULL; + } + + if (pyrna_enum_value_from_id( + region_draw_mode_items, params.event_str, ¶ms.event, error_prefix) == -1) { + return NULL; + } + else if (pyrna_enum_value_from_id(rna_enum_region_type_items, + params.region_type_str, + ¶ms.region_type, + error_prefix) == -1) { + return NULL; + } + else { + const eSpace_Type spaceid = rna_Space_refine_reverse(srna); + if (spaceid == SPACE_EMPTY) { + PyErr_Format(PyExc_TypeError, "unknown space type '%.200s'", RNA_struct_identifier(srna)); + return NULL; + } + else { + SpaceType *st = BKE_spacetype_from_id(spaceid); + ARegionType *art = BKE_regiontype_from_id(st, params.region_type); + if (art == NULL) { + PyErr_Format( + PyExc_TypeError, "region type '%.200s' not in space", params.region_type_str); + return NULL; + } + handle = ED_region_draw_cb_activate(art, cb_region_draw, (void *)args, params.event); + } + } + } + else { + PyErr_SetString(PyExc_TypeError, "callback_add(): type does not support callbacks"); + return NULL; + } + + PyObject *ret = PyCapsule_New((void *)handle, rna_capsual_id, NULL); + + /* Store 'args' in context as well as the handler custom-data, + * because the handle may be freed by Blender (new file, new window... etc) */ + PyCapsule_SetContext(ret, args); + Py_INCREF(args); + + return ret; } PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *args) { - PyObject *cls; - PyObject *py_handle; - void *handle; - StructRNA *srna; - bool capsule_clear = false; - - if (PyTuple_GET_SIZE(args) < 2) { - PyErr_SetString(PyExc_ValueError, "callback_remove(handler): expected at least 2 args"); - return NULL; - } - - cls = PyTuple_GET_ITEM(args, 0); - if (!(srna = pyrna_struct_as_srna(cls, false, "callback_remove"))) { - return NULL; - } - py_handle = PyTuple_GET_ITEM(args, 1); - handle = PyCapsule_GetPointer(py_handle, rna_capsual_id); - if (handle == NULL) { - PyErr_SetString(PyExc_ValueError, "callback_remove(handler): NULL handler given, invalid or already removed"); - return NULL; - } - PyObject *handle_args = PyCapsule_GetContext(py_handle); - - if (srna == &RNA_WindowManager) { - if (!PyArg_ParseTuple( - args, "OO!:WindowManager.draw_cursor_remove", - &cls, &PyCapsule_Type, &py_handle)) - { - return NULL; - } - bContext *C = BPy_GetContext(); - struct wmWindowManager *wm = CTX_wm_manager(C); - WM_paint_cursor_end(wm, handle); - capsule_clear = true; - } - else if (RNA_struct_is_a(srna, &RNA_Space)) { - const char *error_prefix = "Space.draw_handler_remove"; - struct { - const char *region_type_str; - - int region_type; - } params; - - if (!PyArg_ParseTuple( - args, "OO!s:Space.draw_handler_remove", - &cls, &PyCapsule_Type, &py_handle, /* already assigned, no matter */ - ¶ms.region_type_str)) - { - return NULL; - } - - if (pyrna_enum_value_from_id( - rna_enum_region_type_items, params.region_type_str, - ¶ms.region_type, error_prefix) == -1) - { - return NULL; - } - else { - const eSpace_Type spaceid = rna_Space_refine_reverse(srna); - if (spaceid == SPACE_EMPTY) { - PyErr_Format(PyExc_TypeError, "unknown space type '%.200s'", RNA_struct_identifier(srna)); - return NULL; - } - else { - SpaceType *st = BKE_spacetype_from_id(spaceid); - ARegionType *art = BKE_regiontype_from_id(st, params.region_type); - if (art == NULL) { - PyErr_Format(PyExc_TypeError, "region type '%.200s' not in space", params.region_type_str); - return NULL; - } - ED_region_draw_cb_exit(art, handle); - capsule_clear = true; - } - } - } - else { - PyErr_SetString(PyExc_TypeError, "callback_remove(): type does not support callbacks"); - return NULL; - } - - /* don't allow reuse */ - if (capsule_clear) { - Py_DECREF(handle_args); - PyCapsule_SetName(py_handle, rna_capsual_id_invalid); - } - - Py_RETURN_NONE; + PyObject *cls; + PyObject *py_handle; + void *handle; + StructRNA *srna; + bool capsule_clear = false; + + if (PyTuple_GET_SIZE(args) < 2) { + PyErr_SetString(PyExc_ValueError, "callback_remove(handler): expected at least 2 args"); + return NULL; + } + + cls = PyTuple_GET_ITEM(args, 0); + if (!(srna = pyrna_struct_as_srna(cls, false, "callback_remove"))) { + return NULL; + } + py_handle = PyTuple_GET_ITEM(args, 1); + handle = PyCapsule_GetPointer(py_handle, rna_capsual_id); + if (handle == NULL) { + PyErr_SetString(PyExc_ValueError, + "callback_remove(handler): NULL handler given, invalid or already removed"); + return NULL; + } + PyObject *handle_args = PyCapsule_GetContext(py_handle); + + if (srna == &RNA_WindowManager) { + if (!PyArg_ParseTuple( + args, "OO!:WindowManager.draw_cursor_remove", &cls, &PyCapsule_Type, &py_handle)) { + return NULL; + } + bContext *C = BPy_GetContext(); + struct wmWindowManager *wm = CTX_wm_manager(C); + WM_paint_cursor_end(wm, handle); + capsule_clear = true; + } + else if (RNA_struct_is_a(srna, &RNA_Space)) { + const char *error_prefix = "Space.draw_handler_remove"; + struct { + const char *region_type_str; + + int region_type; + } params; + + if (!PyArg_ParseTuple(args, + "OO!s:Space.draw_handler_remove", + &cls, + &PyCapsule_Type, + &py_handle, /* already assigned, no matter */ + ¶ms.region_type_str)) { + return NULL; + } + + if (pyrna_enum_value_from_id(rna_enum_region_type_items, + params.region_type_str, + ¶ms.region_type, + error_prefix) == -1) { + return NULL; + } + else { + const eSpace_Type spaceid = rna_Space_refine_reverse(srna); + if (spaceid == SPACE_EMPTY) { + PyErr_Format(PyExc_TypeError, "unknown space type '%.200s'", RNA_struct_identifier(srna)); + return NULL; + } + else { + SpaceType *st = BKE_spacetype_from_id(spaceid); + ARegionType *art = BKE_regiontype_from_id(st, params.region_type); + if (art == NULL) { + PyErr_Format( + PyExc_TypeError, "region type '%.200s' not in space", params.region_type_str); + return NULL; + } + ED_region_draw_cb_exit(art, handle); + capsule_clear = true; + } + } + } + else { + PyErr_SetString(PyExc_TypeError, "callback_remove(): type does not support callbacks"); + return NULL; + } + + /* don't allow reuse */ + if (capsule_clear) { + Py_DECREF(handle_args); + PyCapsule_SetName(py_handle, rna_capsual_id_invalid); + } + + Py_RETURN_NONE; } diff --git a/source/blender/python/intern/bpy_rna_callback.h b/source/blender/python/intern/bpy_rna_callback.h index 6a13e2de9a7..71e1f71f8af 100644 --- a/source/blender/python/intern/bpy_rna_callback.h +++ b/source/blender/python/intern/bpy_rna_callback.h @@ -32,4 +32,4 @@ PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args); PyObject *pyrna_callback_classmethod_add(PyObject *cls, PyObject *args); PyObject *pyrna_callback_classmethod_remove(PyObject *cls, PyObject *args); -#endif /* __BPY_RNA_CALLBACK_H__ */ +#endif /* __BPY_RNA_CALLBACK_H__ */ diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c index 91030f7ac36..e9e8d05aa74 100644 --- a/source/blender/python/intern/bpy_rna_driver.c +++ b/source/blender/python/intern/bpy_rna_driver.c @@ -32,73 +32,69 @@ #include "bpy_rna.h" -#include "bpy_rna_driver.h" /* own include */ - +#include "bpy_rna_driver.h" /* own include */ /** * A version of #driver_get_variable_value which returns a PyObject. */ -PyObject *pyrna_driver_get_variable_value( - struct ChannelDriver *driver, struct DriverTarget *dtar) +PyObject *pyrna_driver_get_variable_value(struct ChannelDriver *driver, struct DriverTarget *dtar) { - PyObject *driver_arg = NULL; - PointerRNA ptr; - PropertyRNA *prop = NULL; - int index; + PyObject *driver_arg = NULL; + PointerRNA ptr; + PropertyRNA *prop = NULL; + int index; - if (driver_get_variable_property(driver, dtar, &ptr, &prop, &index)) { - if (prop) { - if (index != -1) { - if (index < RNA_property_array_length(&ptr, prop) && index >= 0) { - /* object, property & index */ - driver_arg = pyrna_array_index(&ptr, prop, index); - } - else { - /* out of range, pass */ - } - } - else { - /* object & property */ - PropertyType type = RNA_property_type(prop); - if (type == PROP_ENUM) { - /* Note that enum's are converted to strings by default, - * we want to avoid that, see: T52213 */ - driver_arg = PyLong_FromLong(RNA_property_enum_get(&ptr, prop)); - } - else { - driver_arg = pyrna_prop_to_py(&ptr, prop); - } - } - } - else { - /* object only */ - driver_arg = pyrna_struct_CreatePyObject(&ptr); - } - } - else { - /* can't resolve path, pass */ - } + if (driver_get_variable_property(driver, dtar, &ptr, &prop, &index)) { + if (prop) { + if (index != -1) { + if (index < RNA_property_array_length(&ptr, prop) && index >= 0) { + /* object, property & index */ + driver_arg = pyrna_array_index(&ptr, prop, index); + } + else { + /* out of range, pass */ + } + } + else { + /* object & property */ + PropertyType type = RNA_property_type(prop); + if (type == PROP_ENUM) { + /* Note that enum's are converted to strings by default, + * we want to avoid that, see: T52213 */ + driver_arg = PyLong_FromLong(RNA_property_enum_get(&ptr, prop)); + } + else { + driver_arg = pyrna_prop_to_py(&ptr, prop); + } + } + } + else { + /* object only */ + driver_arg = pyrna_struct_CreatePyObject(&ptr); + } + } + else { + /* can't resolve path, pass */ + } - return driver_arg; + return driver_arg; } PyObject *pyrna_driver_self_from_anim_rna(PathResolvedRNA *anim_rna) { - return pyrna_struct_CreatePyObject(&anim_rna->ptr); + return pyrna_struct_CreatePyObject(&anim_rna->ptr); } bool pyrna_driver_is_equal_anim_rna(const PathResolvedRNA *anim_rna, const PyObject *py_anim_rna) { - if (BPy_StructRNA_Check(py_anim_rna)) { - const PointerRNA *ptr_a = &anim_rna->ptr; - const PointerRNA *ptr_b = &(((const BPy_StructRNA *)py_anim_rna)->ptr); + if (BPy_StructRNA_Check(py_anim_rna)) { + const PointerRNA *ptr_a = &anim_rna->ptr; + const PointerRNA *ptr_b = &(((const BPy_StructRNA *)py_anim_rna)->ptr); - if ((ptr_a->id.data == ptr_b->id.data) && - (ptr_a->type == ptr_b->type) && - (ptr_a->data == ptr_b->data)) - { - return true; - } - } - return false; + if ((ptr_a->id.data == ptr_b->id.data) && (ptr_a->type == ptr_b->type) && + (ptr_a->data == ptr_b->data)) { + return true; + } + } + return false; } diff --git a/source/blender/python/intern/bpy_rna_driver.h b/source/blender/python/intern/bpy_rna_driver.h index 0bb34b8fe9a..36160d7c867 100644 --- a/source/blender/python/intern/bpy_rna_driver.h +++ b/source/blender/python/intern/bpy_rna_driver.h @@ -28,6 +28,7 @@ struct PathResolvedRNA; PyObject *pyrna_driver_get_variable_value(struct ChannelDriver *driver, struct DriverTarget *dtar); PyObject *pyrna_driver_self_from_anim_rna(struct PathResolvedRNA *anim_rna); -bool pyrna_driver_is_equal_anim_rna(const struct PathResolvedRNA *anim_rna, const PyObject *py_anim_rna); +bool pyrna_driver_is_equal_anim_rna(const struct PathResolvedRNA *anim_rna, + const PyObject *py_anim_rna); -#endif /* __BPY_RNA_DRIVER_H__ */ +#endif /* __BPY_RNA_DRIVER_H__ */ diff --git a/source/blender/python/intern/bpy_rna_gizmo.c b/source/blender/python/intern/bpy_rna_gizmo.c index 68511627d51..ec041b3054a 100644 --- a/source/blender/python/intern/bpy_rna_gizmo.c +++ b/source/blender/python/intern/bpy_rna_gizmo.c @@ -28,7 +28,6 @@ #include "BLI_utildefines.h" #include "BLI_alloca.h" - #include "WM_api.h" #include "WM_types.h" @@ -44,280 +43,278 @@ #include "bpy_rna.h" - /* -------------------------------------------------------------------- */ /** \name Gizmo Target Property Define API * \{ */ enum { - BPY_GIZMO_FN_SLOT_GET = 0, - BPY_GIZMO_FN_SLOT_SET, - BPY_GIZMO_FN_SLOT_RANGE_GET, + BPY_GIZMO_FN_SLOT_GET = 0, + BPY_GIZMO_FN_SLOT_SET, + BPY_GIZMO_FN_SLOT_RANGE_GET, }; #define BPY_GIZMO_FN_SLOT_LEN (BPY_GIZMO_FN_SLOT_RANGE_GET + 1) struct BPyGizmoHandlerUserData { - PyObject *fn_slots[BPY_GIZMO_FN_SLOT_LEN]; + PyObject *fn_slots[BPY_GIZMO_FN_SLOT_LEN]; }; -static void py_rna_gizmo_handler_get_cb( - const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, - void *value_p) +static void py_rna_gizmo_handler_get_cb(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + void *value_p) { - PyGILState_STATE gilstate = PyGILState_Ensure(); - - struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; - PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_GET], NULL); - if (ret == NULL) { - goto fail; - } - - if (gz_prop->type->data_type == PROP_FLOAT) { - float *value = value_p; - if (gz_prop->type->array_length == 1) { - if ((*value = PyFloat_AsDouble(ret)) == -1.0f && PyErr_Occurred()) { - goto fail; - } - } - else { - if (PyC_AsArray(value, ret, gz_prop->type->array_length, &PyFloat_Type, false, - "Gizmo get callback: ") == -1) - { - goto fail; - } - } - } - else { - PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type"); - goto fail; - } - - Py_DECREF(ret); - - PyGILState_Release(gilstate); - return; + PyGILState_STATE gilstate = PyGILState_Ensure(); + + struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; + PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_GET], NULL); + if (ret == NULL) { + goto fail; + } + + if (gz_prop->type->data_type == PROP_FLOAT) { + float *value = value_p; + if (gz_prop->type->array_length == 1) { + if ((*value = PyFloat_AsDouble(ret)) == -1.0f && PyErr_Occurred()) { + goto fail; + } + } + else { + if (PyC_AsArray(value, + ret, + gz_prop->type->array_length, + &PyFloat_Type, + false, + "Gizmo get callback: ") == -1) { + goto fail; + } + } + } + else { + PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type"); + goto fail; + } + + Py_DECREF(ret); + + PyGILState_Release(gilstate); + return; fail: - PyErr_Print(); - PyErr_Clear(); + PyErr_Print(); + PyErr_Clear(); - PyGILState_Release(gilstate); + PyGILState_Release(gilstate); } -static void py_rna_gizmo_handler_set_cb( - const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, - const void *value_p) +static void py_rna_gizmo_handler_set_cb(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + const void *value_p) { - PyGILState_STATE gilstate = PyGILState_Ensure(); - - struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; - - PyObject *args = PyTuple_New(1); - - if (gz_prop->type->data_type == PROP_FLOAT) { - const float *value = value_p; - PyObject *py_value; - if (gz_prop->type->array_length == 1) { - py_value = PyFloat_FromDouble(*value); - } - else { - py_value = PyC_Tuple_PackArray_F32(value, gz_prop->type->array_length); - } - if (py_value == NULL) { - goto fail; - } - PyTuple_SET_ITEM(args, 0, py_value); - } - else { - PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type"); - goto fail; - } - - PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_SET], args); - if (ret == NULL) { - goto fail; - } - Py_DECREF(ret); - - PyGILState_Release(gilstate); - return; + PyGILState_STATE gilstate = PyGILState_Ensure(); + + struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; + + PyObject *args = PyTuple_New(1); + + if (gz_prop->type->data_type == PROP_FLOAT) { + const float *value = value_p; + PyObject *py_value; + if (gz_prop->type->array_length == 1) { + py_value = PyFloat_FromDouble(*value); + } + else { + py_value = PyC_Tuple_PackArray_F32(value, gz_prop->type->array_length); + } + if (py_value == NULL) { + goto fail; + } + PyTuple_SET_ITEM(args, 0, py_value); + } + else { + PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type"); + goto fail; + } + + PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_SET], args); + if (ret == NULL) { + goto fail; + } + Py_DECREF(ret); + + PyGILState_Release(gilstate); + return; fail: - PyErr_Print(); - PyErr_Clear(); + PyErr_Print(); + PyErr_Clear(); - Py_DECREF(args); + Py_DECREF(args); - PyGILState_Release(gilstate); + PyGILState_Release(gilstate); } -static void py_rna_gizmo_handler_range_get_cb( - const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, - void *value_p) +static void py_rna_gizmo_handler_range_get_cb(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + void *value_p) { - struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; - - PyGILState_STATE gilstate = PyGILState_Ensure(); - - PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_RANGE_GET], NULL); - if (ret == NULL) { - goto fail; - } - - if (!PyTuple_Check(ret)) { - PyErr_Format(PyExc_TypeError, - "Expected a tuple, not %.200s", - Py_TYPE(ret)->tp_name); - goto fail; - } - - if (PyTuple_GET_SIZE(ret) != 2) { - PyErr_Format(PyExc_TypeError, - "Expected a tuple of size 2, not %d", - PyTuple_GET_SIZE(ret)); - goto fail; - } - - if (gz_prop->type->data_type == PROP_FLOAT) { - float range[2]; - for (int i = 0; i < 2; i++) { - if (((range[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(ret, i))) == -1.0f && PyErr_Occurred()) == 0) { - /* pass */ - } - else { - goto fail; - } - } - memcpy(value_p, range, sizeof(range)); - } - else { - PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type"); - goto fail; - } - - Py_DECREF(ret); - PyGILState_Release(gilstate); - return; + struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; + + PyGILState_STATE gilstate = PyGILState_Ensure(); + + PyObject *ret = PyObject_CallObject(data->fn_slots[BPY_GIZMO_FN_SLOT_RANGE_GET], NULL); + if (ret == NULL) { + goto fail; + } + + if (!PyTuple_Check(ret)) { + PyErr_Format(PyExc_TypeError, "Expected a tuple, not %.200s", Py_TYPE(ret)->tp_name); + goto fail; + } + + if (PyTuple_GET_SIZE(ret) != 2) { + PyErr_Format(PyExc_TypeError, "Expected a tuple of size 2, not %d", PyTuple_GET_SIZE(ret)); + goto fail; + } + + if (gz_prop->type->data_type == PROP_FLOAT) { + float range[2]; + for (int i = 0; i < 2; i++) { + if (((range[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(ret, i))) == -1.0f && PyErr_Occurred()) == + 0) { + /* pass */ + } + else { + goto fail; + } + } + memcpy(value_p, range, sizeof(range)); + } + else { + PyErr_SetString(PyExc_AttributeError, "internal error, unsupported type"); + goto fail; + } + + Py_DECREF(ret); + PyGILState_Release(gilstate); + return; fail: - Py_XDECREF(ret); + Py_XDECREF(ret); - PyErr_Print(); - PyErr_Clear(); + PyErr_Print(); + PyErr_Clear(); - PyGILState_Release(gilstate); + PyGILState_Release(gilstate); } -static void py_rna_gizmo_handler_free_cb( - const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop) +static void py_rna_gizmo_handler_free_cb(const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop) { - struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; + struct BPyGizmoHandlerUserData *data = gz_prop->custom_func.user_data; - PyGILState_STATE gilstate = PyGILState_Ensure(); - for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) { - Py_XDECREF(data->fn_slots[i]); - } - PyGILState_Release(gilstate); - - MEM_freeN(data); + PyGILState_STATE gilstate = PyGILState_Ensure(); + for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) { + Py_XDECREF(data->fn_slots[i]); + } + PyGILState_Release(gilstate); + MEM_freeN(data); } -PyDoc_STRVAR(bpy_gizmo_target_set_handler_doc, -".. method:: target_set_handler(target, get, set, range=None):\n" -"\n" -" Assigns callbacks to a gizmos property.\n" -"\n" -" :arg get: Function that returns the value for this property (single value or sequence).\n" -" :type get: callable\n" -" :arg set: Function that takes a single value argument and applies it.\n" -" :type set: callable\n" -" :arg range: Function that returns a (min, max) tuple for gizmos that use a range.\n" -" :type range: callable\n" -); +PyDoc_STRVAR( + bpy_gizmo_target_set_handler_doc, + ".. method:: target_set_handler(target, get, set, range=None):\n" + "\n" + " Assigns callbacks to a gizmos property.\n" + "\n" + " :arg get: Function that returns the value for this property (single value or sequence).\n" + " :type get: callable\n" + " :arg set: Function that takes a single value argument and applies it.\n" + " :type set: callable\n" + " :arg range: Function that returns a (min, max) tuple for gizmos that use a range.\n" + " :type range: callable\n"); static PyObject *bpy_gizmo_target_set_handler(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - PyGILState_STATE gilstate = PyGILState_Ensure(); - - struct { - PyObject *self; - char *target; - PyObject *py_fn_slots[BPY_GIZMO_FN_SLOT_LEN]; - } params = { - .self = NULL, - .target = NULL, - .py_fn_slots = {NULL}, - }; - - /* Note: this is a counter-part to functions: - * 'Gizmo.target_set_prop & target_set_operator' - * (see: rna_wm_gizmo_api.c). conventions should match. */ - static const char * const _keywords[] = {"self", "target", "get", "set", "range", NULL}; - static _PyArg_Parser _parser = {"Os|$OOO:target_set_handler", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - ¶ms.self, - ¶ms.target, - ¶ms.py_fn_slots[BPY_GIZMO_FN_SLOT_GET], - ¶ms.py_fn_slots[BPY_GIZMO_FN_SLOT_SET], - ¶ms.py_fn_slots[BPY_GIZMO_FN_SLOT_RANGE_GET])) - { - goto fail; - } - - wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data; - - const wmGizmoPropertyType *gz_prop_type = - WM_gizmotype_target_property_find(gz->type, params.target); - if (gz_prop_type == NULL) { - PyErr_Format(PyExc_ValueError, - "Gizmo target property '%s.%s' not found", - gz->type->idname, params.target); - goto fail; - } - - { - const int slots_required = 2; - const int slots_start = 2; - for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) { - if (params.py_fn_slots[i] == NULL) { - if (i < slots_required) { - PyErr_Format(PyExc_ValueError, "Argument '%s' not given", _keywords[slots_start + i]); - goto fail; - } - } - else if (!PyCallable_Check(params.py_fn_slots[i])) { - PyErr_Format(PyExc_ValueError, "Argument '%s' not callable", _keywords[slots_start + i]); - goto fail; - } - } - } - - struct BPyGizmoHandlerUserData *data = MEM_callocN(sizeof(*data), __func__); - - for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) { - data->fn_slots[i] = params.py_fn_slots[i]; - Py_XINCREF(params.py_fn_slots[i]); - } - - WM_gizmo_target_property_def_func_ptr( - gz, gz_prop_type, - &(const struct wmGizmoPropertyFnParams) { - .value_get_fn = py_rna_gizmo_handler_get_cb, - .value_set_fn = py_rna_gizmo_handler_set_cb, - .range_get_fn = py_rna_gizmo_handler_range_get_cb, - .free_fn = py_rna_gizmo_handler_free_cb, - .user_data = data, - }); - - PyGILState_Release(gilstate); - - Py_RETURN_NONE; + PyGILState_STATE gilstate = PyGILState_Ensure(); + + struct { + PyObject *self; + char *target; + PyObject *py_fn_slots[BPY_GIZMO_FN_SLOT_LEN]; + } params = { + .self = NULL, + .target = NULL, + .py_fn_slots = {NULL}, + }; + + /* Note: this is a counter-part to functions: + * 'Gizmo.target_set_prop & target_set_operator' + * (see: rna_wm_gizmo_api.c). conventions should match. */ + static const char *const _keywords[] = {"self", "target", "get", "set", "range", NULL}; + static _PyArg_Parser _parser = {"Os|$OOO:target_set_handler", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + ¶ms.self, + ¶ms.target, + ¶ms.py_fn_slots[BPY_GIZMO_FN_SLOT_GET], + ¶ms.py_fn_slots[BPY_GIZMO_FN_SLOT_SET], + ¶ms.py_fn_slots[BPY_GIZMO_FN_SLOT_RANGE_GET])) { + goto fail; + } + + wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data; + + const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(gz->type, + params.target); + if (gz_prop_type == NULL) { + PyErr_Format(PyExc_ValueError, + "Gizmo target property '%s.%s' not found", + gz->type->idname, + params.target); + goto fail; + } + + { + const int slots_required = 2; + const int slots_start = 2; + for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) { + if (params.py_fn_slots[i] == NULL) { + if (i < slots_required) { + PyErr_Format(PyExc_ValueError, "Argument '%s' not given", _keywords[slots_start + i]); + goto fail; + } + } + else if (!PyCallable_Check(params.py_fn_slots[i])) { + PyErr_Format(PyExc_ValueError, "Argument '%s' not callable", _keywords[slots_start + i]); + goto fail; + } + } + } + + struct BPyGizmoHandlerUserData *data = MEM_callocN(sizeof(*data), __func__); + + for (int i = 0; i < BPY_GIZMO_FN_SLOT_LEN; i++) { + data->fn_slots[i] = params.py_fn_slots[i]; + Py_XINCREF(params.py_fn_slots[i]); + } + + WM_gizmo_target_property_def_func_ptr(gz, + gz_prop_type, + &(const struct wmGizmoPropertyFnParams){ + .value_get_fn = py_rna_gizmo_handler_get_cb, + .value_set_fn = py_rna_gizmo_handler_set_cb, + .range_get_fn = py_rna_gizmo_handler_range_get_cb, + .free_fn = py_rna_gizmo_handler_free_cb, + .user_data = data, + }); + + PyGILState_Release(gilstate); + + Py_RETURN_NONE; fail: - PyGILState_Release(gilstate); - return NULL; + PyGILState_Release(gilstate); + return NULL; } /** \} */ @@ -327,233 +324,222 @@ fail: * \{ */ PyDoc_STRVAR(bpy_gizmo_target_get_value_doc, -".. method:: target_get_value(target):\n" -"\n" -" Get the value of this target property.\n" -"\n" -" :arg target: Target property name.\n" -" :type target: string\n" -" :return: The value of the target property.\n" -" :rtype: Single value or array based on the target type\n" -); + ".. method:: target_get_value(target):\n" + "\n" + " Get the value of this target property.\n" + "\n" + " :arg target: Target property name.\n" + " :type target: string\n" + " :return: The value of the target property.\n" + " :rtype: Single value or array based on the target type\n"); static PyObject *bpy_gizmo_target_get_value(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - struct { - PyObject *self; - char *target; - } params = { - .self = NULL, - .target = NULL, - }; - - static const char * const _keywords[] = {"self", "target", NULL}; - static _PyArg_Parser _parser = {"Os:target_get_value", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - ¶ms.self, - ¶ms.target)) - { - goto fail; - } - - wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data; - - wmGizmoProperty *gz_prop = - WM_gizmo_target_property_find(gz, params.target); - if (gz_prop == NULL) { - PyErr_Format(PyExc_ValueError, - "Gizmo target property '%s.%s' not found", - gz->type->idname, params.target); - goto fail; - } - - const int array_len = WM_gizmo_target_property_array_length(gz, gz_prop); - switch (gz_prop->type->data_type) { - case PROP_FLOAT: - { - if (array_len != 0) { - float *value = BLI_array_alloca(value, array_len); - WM_gizmo_target_property_float_get_array(gz, gz_prop, value); - return PyC_Tuple_PackArray_F32(value, array_len); - } - else { - float value = WM_gizmo_target_property_float_get(gz, gz_prop); - return PyFloat_FromDouble(value); - } - break; - } - default: - { - PyErr_SetString(PyExc_RuntimeError, "Not yet supported type"); - goto fail; - } - } + struct { + PyObject *self; + char *target; + } params = { + .self = NULL, + .target = NULL, + }; + + static const char *const _keywords[] = {"self", "target", NULL}; + static _PyArg_Parser _parser = {"Os:target_get_value", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, ¶ms.self, ¶ms.target)) { + goto fail; + } + + wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data; + + wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, params.target); + if (gz_prop == NULL) { + PyErr_Format(PyExc_ValueError, + "Gizmo target property '%s.%s' not found", + gz->type->idname, + params.target); + goto fail; + } + + const int array_len = WM_gizmo_target_property_array_length(gz, gz_prop); + switch (gz_prop->type->data_type) { + case PROP_FLOAT: { + if (array_len != 0) { + float *value = BLI_array_alloca(value, array_len); + WM_gizmo_target_property_float_get_array(gz, gz_prop, value); + return PyC_Tuple_PackArray_F32(value, array_len); + } + else { + float value = WM_gizmo_target_property_float_get(gz, gz_prop); + return PyFloat_FromDouble(value); + } + break; + } + default: { + PyErr_SetString(PyExc_RuntimeError, "Not yet supported type"); + goto fail; + } + } fail: - return NULL; + return NULL; } PyDoc_STRVAR(bpy_gizmo_target_set_value_doc, -".. method:: target_set_value(target):\n" -"\n" -" Set the value of this target property.\n" -"\n" -" :arg target: Target property name.\n" -" :type target: string\n" -); + ".. method:: target_set_value(target):\n" + "\n" + " Set the value of this target property.\n" + "\n" + " :arg target: Target property name.\n" + " :type target: string\n"); static PyObject *bpy_gizmo_target_set_value(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - struct { - PyObject *self; - char *target; - PyObject *value; - } params = { - .self = NULL, - .target = NULL, - .value = NULL, - }; - - static const char * const _keywords[] = {"self", "target", "value", NULL}; - static _PyArg_Parser _parser = {"OsO:target_set_value", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - ¶ms.self, - ¶ms.target, - ¶ms.value)) - { - goto fail; - } - - wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data; - - wmGizmoProperty *gz_prop = - WM_gizmo_target_property_find(gz, params.target); - if (gz_prop == NULL) { - PyErr_Format(PyExc_ValueError, - "Gizmo target property '%s.%s' not found", - gz->type->idname, params.target); - goto fail; - } - - const int array_len = WM_gizmo_target_property_array_length(gz, gz_prop); - switch (gz_prop->type->data_type) { - case PROP_FLOAT: - { - if (array_len != 0) { - float *value = BLI_array_alloca(value, array_len); - if (PyC_AsArray(value, params.value, gz_prop->type->array_length, &PyFloat_Type, false, - "Gizmo target property array") == -1) - { - goto fail; - } - WM_gizmo_target_property_float_set_array(BPy_GetContext(), gz, gz_prop, value); - } - else { - float value; - if ((value = PyFloat_AsDouble(params.value)) == -1.0f && PyErr_Occurred()) { - goto fail; - } - WM_gizmo_target_property_float_set(BPy_GetContext(), gz, gz_prop, value); - } - Py_RETURN_NONE; - } - default: - { - PyErr_SetString(PyExc_RuntimeError, "Not yet supported type"); - goto fail; - } - } + struct { + PyObject *self; + char *target; + PyObject *value; + } params = { + .self = NULL, + .target = NULL, + .value = NULL, + }; + + static const char *const _keywords[] = {"self", "target", "value", NULL}; + static _PyArg_Parser _parser = {"OsO:target_set_value", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast( + args, kw, &_parser, ¶ms.self, ¶ms.target, ¶ms.value)) { + goto fail; + } + + wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data; + + wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, params.target); + if (gz_prop == NULL) { + PyErr_Format(PyExc_ValueError, + "Gizmo target property '%s.%s' not found", + gz->type->idname, + params.target); + goto fail; + } + + const int array_len = WM_gizmo_target_property_array_length(gz, gz_prop); + switch (gz_prop->type->data_type) { + case PROP_FLOAT: { + if (array_len != 0) { + float *value = BLI_array_alloca(value, array_len); + if (PyC_AsArray(value, + params.value, + gz_prop->type->array_length, + &PyFloat_Type, + false, + "Gizmo target property array") == -1) { + goto fail; + } + WM_gizmo_target_property_float_set_array(BPy_GetContext(), gz, gz_prop, value); + } + else { + float value; + if ((value = PyFloat_AsDouble(params.value)) == -1.0f && PyErr_Occurred()) { + goto fail; + } + WM_gizmo_target_property_float_set(BPy_GetContext(), gz, gz_prop, value); + } + Py_RETURN_NONE; + } + default: { + PyErr_SetString(PyExc_RuntimeError, "Not yet supported type"); + goto fail; + } + } fail: - return NULL; + return NULL; } - PyDoc_STRVAR(bpy_gizmo_target_get_range_doc, -".. method:: target_get_range(target):\n" -"\n" -" Get the range for this target property.\n" -"\n" -" :arg target: Target property name.\n" -" :return: The range of this property (min, max).\n" -" :rtype: tuple pair.\n" -); + ".. method:: target_get_range(target):\n" + "\n" + " Get the range for this target property.\n" + "\n" + " :arg target: Target property name.\n" + " :return: The range of this property (min, max).\n" + " :rtype: tuple pair.\n"); static PyObject *bpy_gizmo_target_get_range(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - struct { - PyObject *self; - char *target; - } params = { - .self = NULL, - .target = NULL, - }; - - static const char * const _keywords[] = {"self", "target", NULL}; - static _PyArg_Parser _parser = {"Os:target_get_range", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - ¶ms.self, - ¶ms.target)) - { - goto fail; - } - - wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data; - - wmGizmoProperty *gz_prop = - WM_gizmo_target_property_find(gz, params.target); - if (gz_prop == NULL) { - PyErr_Format(PyExc_ValueError, - "Gizmo target property '%s.%s' not found", - gz->type->idname, params.target); - goto fail; - } - - switch (gz_prop->type->data_type) { - case PROP_FLOAT: - { - float range[2]; - WM_gizmo_target_property_float_range_get(gz, gz_prop, range); - return PyC_Tuple_PackArray_F32(range, 2); - } - default: - { - PyErr_SetString(PyExc_RuntimeError, "Not yet supported type"); - goto fail; - } - } + struct { + PyObject *self; + char *target; + } params = { + .self = NULL, + .target = NULL, + }; + + static const char *const _keywords[] = {"self", "target", NULL}; + static _PyArg_Parser _parser = {"Os:target_get_range", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, ¶ms.self, ¶ms.target)) { + goto fail; + } + + wmGizmo *gz = ((BPy_StructRNA *)params.self)->ptr.data; + + wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, params.target); + if (gz_prop == NULL) { + PyErr_Format(PyExc_ValueError, + "Gizmo target property '%s.%s' not found", + gz->type->idname, + params.target); + goto fail; + } + + switch (gz_prop->type->data_type) { + case PROP_FLOAT: { + float range[2]; + WM_gizmo_target_property_float_range_get(gz, gz_prop, range); + return PyC_Tuple_PackArray_F32(range, 2); + } + default: { + PyErr_SetString(PyExc_RuntimeError, "Not yet supported type"); + goto fail; + } + } fail: - return NULL; + return NULL; } /** \} */ int BPY_rna_gizmo_module(PyObject *mod_par) { - static PyMethodDef method_def_array[] = { - /* Gizmo Target Property Define API */ - {"target_set_handler", (PyCFunction)bpy_gizmo_target_set_handler, - METH_VARARGS | METH_KEYWORDS, bpy_gizmo_target_set_handler_doc}, - /* Gizmo Target Property Access API */ - {"target_get_value", (PyCFunction)bpy_gizmo_target_get_value, - METH_VARARGS | METH_KEYWORDS, bpy_gizmo_target_get_value_doc}, - {"target_set_value", (PyCFunction)bpy_gizmo_target_set_value, - METH_VARARGS | METH_KEYWORDS, bpy_gizmo_target_set_value_doc}, - {"target_get_range", (PyCFunction)bpy_gizmo_target_get_range, - METH_VARARGS | METH_KEYWORDS, bpy_gizmo_target_get_range_doc}, - /* no sentinel needed. */ - }; - - for (int i = 0; i < ARRAY_SIZE(method_def_array); i++) { - PyMethodDef *m = &method_def_array[i]; - PyObject *func = PyCFunction_New(m, NULL); - PyObject *func_inst = PyInstanceMethod_New(func); - char name_prefix[128]; - PyOS_snprintf(name_prefix, sizeof(name_prefix), "_rna_gizmo_%s", m->ml_name); - /* TODO, return a type that binds nearly to a method. */ - PyModule_AddObject(mod_par, name_prefix, func_inst); - } - - return 0; + static PyMethodDef method_def_array[] = { + /* Gizmo Target Property Define API */ + {"target_set_handler", + (PyCFunction)bpy_gizmo_target_set_handler, + METH_VARARGS | METH_KEYWORDS, + bpy_gizmo_target_set_handler_doc}, + /* Gizmo Target Property Access API */ + {"target_get_value", + (PyCFunction)bpy_gizmo_target_get_value, + METH_VARARGS | METH_KEYWORDS, + bpy_gizmo_target_get_value_doc}, + {"target_set_value", + (PyCFunction)bpy_gizmo_target_set_value, + METH_VARARGS | METH_KEYWORDS, + bpy_gizmo_target_set_value_doc}, + {"target_get_range", + (PyCFunction)bpy_gizmo_target_get_range, + METH_VARARGS | METH_KEYWORDS, + bpy_gizmo_target_get_range_doc}, + /* no sentinel needed. */ + }; + + for (int i = 0; i < ARRAY_SIZE(method_def_array); i++) { + PyMethodDef *m = &method_def_array[i]; + PyObject *func = PyCFunction_New(m, NULL); + PyObject *func_inst = PyInstanceMethod_New(func); + char name_prefix[128]; + PyOS_snprintf(name_prefix, sizeof(name_prefix), "_rna_gizmo_%s", m->ml_name); + /* TODO, return a type that binds nearly to a method. */ + PyModule_AddObject(mod_par, name_prefix, func_inst); + } + + return 0; } diff --git a/source/blender/python/intern/bpy_rna_gizmo.h b/source/blender/python/intern/bpy_rna_gizmo.h index 2eb02008eb1..293ab38a6ab 100644 --- a/source/blender/python/intern/bpy_rna_gizmo.h +++ b/source/blender/python/intern/bpy_rna_gizmo.h @@ -23,4 +23,4 @@ int BPY_rna_gizmo_module(PyObject *); -#endif /* __BPY_RNA_GIZMO_H__ */ +#endif /* __BPY_RNA_GIZMO_H__ */ diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c index 7a5849f818d..bb7604aea97 100644 --- a/source/blender/python/intern/bpy_rna_id_collection.c +++ b/source/blender/python/intern/bpy_rna_id_collection.c @@ -54,336 +54,337 @@ #include "bpy_rna.h" typedef struct IDUserMapData { - /* place-holder key only used for lookups to avoid creating new data only for lookups - * (never return its contents) */ - PyObject *py_id_key_lookup_only; + /* place-holder key only used for lookups to avoid creating new data only for lookups + * (never return its contents) */ + PyObject *py_id_key_lookup_only; - /* we loop over data-blocks that this ID points to (do build a reverse lookup table) */ - PyObject *py_id_curr; - ID *id_curr; + /* we loop over data-blocks that this ID points to (do build a reverse lookup table) */ + PyObject *py_id_curr; + ID *id_curr; - /* filter the values we add into the set */ - BLI_bitmap *types_bitmap; + /* filter the values we add into the set */ + BLI_bitmap *types_bitmap; - PyObject *user_map; /* set to fill in as we iterate */ - bool is_subset; /* true when we're only mapping a subset of all the ID's (subset arg is passed) */ + PyObject *user_map; /* set to fill in as we iterate */ + bool + is_subset; /* true when we're only mapping a subset of all the ID's (subset arg is passed) */ } IDUserMapData; - static int id_code_as_index(const short idcode) { - return (int)*((unsigned short *)&idcode); + return (int)*((unsigned short *)&idcode); } static bool id_check_type(const ID *id, const BLI_bitmap *types_bitmap) { - return BLI_BITMAP_TEST_BOOL(types_bitmap, id_code_as_index(GS(id->name))); + return BLI_BITMAP_TEST_BOOL(types_bitmap, id_code_as_index(GS(id->name))); } -static int foreach_libblock_id_user_map_callback( - void *user_data, ID *self_id, ID **id_p, int UNUSED(cb_flag)) +static int foreach_libblock_id_user_map_callback(void *user_data, + ID *self_id, + ID **id_p, + int UNUSED(cb_flag)) { - IDUserMapData *data = user_data; - - if (*id_p) { - - if (data->types_bitmap) { - if (!id_check_type(*id_p, data->types_bitmap)) { - return IDWALK_RET_NOP; - } - } - - if ((GS(self_id->name) == ID_OB) && (id_p == (ID **)&((Object *)self_id)->proxy_from)) { - /* We skip proxy_from here, since it's some internal pointer which is not relevant info for py/API level. */ - return IDWALK_RET_NOP; - } - else if ((GS(self_id->name) == ID_KE) && (id_p == (ID **)&((Key *)self_id)->from)) { - /* We skip from here, since it's some internal pointer which is not relevant info for py/API level. */ - return IDWALK_RET_NOP; - } - - /* pyrna_struct_hash() uses ptr.data only, - * but pyrna_struct_richcmp() uses also ptr.type, - * so we need to create a valid PointerRNA here... - */ - PyObject *key = data->py_id_key_lookup_only; - RNA_id_pointer_create(*id_p, &((BPy_StructRNA *)key)->ptr); - - PyObject *set; - if ((set = PyDict_GetItem(data->user_map, key)) == NULL) { - - /* limit to key's added already */ - if (data->is_subset) { - return IDWALK_RET_NOP; - } - - /* Cannot use our placeholder key here! */ - key = pyrna_id_CreatePyObject(*id_p); - set = PySet_New(NULL); - PyDict_SetItem(data->user_map, key, set); - Py_DECREF(set); - Py_DECREF(key); - } - - if (data->py_id_curr == NULL) { - data->py_id_curr = pyrna_id_CreatePyObject(data->id_curr); - } - - PySet_Add(set, data->py_id_curr); - } - - return IDWALK_RET_NOP; + IDUserMapData *data = user_data; + + if (*id_p) { + + if (data->types_bitmap) { + if (!id_check_type(*id_p, data->types_bitmap)) { + return IDWALK_RET_NOP; + } + } + + if ((GS(self_id->name) == ID_OB) && (id_p == (ID **)&((Object *)self_id)->proxy_from)) { + /* We skip proxy_from here, since it's some internal pointer which is not relevant info for py/API level. */ + return IDWALK_RET_NOP; + } + else if ((GS(self_id->name) == ID_KE) && (id_p == (ID **)&((Key *)self_id)->from)) { + /* We skip from here, since it's some internal pointer which is not relevant info for py/API level. */ + return IDWALK_RET_NOP; + } + + /* pyrna_struct_hash() uses ptr.data only, + * but pyrna_struct_richcmp() uses also ptr.type, + * so we need to create a valid PointerRNA here... + */ + PyObject *key = data->py_id_key_lookup_only; + RNA_id_pointer_create(*id_p, &((BPy_StructRNA *)key)->ptr); + + PyObject *set; + if ((set = PyDict_GetItem(data->user_map, key)) == NULL) { + + /* limit to key's added already */ + if (data->is_subset) { + return IDWALK_RET_NOP; + } + + /* Cannot use our placeholder key here! */ + key = pyrna_id_CreatePyObject(*id_p); + set = PySet_New(NULL); + PyDict_SetItem(data->user_map, key, set); + Py_DECREF(set); + Py_DECREF(key); + } + + if (data->py_id_curr == NULL) { + data->py_id_curr = pyrna_id_CreatePyObject(data->id_curr); + } + + PySet_Add(set, data->py_id_curr); + } + + return IDWALK_RET_NOP; } PyDoc_STRVAR(bpy_user_map_doc, -".. method:: user_map([subset=(id1, id2, ...)], key_types={..}, value_types={..})\n" -"\n" -" Returns a mapping of all ID datablocks in current ``bpy.data`` to a set of all datablocks using them.\n" -"\n" -" For list of valid set members for key_types & value_types, see: :class:`bpy.types.KeyingSetPath.id_type`.\n" -"\n" -" :arg subset: When passed, only these data-blocks and their users will be included as keys/values in the map.\n" -" :type subset: sequence\n" -" :arg key_types: Filter the keys mapped by ID types.\n" -" :type key_types: set of strings\n" -" :arg value_types: Filter the values in the set by ID types.\n" -" :type value_types: set of strings\n" -" :return: dictionary of :class:`bpy.types.ID` instances, with sets of ID's as their values.\n" -" :rtype: dict\n" -); + ".. method:: user_map([subset=(id1, id2, ...)], key_types={..}, value_types={..})\n" + "\n" + " Returns a mapping of all ID datablocks in current ``bpy.data`` to a set of all " + "datablocks using them.\n" + "\n" + " For list of valid set members for key_types & value_types, see: " + ":class:`bpy.types.KeyingSetPath.id_type`.\n" + "\n" + " :arg subset: When passed, only these data-blocks and their users will be " + "included as keys/values in the map.\n" + " :type subset: sequence\n" + " :arg key_types: Filter the keys mapped by ID types.\n" + " :type key_types: set of strings\n" + " :arg value_types: Filter the values in the set by ID types.\n" + " :type value_types: set of strings\n" + " :return: dictionary of :class:`bpy.types.ID` instances, with sets of ID's as " + "their values.\n" + " :rtype: dict\n"); static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *kwds) { -#if 0 /* If someone knows how to get a proper 'self' in that case... */ - BPy_StructRNA *pyrna = (BPy_StructRNA *)self; - Main *bmain = pyrna->ptr.data; +#if 0 /* If someone knows how to get a proper 'self' in that case... */ + BPy_StructRNA *pyrna = (BPy_StructRNA *)self; + Main *bmain = pyrna->ptr.data; #else - Main *bmain = G_MAIN; /* XXX Ugly, but should work! */ + Main *bmain = G_MAIN; /* XXX Ugly, but should work! */ #endif - ListBase *lb; - ID *id; - - PyObject *subset = NULL; - - PyObject *key_types = NULL; - PyObject *val_types = NULL; - BLI_bitmap *key_types_bitmap = NULL; - BLI_bitmap *val_types_bitmap = NULL; - - PyObject *ret = NULL; - - IDUserMapData data_cb = {NULL}; - - static const char *_keywords[] = {"subset", "key_types", "value_types", NULL}; - static _PyArg_Parser _parser = {"|O$O!O!:user_map", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kwds, &_parser, - &subset, - &PySet_Type, &key_types, - &PySet_Type, &val_types)) - { - return NULL; - } - - if (key_types) { - key_types_bitmap = pyrna_set_to_enum_bitmap( - rna_enum_id_type_items, key_types, sizeof(short), true, USHRT_MAX, "key types"); - if (key_types_bitmap == NULL) { - goto error; - } - } - - if (val_types) { - val_types_bitmap = pyrna_set_to_enum_bitmap( - rna_enum_id_type_items, val_types, sizeof(short), true, USHRT_MAX, "value types"); - if (val_types_bitmap == NULL) { - goto error; - } - } - - if (subset) { - PyObject *subset_fast = PySequence_Fast(subset, "user_map"); - if (subset_fast == NULL) { - goto error; - } - - PyObject **subset_array = PySequence_Fast_ITEMS(subset_fast); - Py_ssize_t subset_len = PySequence_Fast_GET_SIZE(subset_fast); - - data_cb.user_map = _PyDict_NewPresized(subset_len); - data_cb.is_subset = true; - for (; subset_len; subset_array++, subset_len--) { - PyObject *set = PySet_New(NULL); - PyDict_SetItem(data_cb.user_map, *subset_array, set); - Py_DECREF(set); - } - Py_DECREF(subset_fast); - } - else { - data_cb.user_map = PyDict_New(); - } - - data_cb.types_bitmap = key_types_bitmap; - - FOREACH_MAIN_LISTBASE_BEGIN(bmain, lb) - { - FOREACH_MAIN_LISTBASE_ID_BEGIN(lb, id) - { - /* We cannot skip here in case we have some filter on key types... */ - if (key_types_bitmap == NULL && val_types_bitmap != NULL) { - if (!id_check_type(id, val_types_bitmap)) { - break; - } - } - - /* One-time init, ID is just used as placeholder here, we abuse this in iterator callback - * to avoid having to rebuild a complete bpyrna object each time for the key searching - * (where only ID pointer value is used). */ - if (data_cb.py_id_key_lookup_only == NULL) { - data_cb.py_id_key_lookup_only = pyrna_id_CreatePyObject(id); - } - - if (!data_cb.is_subset && - /* We do not want to pre-add keys of flitered out types. */ - (key_types_bitmap == NULL || id_check_type(id, key_types_bitmap)) && - /* We do not want to pre-add keys when we have filter on value types, but not on key types. */ - (val_types_bitmap == NULL || key_types_bitmap != NULL)) - { - PyObject *key = data_cb.py_id_key_lookup_only; - PyObject *set; - - RNA_id_pointer_create(id, &((BPy_StructRNA *)key)->ptr); - - /* We have to insert the key now, otherwise ID unused would be missing from final dict... */ - if ((set = PyDict_GetItem(data_cb.user_map, key)) == NULL) { - /* Cannot use our placeholder key here! */ - key = pyrna_id_CreatePyObject(id); - set = PySet_New(NULL); - PyDict_SetItem(data_cb.user_map, key, set); - Py_DECREF(set); - Py_DECREF(key); - } - } - - if (val_types_bitmap != NULL && !id_check_type(id, val_types_bitmap)) { - continue; - } - - data_cb.id_curr = id; - BKE_library_foreach_ID_link(NULL, id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_CB_NOP); - - if (data_cb.py_id_curr) { - Py_DECREF(data_cb.py_id_curr); - data_cb.py_id_curr = NULL; - } - } - FOREACH_MAIN_LISTBASE_ID_END; - } - FOREACH_MAIN_LISTBASE_ID_END; - - ret = data_cb.user_map; + ListBase *lb; + ID *id; + + PyObject *subset = NULL; + + PyObject *key_types = NULL; + PyObject *val_types = NULL; + BLI_bitmap *key_types_bitmap = NULL; + BLI_bitmap *val_types_bitmap = NULL; + + PyObject *ret = NULL; + + IDUserMapData data_cb = {NULL}; + + static const char *_keywords[] = {"subset", "key_types", "value_types", NULL}; + static _PyArg_Parser _parser = {"|O$O!O!:user_map", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast( + args, kwds, &_parser, &subset, &PySet_Type, &key_types, &PySet_Type, &val_types)) { + return NULL; + } + + if (key_types) { + key_types_bitmap = pyrna_set_to_enum_bitmap( + rna_enum_id_type_items, key_types, sizeof(short), true, USHRT_MAX, "key types"); + if (key_types_bitmap == NULL) { + goto error; + } + } + + if (val_types) { + val_types_bitmap = pyrna_set_to_enum_bitmap( + rna_enum_id_type_items, val_types, sizeof(short), true, USHRT_MAX, "value types"); + if (val_types_bitmap == NULL) { + goto error; + } + } + + if (subset) { + PyObject *subset_fast = PySequence_Fast(subset, "user_map"); + if (subset_fast == NULL) { + goto error; + } + + PyObject **subset_array = PySequence_Fast_ITEMS(subset_fast); + Py_ssize_t subset_len = PySequence_Fast_GET_SIZE(subset_fast); + + data_cb.user_map = _PyDict_NewPresized(subset_len); + data_cb.is_subset = true; + for (; subset_len; subset_array++, subset_len--) { + PyObject *set = PySet_New(NULL); + PyDict_SetItem(data_cb.user_map, *subset_array, set); + Py_DECREF(set); + } + Py_DECREF(subset_fast); + } + else { + data_cb.user_map = PyDict_New(); + } + + data_cb.types_bitmap = key_types_bitmap; + + FOREACH_MAIN_LISTBASE_BEGIN(bmain, lb) + { + FOREACH_MAIN_LISTBASE_ID_BEGIN(lb, id) + { + /* We cannot skip here in case we have some filter on key types... */ + if (key_types_bitmap == NULL && val_types_bitmap != NULL) { + if (!id_check_type(id, val_types_bitmap)) { + break; + } + } + + /* One-time init, ID is just used as placeholder here, we abuse this in iterator callback + * to avoid having to rebuild a complete bpyrna object each time for the key searching + * (where only ID pointer value is used). */ + if (data_cb.py_id_key_lookup_only == NULL) { + data_cb.py_id_key_lookup_only = pyrna_id_CreatePyObject(id); + } + + if (!data_cb.is_subset && + /* We do not want to pre-add keys of flitered out types. */ + (key_types_bitmap == NULL || id_check_type(id, key_types_bitmap)) && + /* We do not want to pre-add keys when we have filter on value types, but not on key types. */ + (val_types_bitmap == NULL || key_types_bitmap != NULL)) { + PyObject *key = data_cb.py_id_key_lookup_only; + PyObject *set; + + RNA_id_pointer_create(id, &((BPy_StructRNA *)key)->ptr); + + /* We have to insert the key now, otherwise ID unused would be missing from final dict... */ + if ((set = PyDict_GetItem(data_cb.user_map, key)) == NULL) { + /* Cannot use our placeholder key here! */ + key = pyrna_id_CreatePyObject(id); + set = PySet_New(NULL); + PyDict_SetItem(data_cb.user_map, key, set); + Py_DECREF(set); + Py_DECREF(key); + } + } + + if (val_types_bitmap != NULL && !id_check_type(id, val_types_bitmap)) { + continue; + } + + data_cb.id_curr = id; + BKE_library_foreach_ID_link( + NULL, id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_CB_NOP); + + if (data_cb.py_id_curr) { + Py_DECREF(data_cb.py_id_curr); + data_cb.py_id_curr = NULL; + } + } + FOREACH_MAIN_LISTBASE_ID_END; + } + FOREACH_MAIN_LISTBASE_ID_END; + + ret = data_cb.user_map; error: - if (data_cb.py_id_key_lookup_only != NULL) { - Py_XDECREF(data_cb.py_id_key_lookup_only); - } + if (data_cb.py_id_key_lookup_only != NULL) { + Py_XDECREF(data_cb.py_id_key_lookup_only); + } - if (key_types_bitmap != NULL) { - MEM_freeN(key_types_bitmap); - } + if (key_types_bitmap != NULL) { + MEM_freeN(key_types_bitmap); + } - if (val_types_bitmap != NULL) { - MEM_freeN(val_types_bitmap); - } + if (val_types_bitmap != NULL) { + MEM_freeN(val_types_bitmap); + } - return ret; + return ret; } PyDoc_STRVAR(bpy_batch_remove_doc, -".. method:: batch_remove(ids=(id1, id2, ...))\n" -"\n" -" Remove (delete) several IDs at once.\n" -"\n" -" WARNING: Considered experimental feature currently.\n" -"\n" -" Note that this function is quicker than individual calls to :func:`remove()` (from :class:`bpy.types.BlendData`\n" -" ID collections), but less safe/versatile (it can break Blender, e.g. by removing all scenes...).\n" -"\n" -" :arg ids: Iterables of IDs (types can be mixed).\n" -" :type subset: sequence\n" -); + ".. method:: batch_remove(ids=(id1, id2, ...))\n" + "\n" + " Remove (delete) several IDs at once.\n" + "\n" + " WARNING: Considered experimental feature currently.\n" + "\n" + " Note that this function is quicker than individual calls to :func:`remove()` " + "(from :class:`bpy.types.BlendData`\n" + " ID collections), but less safe/versatile (it can break Blender, e.g. by removing " + "all scenes...).\n" + "\n" + " :arg ids: Iterables of IDs (types can be mixed).\n" + " :type subset: sequence\n"); static PyObject *bpy_batch_remove(PyObject *UNUSED(self), PyObject *args, PyObject *kwds) { -#if 0 /* If someone knows how to get a proper 'self' in that case... */ - BPy_StructRNA *pyrna = (BPy_StructRNA *)self; - Main *bmain = pyrna->ptr.data; +#if 0 /* If someone knows how to get a proper 'self' in that case... */ + BPy_StructRNA *pyrna = (BPy_StructRNA *)self; + Main *bmain = pyrna->ptr.data; #else - Main *bmain = G_MAIN; /* XXX Ugly, but should work! */ + Main *bmain = G_MAIN; /* XXX Ugly, but should work! */ #endif - PyObject *ids = NULL; - - PyObject *ret = NULL; - - static const char *_keywords[] = {"ids", NULL}; - static _PyArg_Parser _parser = {"O:user_map", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kwds, &_parser, - &ids)) - { - return ret; - } - - if (ids) { - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - - PyObject *ids_fast = PySequence_Fast(ids, "batch_remove"); - if (ids_fast == NULL) { - goto error; - } - - PyObject **ids_array = PySequence_Fast_ITEMS(ids_fast); - Py_ssize_t ids_len = PySequence_Fast_GET_SIZE(ids_fast); - - for (; ids_len; ids_array++, ids_len--) { - ID *id; - if (!pyrna_id_FromPyObject(*ids_array, &id)) { - PyErr_Format(PyExc_TypeError, - "Expected an ID type, not %.200s", - Py_TYPE(*ids_array)->tp_name); - Py_DECREF(ids_fast); - goto error; - } - - id->tag |= LIB_TAG_DOIT; - } - Py_DECREF(ids_fast); - - BKE_id_multi_tagged_delete(bmain); - /* Force full redraw, mandatory to avoid crashes when running this from UI... */ - WM_main_add_notifier(NC_WINDOW, NULL); - } - else { - goto error; - } - - Py_INCREF(Py_None); - ret = Py_None; + PyObject *ids = NULL; + + PyObject *ret = NULL; + + static const char *_keywords[] = {"ids", NULL}; + static _PyArg_Parser _parser = {"O:user_map", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &ids)) { + return ret; + } + + if (ids) { + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + + PyObject *ids_fast = PySequence_Fast(ids, "batch_remove"); + if (ids_fast == NULL) { + goto error; + } + + PyObject **ids_array = PySequence_Fast_ITEMS(ids_fast); + Py_ssize_t ids_len = PySequence_Fast_GET_SIZE(ids_fast); + + for (; ids_len; ids_array++, ids_len--) { + ID *id; + if (!pyrna_id_FromPyObject(*ids_array, &id)) { + PyErr_Format( + PyExc_TypeError, "Expected an ID type, not %.200s", Py_TYPE(*ids_array)->tp_name); + Py_DECREF(ids_fast); + goto error; + } + + id->tag |= LIB_TAG_DOIT; + } + Py_DECREF(ids_fast); + + BKE_id_multi_tagged_delete(bmain); + /* Force full redraw, mandatory to avoid crashes when running this from UI... */ + WM_main_add_notifier(NC_WINDOW, NULL); + } + else { + goto error; + } + + Py_INCREF(Py_None); + ret = Py_None; error: - return ret; + return ret; } int BPY_rna_id_collection_module(PyObject *mod_par) { - static PyMethodDef user_map = { - "user_map", (PyCFunction)bpy_user_map, METH_VARARGS | METH_KEYWORDS, bpy_user_map_doc}; + static PyMethodDef user_map = { + "user_map", (PyCFunction)bpy_user_map, METH_VARARGS | METH_KEYWORDS, bpy_user_map_doc}; - PyModule_AddObject(mod_par, "_rna_id_collection_user_map", PyCFunction_New(&user_map, NULL)); + PyModule_AddObject(mod_par, "_rna_id_collection_user_map", PyCFunction_New(&user_map, NULL)); - static PyMethodDef batch_remove = { - "batch_remove", (PyCFunction)bpy_batch_remove, METH_VARARGS | METH_KEYWORDS, bpy_batch_remove_doc}; + static PyMethodDef batch_remove = {"batch_remove", + (PyCFunction)bpy_batch_remove, + METH_VARARGS | METH_KEYWORDS, + bpy_batch_remove_doc}; - PyModule_AddObject(mod_par, "_rna_id_collection_batch_remove", PyCFunction_New(&batch_remove, NULL)); + PyModule_AddObject( + mod_par, "_rna_id_collection_batch_remove", PyCFunction_New(&batch_remove, NULL)); - return 0; + return 0; } diff --git a/source/blender/python/intern/bpy_rna_id_collection.h b/source/blender/python/intern/bpy_rna_id_collection.h index b66629fc790..8cb375960a9 100644 --- a/source/blender/python/intern/bpy_rna_id_collection.h +++ b/source/blender/python/intern/bpy_rna_id_collection.h @@ -23,4 +23,4 @@ int BPY_rna_id_collection_module(PyObject *); -#endif /* __BPY_RNA_ID_COLLECTION_H__ */ +#endif /* __BPY_RNA_ID_COLLECTION_H__ */ diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c index 77cd8d8a9b7..c9c9e4adafb 100644 --- a/source/blender/python/intern/bpy_traceback.c +++ b/source/blender/python/intern/bpy_traceback.c @@ -21,167 +21,170 @@ * trace. */ - #include <Python.h> #include <frameobject.h> #include "BLI_utildefines.h" #include "BLI_path_util.h" #ifdef WIN32 -# include "BLI_string.h" /* BLI_strcasecmp */ +# include "BLI_string.h" /* BLI_strcasecmp */ #endif #include "bpy_traceback.h" static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce) { - return PyBytes_AS_STRING((*coerce = PyUnicode_EncodeFSDefault(tb->tb_frame->f_code->co_filename))); + return PyBytes_AS_STRING( + (*coerce = PyUnicode_EncodeFSDefault(tb->tb_frame->f_code->co_filename))); } /* copied from pythonrun.c, 3.4.0 */ _Py_static_string(PyId_string, "<string>"); -static int -parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename, - int *lineno, int *offset, PyObject **text) +static int parse_syntax_error(PyObject *err, + PyObject **message, + PyObject **filename, + int *lineno, + int *offset, + PyObject **text) { - long hold; - PyObject *v; - _Py_IDENTIFIER(msg); - _Py_IDENTIFIER(filename); - _Py_IDENTIFIER(lineno); - _Py_IDENTIFIER(offset); - _Py_IDENTIFIER(text); - - *message = NULL; - *filename = NULL; - - /* new style errors. `err' is an instance */ - *message = _PyObject_GetAttrId(err, &PyId_msg); - if (!*message) { - goto finally; - } - - v = _PyObject_GetAttrId(err, &PyId_filename); - if (!v) { - goto finally; - } - if (v == Py_None) { - Py_DECREF(v); - *filename = _PyUnicode_FromId(&PyId_string); - if (*filename == NULL) { - goto finally; - } - Py_INCREF(*filename); - } - else { - *filename = v; - } - - v = _PyObject_GetAttrId(err, &PyId_lineno); - if (!v) { - goto finally; - } - hold = PyLong_AsLong(v); - Py_DECREF(v); - if (hold < 0 && PyErr_Occurred()) { - goto finally; - } - *lineno = (int)hold; - - v = _PyObject_GetAttrId(err, &PyId_offset); - if (!v) { - goto finally; - } - if (v == Py_None) { - *offset = -1; - Py_DECREF(v); - } else { - hold = PyLong_AsLong(v); - Py_DECREF(v); - if (hold < 0 && PyErr_Occurred()) { - goto finally; - } - *offset = (int)hold; - } - - v = _PyObject_GetAttrId(err, &PyId_text); - if (!v) { - goto finally; - } - if (v == Py_None) { - Py_DECREF(v); - *text = NULL; - } - else { - *text = v; - } - return 1; + long hold; + PyObject *v; + _Py_IDENTIFIER(msg); + _Py_IDENTIFIER(filename); + _Py_IDENTIFIER(lineno); + _Py_IDENTIFIER(offset); + _Py_IDENTIFIER(text); + + *message = NULL; + *filename = NULL; + + /* new style errors. `err' is an instance */ + *message = _PyObject_GetAttrId(err, &PyId_msg); + if (!*message) { + goto finally; + } + + v = _PyObject_GetAttrId(err, &PyId_filename); + if (!v) { + goto finally; + } + if (v == Py_None) { + Py_DECREF(v); + *filename = _PyUnicode_FromId(&PyId_string); + if (*filename == NULL) { + goto finally; + } + Py_INCREF(*filename); + } + else { + *filename = v; + } + + v = _PyObject_GetAttrId(err, &PyId_lineno); + if (!v) { + goto finally; + } + hold = PyLong_AsLong(v); + Py_DECREF(v); + if (hold < 0 && PyErr_Occurred()) { + goto finally; + } + *lineno = (int)hold; + + v = _PyObject_GetAttrId(err, &PyId_offset); + if (!v) { + goto finally; + } + if (v == Py_None) { + *offset = -1; + Py_DECREF(v); + } + else { + hold = PyLong_AsLong(v); + Py_DECREF(v); + if (hold < 0 && PyErr_Occurred()) { + goto finally; + } + *offset = (int)hold; + } + + v = _PyObject_GetAttrId(err, &PyId_text); + if (!v) { + goto finally; + } + if (v == Py_None) { + Py_DECREF(v); + *text = NULL; + } + else { + *text = v; + } + return 1; finally: - Py_XDECREF(*message); - Py_XDECREF(*filename); - return 0; + Py_XDECREF(*message); + Py_XDECREF(*filename); + return 0; } /* end copied function! */ - void python_script_error_jump(const char *filepath, int *lineno, int *offset) { - PyObject *exception, *value; - PyTracebackObject *tb; - - *lineno = -1; - *offset = 0; - - PyErr_Fetch(&exception, &value, (PyObject **)&tb); - - if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { - /* no traceback available when SyntaxError. - * python has no api's to this. reference parse_syntax_error() from pythonrun.c */ - PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); - PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ - - if (value) { /* should always be true */ - PyObject *message; - PyObject *filename_py, *text_py; - - if (parse_syntax_error(value, &message, &filename_py, lineno, offset, &text_py)) { - const char *filename = _PyUnicode_AsString(filename_py); - /* python adds a '/', prefix, so check for both */ - if ((BLI_path_cmp(filename, filepath) == 0) || - ((filename[0] == '\\' || filename[0] == '/') && BLI_path_cmp(filename + 1, filepath) == 0)) - { - /* good */ - } - else { - *lineno = -1; - } - } - else { - *lineno = -1; - } - } - } - else { - PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); - PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ - PyErr_Print(); - - for (tb = (PyTracebackObject *)PySys_GetObject("last_traceback"); - tb && (PyObject *)tb != Py_None; - tb = tb->tb_next) - { - PyObject *coerce; - const char *tb_filepath = traceback_filepath(tb, &coerce); - const int match = ((BLI_path_cmp(tb_filepath, filepath) == 0) || - ((tb_filepath[0] == '\\' || tb_filepath[0] == '/') && BLI_path_cmp(tb_filepath + 1, filepath) == 0)); - Py_DECREF(coerce); - - if (match) { - *lineno = tb->tb_lineno; - /* used to break here, but better find the inner most line */ - } - } - } + PyObject *exception, *value; + PyTracebackObject *tb; + + *lineno = -1; + *offset = 0; + + PyErr_Fetch(&exception, &value, (PyObject **)&tb); + + if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { + /* no traceback available when SyntaxError. + * python has no api's to this. reference parse_syntax_error() from pythonrun.c */ + PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); + PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ + + if (value) { /* should always be true */ + PyObject *message; + PyObject *filename_py, *text_py; + + if (parse_syntax_error(value, &message, &filename_py, lineno, offset, &text_py)) { + const char *filename = _PyUnicode_AsString(filename_py); + /* python adds a '/', prefix, so check for both */ + if ((BLI_path_cmp(filename, filepath) == 0) || + ((filename[0] == '\\' || filename[0] == '/') && + BLI_path_cmp(filename + 1, filepath) == 0)) { + /* good */ + } + else { + *lineno = -1; + } + } + else { + *lineno = -1; + } + } + } + else { + PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); + PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ + PyErr_Print(); + + for (tb = (PyTracebackObject *)PySys_GetObject("last_traceback"); + tb && (PyObject *)tb != Py_None; + tb = tb->tb_next) { + PyObject *coerce; + const char *tb_filepath = traceback_filepath(tb, &coerce); + const int match = ((BLI_path_cmp(tb_filepath, filepath) == 0) || + ((tb_filepath[0] == '\\' || tb_filepath[0] == '/') && + BLI_path_cmp(tb_filepath + 1, filepath) == 0)); + Py_DECREF(coerce); + + if (match) { + *lineno = tb->tb_lineno; + /* used to break here, but better find the inner most line */ + } + } + } } diff --git a/source/blender/python/intern/bpy_traceback.h b/source/blender/python/intern/bpy_traceback.h index 118b594b6d9..11295706240 100644 --- a/source/blender/python/intern/bpy_traceback.h +++ b/source/blender/python/intern/bpy_traceback.h @@ -18,10 +18,9 @@ * \ingroup pythonintern */ - #ifndef __BPY_TRACEBACK_H__ #define __BPY_TRACEBACK_H__ void python_script_error_jump(const char *filepath, int *lineno, int *offset); -#endif /* __BPY_TRACEBACK_H__ */ +#endif /* __BPY_TRACEBACK_H__ */ diff --git a/source/blender/python/intern/bpy_utils_previews.c b/source/blender/python/intern/bpy_utils_previews.c index 338e915780d..7423e55d253 100644 --- a/source/blender/python/intern/bpy_utils_previews.c +++ b/source/blender/python/intern/bpy_utils_previews.c @@ -50,133 +50,140 @@ #define STR_SOURCE_TYPES "'IMAGE', 'MOVIE', 'BLEND', 'FONT'" PyDoc_STRVAR(bpy_utils_previews_new_doc, -".. method:: new(name)\n" -"\n" -" Generate a new empty preview, or return existing one matching ``name``.\n" -"\n" -" :arg name: The name (unique id) identifying the preview.\n" -" :type name: string\n" -" :return: The Preview matching given name, or a new empty one.\n" -" :rtype: :class:`bpy.types.ImagePreview`\n" -); + ".. method:: new(name)\n" + "\n" + " Generate a new empty preview, or return existing one matching ``name``.\n" + "\n" + " :arg name: The name (unique id) identifying the preview.\n" + " :type name: string\n" + " :return: The Preview matching given name, or a new empty one.\n" + " :rtype: :class:`bpy.types.ImagePreview`\n"); static PyObject *bpy_utils_previews_new(PyObject *UNUSED(self), PyObject *args) { - char *name; - PreviewImage *prv; - PointerRNA ptr; + char *name; + PreviewImage *prv; + PointerRNA ptr; - if (!PyArg_ParseTuple(args, "s:new", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:new", &name)) { + return NULL; + } - prv = BKE_previewimg_cached_ensure(name); - RNA_pointer_create(NULL, &RNA_ImagePreview, prv, &ptr); + prv = BKE_previewimg_cached_ensure(name); + RNA_pointer_create(NULL, &RNA_ImagePreview, prv, &ptr); - return pyrna_struct_CreatePyObject(&ptr); + return pyrna_struct_CreatePyObject(&ptr); } -PyDoc_STRVAR(bpy_utils_previews_load_doc, -".. method:: load(name, filepath, filetype, force_reload=False)\n" -"\n" -" Generate a new preview from given file path, or return existing one matching ``name``.\n" -"\n" -" :arg name: The name (unique id) identifying the preview.\n" -" :type name: string\n" -" :arg filepath: The file path to generate the preview from.\n" -" :type filepath: string\n" -" :arg filetype: The type of file, needed to generate the preview in [" STR_SOURCE_TYPES "].\n" -" :type filetype: string\n" -" :arg force_reload: If True, force running thumbnail manager even if preview already exists in cache.\n" -" :type force_reload: bool\n" -" :return: The Preview matching given name, or a new empty one.\n" -" :rtype: :class:`bpy.types.ImagePreview`\n" -); +PyDoc_STRVAR( + bpy_utils_previews_load_doc, + ".. method:: load(name, filepath, filetype, force_reload=False)\n" + "\n" + " Generate a new preview from given file path, or return existing one matching ``name``.\n" + "\n" + " :arg name: The name (unique id) identifying the preview.\n" + " :type name: string\n" + " :arg filepath: The file path to generate the preview from.\n" + " :type filepath: string\n" + " :arg filetype: The type of file, needed to generate the preview in [" STR_SOURCE_TYPES + "].\n" + " :type filetype: string\n" + " :arg force_reload: If True, force running thumbnail manager even if preview already " + "exists in cache.\n" + " :type force_reload: bool\n" + " :return: The Preview matching given name, or a new empty one.\n" + " :rtype: :class:`bpy.types.ImagePreview`\n"); static PyObject *bpy_utils_previews_load(PyObject *UNUSED(self), PyObject *args) { - char *name, *path, *path_type_s; - int path_type, force_reload = false; - - PreviewImage *prv; - PointerRNA ptr; - - if (!PyArg_ParseTuple( args, "sss|p:load", &name, &path, &path_type_s, &force_reload)) { - return NULL; - } - - if (STREQ(path_type_s, "IMAGE")) { - path_type = THB_SOURCE_IMAGE; - } - else if (STREQ(path_type_s, "MOVIE")) { - path_type = THB_SOURCE_MOVIE; - } - else if (STREQ(path_type_s, "BLEND")) { - path_type = THB_SOURCE_BLEND; - } - else if (STREQ(path_type_s, "FONT")) { - path_type = THB_SOURCE_FONT; - } - else { - PyErr_Format(PyExc_ValueError, - "load: invalid '%s' filetype, only [" STR_SOURCE_TYPES "] " - "are supported", path_type_s); - return NULL; - } - - prv = BKE_previewimg_cached_thumbnail_read(name, path, path_type, force_reload); - RNA_pointer_create(NULL, &RNA_ImagePreview, prv, &ptr); - - return pyrna_struct_CreatePyObject(&ptr); + char *name, *path, *path_type_s; + int path_type, force_reload = false; + + PreviewImage *prv; + PointerRNA ptr; + + if (!PyArg_ParseTuple(args, "sss|p:load", &name, &path, &path_type_s, &force_reload)) { + return NULL; + } + + if (STREQ(path_type_s, "IMAGE")) { + path_type = THB_SOURCE_IMAGE; + } + else if (STREQ(path_type_s, "MOVIE")) { + path_type = THB_SOURCE_MOVIE; + } + else if (STREQ(path_type_s, "BLEND")) { + path_type = THB_SOURCE_BLEND; + } + else if (STREQ(path_type_s, "FONT")) { + path_type = THB_SOURCE_FONT; + } + else { + PyErr_Format(PyExc_ValueError, + "load: invalid '%s' filetype, only [" STR_SOURCE_TYPES + "] " + "are supported", + path_type_s); + return NULL; + } + + prv = BKE_previewimg_cached_thumbnail_read(name, path, path_type, force_reload); + RNA_pointer_create(NULL, &RNA_ImagePreview, prv, &ptr); + + return pyrna_struct_CreatePyObject(&ptr); } PyDoc_STRVAR(bpy_utils_previews_release_doc, -".. method:: release(name)\n" -"\n" -" Release (free) a previously created preview.\n" -"\n" -"\n" -" :arg name: The name (unique id) identifying the preview.\n" -" :type name: string\n" -); + ".. method:: release(name)\n" + "\n" + " Release (free) a previously created preview.\n" + "\n" + "\n" + " :arg name: The name (unique id) identifying the preview.\n" + " :type name: string\n"); static PyObject *bpy_utils_previews_release(PyObject *UNUSED(self), PyObject *args) { - char *name; + char *name; - if (!PyArg_ParseTuple(args, "s:release", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:release", &name)) { + return NULL; + } - BKE_previewimg_cached_release(name); + BKE_previewimg_cached_release(name); - Py_RETURN_NONE; + Py_RETURN_NONE; } static struct PyMethodDef bpy_utils_previews_methods[] = { - /* Can't use METH_KEYWORDS alone, see http://bugs.python.org/issue11587 */ - {"new", (PyCFunction)bpy_utils_previews_new, METH_VARARGS, bpy_utils_previews_new_doc}, - {"load", (PyCFunction)bpy_utils_previews_load, METH_VARARGS, bpy_utils_previews_load_doc}, - {"release", (PyCFunction)bpy_utils_previews_release, METH_VARARGS, bpy_utils_previews_release_doc}, - {NULL, NULL, 0, NULL}, + /* Can't use METH_KEYWORDS alone, see http://bugs.python.org/issue11587 */ + {"new", (PyCFunction)bpy_utils_previews_new, METH_VARARGS, bpy_utils_previews_new_doc}, + {"load", (PyCFunction)bpy_utils_previews_load, METH_VARARGS, bpy_utils_previews_load_doc}, + {"release", + (PyCFunction)bpy_utils_previews_release, + METH_VARARGS, + bpy_utils_previews_release_doc}, + {NULL, NULL, 0, NULL}, }; -PyDoc_STRVAR(bpy_utils_previews_doc, -"This object contains basic static methods to handle cached (non-ID) previews in Blender\n" -"(low-level API, not exposed to final users)." -); +PyDoc_STRVAR( + bpy_utils_previews_doc, + "This object contains basic static methods to handle cached (non-ID) previews in Blender\n" + "(low-level API, not exposed to final users)."); static struct PyModuleDef bpy_utils_previews_module = { - PyModuleDef_HEAD_INIT, - "bpy._utils_previews", - bpy_utils_previews_doc, - 0, - bpy_utils_previews_methods, - NULL, NULL, NULL, NULL, + PyModuleDef_HEAD_INIT, + "bpy._utils_previews", + bpy_utils_previews_doc, + 0, + bpy_utils_previews_methods, + NULL, + NULL, + NULL, + NULL, }; - PyObject *BPY_utils_previews_module(void) { - PyObject *submodule; + PyObject *submodule; - submodule = PyModule_Create(&bpy_utils_previews_module); + submodule = PyModule_Create(&bpy_utils_previews_module); - return submodule; + return submodule; } diff --git a/source/blender/python/intern/bpy_utils_units.c b/source/blender/python/intern/bpy_utils_units.c index abae53088a8..b80ea50dd09 100644 --- a/source/blender/python/intern/bpy_utils_units.c +++ b/source/blender/python/intern/bpy_utils_units.c @@ -43,25 +43,25 @@ static PyTypeObject BPyUnitsCategoriesType; /* XXX Maybe better as externs of BKE_unit.h ? */ static const char *bpyunits_usystem_items[] = { - "NONE", - "METRIC", - "IMPERIAL", - NULL, + "NONE", + "METRIC", + "IMPERIAL", + NULL, }; static const char *bpyunits_ucategorie_items[] = { - "NONE", - "LENGTH", - "AREA", - "VOLUME", - "MASS", - "ROTATION", - "TIME", - "VELOCITY", - "ACCELERATION", - "CAMERA", - "POWER", - NULL, + "NONE", + "LENGTH", + "AREA", + "VOLUME", + "MASS", + "ROTATION", + "TIME", + "VELOCITY", + "ACCELERATION", + "CAMERA", + "POWER", + NULL, }; /** @@ -73,261 +73,282 @@ static PyStructSequence_Field bpyunits_systems_fields[ARRAY_SIZE(bpyunits_usyste static PyStructSequence_Field bpyunits_categories_fields[ARRAY_SIZE(bpyunits_ucategorie_items)]; static PyStructSequence_Desc bpyunits_systems_desc = { - (char *)"bpy.utils.units.systems", /* name */ - (char *)"This named tuple contains all pre-defined unit systems", /* doc */ - bpyunits_systems_fields, /* fields */ - ARRAY_SIZE(bpyunits_systems_fields) - 1, + (char *)"bpy.utils.units.systems", /* name */ + (char *)"This named tuple contains all pre-defined unit systems", /* doc */ + bpyunits_systems_fields, /* fields */ + ARRAY_SIZE(bpyunits_systems_fields) - 1, }; static PyStructSequence_Desc bpyunits_categories_desc = { - (char *)"bpy.utils.units.categories", /* name */ - (char *)"This named tuple contains all pre-defined unit names", /* doc */ - bpyunits_categories_fields, /* fields */ - ARRAY_SIZE(bpyunits_categories_fields) - 1, + (char *)"bpy.utils.units.categories", /* name */ + (char *)"This named tuple contains all pre-defined unit names", /* doc */ + bpyunits_categories_fields, /* fields */ + ARRAY_SIZE(bpyunits_categories_fields) - 1, }; /** * Simple utility function to initialize #PyStructSequence_Desc */ -static PyObject *py_structseq_from_strings( - PyTypeObject *py_type, - PyStructSequence_Desc *py_sseq_desc, - const char **str_items) +static PyObject *py_structseq_from_strings(PyTypeObject *py_type, + PyStructSequence_Desc *py_sseq_desc, + const char **str_items) { - PyObject *py_struct_seq; - int pos = 0; + PyObject *py_struct_seq; + int pos = 0; - const char **str_iter; - PyStructSequence_Field *desc; + const char **str_iter; + PyStructSequence_Field *desc; - /* initialize array */ - /* We really populate the contexts' fields here! */ - for (str_iter = str_items, desc = py_sseq_desc->fields; *str_iter; str_iter++, desc++) { - desc->name = (char *)*str_iter; - desc->doc = NULL; - } - /* end sentinel */ - desc->name = desc->doc = NULL; + /* initialize array */ + /* We really populate the contexts' fields here! */ + for (str_iter = str_items, desc = py_sseq_desc->fields; *str_iter; str_iter++, desc++) { + desc->name = (char *)*str_iter; + desc->doc = NULL; + } + /* end sentinel */ + desc->name = desc->doc = NULL; - PyStructSequence_InitType(py_type, py_sseq_desc); + PyStructSequence_InitType(py_type, py_sseq_desc); - /* initialize pytype */ - py_struct_seq = PyStructSequence_New(py_type); - BLI_assert(py_struct_seq != NULL); + /* initialize pytype */ + py_struct_seq = PyStructSequence_New(py_type); + BLI_assert(py_struct_seq != NULL); - for (str_iter = str_items; *str_iter; str_iter++) { - PyStructSequence_SET_ITEM(py_struct_seq, pos++, PyUnicode_FromString((*str_iter))); - } + for (str_iter = str_items; *str_iter; str_iter++) { + PyStructSequence_SET_ITEM(py_struct_seq, pos++, PyUnicode_FromString((*str_iter))); + } - return py_struct_seq; + return py_struct_seq; } static bool bpyunits_validate(const char *usys_str, const char *ucat_str, int *r_usys, int *r_ucat) { - *r_usys = BLI_str_index_in_array(usys_str, bpyunits_usystem_items); - if (*r_usys < 0) { - PyErr_Format(PyExc_ValueError, - "Unknown unit system specified: %.200s.", - usys_str); - return false; - } - - *r_ucat = BLI_str_index_in_array(ucat_str, bpyunits_ucategorie_items); - if (*r_ucat < 0) { - PyErr_Format(PyExc_ValueError, - "Unknown unit category specified: %.200s.", - ucat_str); - return false; - } - - if (!bUnit_IsValid(*r_usys, *r_ucat)) { - PyErr_Format(PyExc_ValueError, - "%.200s / %.200s unit system/category combination is not valid.", - usys_str, ucat_str); - return false; - } - - return true; + *r_usys = BLI_str_index_in_array(usys_str, bpyunits_usystem_items); + if (*r_usys < 0) { + PyErr_Format(PyExc_ValueError, "Unknown unit system specified: %.200s.", usys_str); + return false; + } + + *r_ucat = BLI_str_index_in_array(ucat_str, bpyunits_ucategorie_items); + if (*r_ucat < 0) { + PyErr_Format(PyExc_ValueError, "Unknown unit category specified: %.200s.", ucat_str); + return false; + } + + if (!bUnit_IsValid(*r_usys, *r_ucat)) { + PyErr_Format(PyExc_ValueError, + "%.200s / %.200s unit system/category combination is not valid.", + usys_str, + ucat_str); + return false; + } + + return true; } -PyDoc_STRVAR(bpyunits_to_value_doc, -".. method:: to_value(unit_system, unit_category, str_input, str_ref_unit=None)\n" -"\n" -" Convert a given input string into a float value.\n" -"\n" -" :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n" -" :type unit_system: string\n" -" :arg unit_category: The category of data we are converting (length, area, rotation, etc.),\n" -" from :attr:`bpy.utils.units.categories`.\n" -" :type unit_category: string\n" -" :arg str_input: The string to convert to a float value.\n" -" :type str_input: string\n" -" :arg str_ref_unit: A reference string from which to extract a default unit, if none is found in ``str_input``.\n" -" :type str_ref_unit: string or None\n" -" :return: The converted/interpreted value.\n" -" :rtype: float\n" -" :raises ValueError: if conversion fails to generate a valid python float value.\n" -); +PyDoc_STRVAR( + bpyunits_to_value_doc, + ".. method:: to_value(unit_system, unit_category, str_input, str_ref_unit=None)\n" + "\n" + " Convert a given input string into a float value.\n" + "\n" + " :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n" + " :type unit_system: string\n" + " :arg unit_category: The category of data we are converting (length, area, rotation, " + "etc.),\n" + " from :attr:`bpy.utils.units.categories`.\n" + " :type unit_category: string\n" + " :arg str_input: The string to convert to a float value.\n" + " :type str_input: string\n" + " :arg str_ref_unit: A reference string from which to extract a default unit, if none is " + "found in ``str_input``.\n" + " :type str_ref_unit: string or None\n" + " :return: The converted/interpreted value.\n" + " :rtype: float\n" + " :raises ValueError: if conversion fails to generate a valid python float value.\n"); static PyObject *bpyunits_to_value(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - char *usys_str = NULL, *ucat_str = NULL, *inpt = NULL, *uref = NULL; - const float scale = 1.0f; - - char *str; - Py_ssize_t str_len; - double result; - int usys, ucat; - PyObject *ret; - - static const char *_keywords[] = { - "unit_system", "unit_category", "str_input", "str_ref_unit", NULL, - }; - static _PyArg_Parser _parser = {"sss#|z:to_value", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &usys_str, &ucat_str, &inpt, &str_len, &uref)) - { - return NULL; - } - - if (!bpyunits_validate(usys_str, ucat_str, &usys, &ucat)) { - return NULL; - } - - str_len = str_len * 2 + 64; - str = PyMem_MALLOC(sizeof(*str) * (size_t)str_len); - BLI_strncpy(str, inpt, (size_t)str_len); - - bUnit_ReplaceString(str, (int)str_len, uref, scale, usys, ucat); - - if (!PyC_RunString_AsNumber(NULL, str, "<bpy_units_api>", &result)) { - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } - - PyErr_Format(PyExc_ValueError, - "'%.200s' (converted as '%s') could not be evaluated.", - inpt, str); - ret = NULL; - } - else { - ret = PyFloat_FromDouble(result); - } - - PyMem_FREE(str); - return ret; + char *usys_str = NULL, *ucat_str = NULL, *inpt = NULL, *uref = NULL; + const float scale = 1.0f; + + char *str; + Py_ssize_t str_len; + double result; + int usys, ucat; + PyObject *ret; + + static const char *_keywords[] = { + "unit_system", + "unit_category", + "str_input", + "str_ref_unit", + NULL, + }; + static _PyArg_Parser _parser = {"sss#|z:to_value", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast( + args, kw, &_parser, &usys_str, &ucat_str, &inpt, &str_len, &uref)) { + return NULL; + } + + if (!bpyunits_validate(usys_str, ucat_str, &usys, &ucat)) { + return NULL; + } + + str_len = str_len * 2 + 64; + str = PyMem_MALLOC(sizeof(*str) * (size_t)str_len); + BLI_strncpy(str, inpt, (size_t)str_len); + + bUnit_ReplaceString(str, (int)str_len, uref, scale, usys, ucat); + + if (!PyC_RunString_AsNumber(NULL, str, "<bpy_units_api>", &result)) { + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + } + + PyErr_Format( + PyExc_ValueError, "'%.200s' (converted as '%s') could not be evaluated.", inpt, str); + ret = NULL; + } + else { + ret = PyFloat_FromDouble(result); + } + + PyMem_FREE(str); + return ret; } PyDoc_STRVAR(bpyunits_to_string_doc, -".. method:: to_string(unit_system, unit_category, value, precision=3, split_unit=False, compatible_unit=False)\n" -"\n" -" Convert a given input float value into a string with units.\n" -"\n" -" :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n" -" :type unit_system: string\n" -" :arg unit_category: The category of data we are converting (length, area, rotation, etc.),\n" -" from :attr:`bpy.utils.units.categories`.\n" -" :type unit_category: string\n" -" :arg value: The value to convert to a string.\n" -" :type value: float\n" -" :arg precision: Number of digits after the comma.\n" -" :type precision: int\n" -" :arg split_unit: Whether to use several units if needed (1m1cm), or always only one (1.01m).\n" -" :type split_unit: bool\n" -" :arg compatible_unit: Whether to use keyboard-friendly units (1m2) or nicer utf-8 ones (1m²).\n" -" :type compatible_unit: bool\n" -" :return: The converted string.\n" -" :rtype: str\n" -" :raises ValueError: if conversion fails to generate a valid python string.\n" -); + ".. method:: to_string(unit_system, unit_category, value, precision=3, " + "split_unit=False, compatible_unit=False)\n" + "\n" + " Convert a given input float value into a string with units.\n" + "\n" + " :arg unit_system: The unit system, from :attr:`bpy.utils.units.systems`.\n" + " :type unit_system: string\n" + " :arg unit_category: The category of data we are converting (length, area, " + "rotation, etc.),\n" + " from :attr:`bpy.utils.units.categories`.\n" + " :type unit_category: string\n" + " :arg value: The value to convert to a string.\n" + " :type value: float\n" + " :arg precision: Number of digits after the comma.\n" + " :type precision: int\n" + " :arg split_unit: Whether to use several units if needed (1m1cm), or always only " + "one (1.01m).\n" + " :type split_unit: bool\n" + " :arg compatible_unit: Whether to use keyboard-friendly units (1m2) or nicer " + "utf-8 ones (1m²).\n" + " :type compatible_unit: bool\n" + " :return: The converted string.\n" + " :rtype: str\n" + " :raises ValueError: if conversion fails to generate a valid python string.\n"); static PyObject *bpyunits_to_string(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - char *usys_str = NULL, *ucat_str = NULL; - double value = 0.0; - int precision = 3; - bool split_unit = false, compatible_unit = false; - - int usys, ucat; - - static const char *_keywords[] = { - "unit_system", "unit_category", "value", - "precision", "split_unit", "compatible_unit", NULL, - }; - static _PyArg_Parser _parser = {"ssd|iO&O&:to_string", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, - &usys_str, &ucat_str, &value, &precision, - PyC_ParseBool, &split_unit, - PyC_ParseBool, &compatible_unit)) - { - return NULL; - } - - if (!bpyunits_validate(usys_str, ucat_str, &usys, &ucat)) { - return NULL; - } - - { - /* Maximum expected length of string result: - * - number itself: precision + decimal dot + up to four 'above dot' digits. - * - unit: up to ten chars (six currently, let's be conservative, also because we use some utf8 chars). - * This can be repeated twice (e.g. 1m20cm), and we add ten more spare chars (spaces, trailing '\0'...). - * So in practice, 64 should be more than enough. - */ - char buf1[64], buf2[64], *str; - PyObject *result; - - bUnit_AsString(buf1, sizeof(buf1), value, precision, usys, ucat, (bool)split_unit, false); - - if (compatible_unit) { - bUnit_ToUnitAltName(buf2, sizeof(buf2), buf1, usys, ucat); - str = buf2; - } - else { - str = buf1; - } - - result = PyUnicode_FromString(str); - - return result; - } + char *usys_str = NULL, *ucat_str = NULL; + double value = 0.0; + int precision = 3; + bool split_unit = false, compatible_unit = false; + + int usys, ucat; + + static const char *_keywords[] = { + "unit_system", + "unit_category", + "value", + "precision", + "split_unit", + "compatible_unit", + NULL, + }; + static _PyArg_Parser _parser = {"ssd|iO&O&:to_string", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &usys_str, + &ucat_str, + &value, + &precision, + PyC_ParseBool, + &split_unit, + PyC_ParseBool, + &compatible_unit)) { + return NULL; + } + + if (!bpyunits_validate(usys_str, ucat_str, &usys, &ucat)) { + return NULL; + } + + { + /* Maximum expected length of string result: + * - number itself: precision + decimal dot + up to four 'above dot' digits. + * - unit: up to ten chars (six currently, let's be conservative, also because we use some utf8 chars). + * This can be repeated twice (e.g. 1m20cm), and we add ten more spare chars (spaces, trailing '\0'...). + * So in practice, 64 should be more than enough. + */ + char buf1[64], buf2[64], *str; + PyObject *result; + + bUnit_AsString(buf1, sizeof(buf1), value, precision, usys, ucat, (bool)split_unit, false); + + if (compatible_unit) { + bUnit_ToUnitAltName(buf2, sizeof(buf2), buf1, usys, ucat); + str = buf2; + } + else { + str = buf1; + } + + result = PyUnicode_FromString(str); + + return result; + } } static PyMethodDef bpyunits_methods[] = { - {"to_value", (PyCFunction)bpyunits_to_value, METH_VARARGS | METH_KEYWORDS, bpyunits_to_value_doc}, - {"to_string", (PyCFunction)bpyunits_to_string, METH_VARARGS | METH_KEYWORDS, bpyunits_to_string_doc}, - {NULL, NULL, 0, NULL}, + {"to_value", + (PyCFunction)bpyunits_to_value, + METH_VARARGS | METH_KEYWORDS, + bpyunits_to_value_doc}, + {"to_string", + (PyCFunction)bpyunits_to_string, + METH_VARARGS | METH_KEYWORDS, + bpyunits_to_string_doc}, + {NULL, NULL, 0, NULL}, }; -PyDoc_STRVAR(bpyunits_doc, -"This module contains some data/methods regarding units handling." -); +PyDoc_STRVAR(bpyunits_doc, "This module contains some data/methods regarding units handling."); static struct PyModuleDef bpyunits_module = { - PyModuleDef_HEAD_INIT, - "bpy.utils.units", - bpyunits_doc, - -1, /* multiple "initialization" just copies the module dict. */ - bpyunits_methods, - NULL, NULL, NULL, NULL, + PyModuleDef_HEAD_INIT, + "bpy.utils.units", + bpyunits_doc, + -1, /* multiple "initialization" just copies the module dict. */ + bpyunits_methods, + NULL, + NULL, + NULL, + NULL, }; PyObject *BPY_utils_units(void) { - PyObject *submodule, *item; + PyObject *submodule, *item; - submodule = PyModule_Create(&bpyunits_module); - PyDict_SetItemString(PyImport_GetModuleDict(), bpyunits_module.m_name, submodule); + submodule = PyModule_Create(&bpyunits_module); + PyDict_SetItemString(PyImport_GetModuleDict(), bpyunits_module.m_name, submodule); - /* Finalize our unit systems and types structseq definitions! */ + /* Finalize our unit systems and types structseq definitions! */ - /* bpy.utils.units.system */ - item = py_structseq_from_strings(&BPyUnitsSystemsType, &bpyunits_systems_desc, bpyunits_usystem_items); - PyModule_AddObject(submodule, "systems", item); /* steals ref */ + /* bpy.utils.units.system */ + item = py_structseq_from_strings( + &BPyUnitsSystemsType, &bpyunits_systems_desc, bpyunits_usystem_items); + PyModule_AddObject(submodule, "systems", item); /* steals ref */ - /* bpy.utils.units.categories */ - item = py_structseq_from_strings(&BPyUnitsCategoriesType, &bpyunits_categories_desc, bpyunits_ucategorie_items); - PyModule_AddObject(submodule, "categories", item); /* steals ref */ + /* bpy.utils.units.categories */ + item = py_structseq_from_strings( + &BPyUnitsCategoriesType, &bpyunits_categories_desc, bpyunits_ucategorie_items); + PyModule_AddObject(submodule, "categories", item); /* steals ref */ - return submodule; + return submodule; } diff --git a/source/blender/python/intern/bpy_utils_units.h b/source/blender/python/intern/bpy_utils_units.h index 55b79da6a93..5a30c1c3dae 100644 --- a/source/blender/python/intern/bpy_utils_units.h +++ b/source/blender/python/intern/bpy_utils_units.h @@ -23,4 +23,4 @@ PyObject *BPY_utils_units(void); -#endif /* __BPY_UTILS_UNITS_H__ */ +#endif /* __BPY_UTILS_UNITS_H__ */ diff --git a/source/blender/python/intern/stubs.c b/source/blender/python/intern/stubs.c index b6c30828f74..bf068f99722 100644 --- a/source/blender/python/intern/stubs.c +++ b/source/blender/python/intern/stubs.c @@ -34,7 +34,18 @@ //void BPY_script_exec(void) {} //void BPY_python_start(void) {} //void BPY_text_free_code(void) {} -void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets) {} -void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct) {} -int BPY_is_pyconstraint(struct Text *text) { return 0;} -void BPY_pyconstraint_update(struct Object *owner, struct bConstraint *con) {} +void BPY_pyconstraint_exec(struct bPythonConstraint *con, + struct bConstraintOb *cob, + struct ListBase *targets) +{ +} +void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct) +{ +} +int BPY_is_pyconstraint(struct Text *text) +{ + return 0; +} +void BPY_pyconstraint_update(struct Object *owner, struct bConstraint *con) +{ +} |