From 18f6bb04fa6bec6368a9d3e5253c041ba5c474b3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 25 Feb 2014 16:18:10 +1100 Subject: [PATCH] Fix for custom property editor when property id's contained quotes Adds bpy.utils.escape_identifier() --- release/scripts/modules/bpy/utils.py | 9 ++++- release/scripts/modules/rna_prop_ui.py | 4 ++- source/blender/python/intern/bpy.c | 48 +++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py index 6c32f95fc03..ce1efa43b3e 100644 --- a/release/scripts/modules/bpy/utils.py +++ b/release/scripts/modules/bpy/utils.py @@ -25,6 +25,7 @@ not associated with blenders internal data. __all__ = ( "blend_paths", + "escape_identifier", "keyconfig_set", "load_scripts", "modules_from_path", @@ -48,7 +49,13 @@ __all__ = ( "user_resource", ) -from _bpy import register_class, unregister_class, blend_paths, resource_path +from _bpy import ( + escape_identifier, + register_class, + unregister_class, + blend_paths, + resource_path, + ) from _bpy import script_paths as _bpy_script_paths from _bpy import user_resource as _user_resource diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py index dd0cd632413..e73b0358d00 100644 --- a/release/scripts/modules/rna_prop_ui.py +++ b/release/scripts/modules/rna_prop_ui.py @@ -92,6 +92,8 @@ def draw(layout, context, context_member, property_type, use_edit=True): if not rna_item: return + from bpy.utils import escape_identifier + if rna_item.id_data.library is not None: use_edit = False @@ -144,7 +146,7 @@ def draw(layout, context, context_member, property_type, use_edit=True): if key in rna_properties: row.prop(rna_item, key, text="") else: - row.prop(rna_item, '["%s"]' % key, text="") + row.prop(rna_item, '["%s"]' % escape_identifier(key), text="") if use_edit: row = split.row(align=True) diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index aa4b8117e3a..ae57588985d 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -212,6 +212,50 @@ static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObj return PyUnicode_DecodeFSDefault(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" +); +static PyObject *bpy_escape_identifier(PyObject *UNUSED(self), PyObject *value) +{ + 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; + + value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); + + 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); + + 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); + + 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 = @@ -220,7 +264,8 @@ 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) { @@ -307,6 +352,7 @@ void BPy_init_modules(void) 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));