diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-10-11 18:30:53 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-10-11 18:30:53 +0400 |
commit | 4f33d65ba1f02f2cd3f340d0123900ea1beffd2c (patch) | |
tree | 05ef40081ce6be190a171e0fee09b12344e16eb6 /source/blender/python | |
parent | 1ab9fc59b750b1dc5ebaacd30c6891949895a10d (diff) | |
parent | 79f21f88c2be305962f6432bf8b1af94056fd92b (diff) |
Cycles: svn merge -r40411:40934 ^/trunk/blender
Diffstat (limited to 'source/blender/python')
19 files changed, 424 insertions, 150 deletions
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index 5cc3f3bedc4..3f47038687a 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -17,9 +17,6 @@ defs = [] if is_debug: defs.append('_DEBUG') -if env['WITH_BF_INTERNATIONAL']: - defs.append('INTERNATIONAL') - sources = env.Glob('generic/*.c') env.BlenderLib( libname = 'bf_python_ext', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core','player'], priority = [363,165]) # ketsji is 360 @@ -43,5 +40,8 @@ if env['WITH_BF_PYTHON_SAFETY']: if env['BF_BUILDINFO']: defs.append('BUILD_DATE') +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + sources = env.Glob('intern/*.c') env.BlenderLib( libname = 'bf_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core'], priority = [361]) diff --git a/source/blender/python/generic/CMakeLists.txt b/source/blender/python/generic/CMakeLists.txt index 0a49036c15d..847a0d19a7f 100644 --- a/source/blender/python/generic/CMakeLists.txt +++ b/source/blender/python/generic/CMakeLists.txt @@ -48,8 +48,4 @@ set(SRC py_capi_utils.h ) -if(WITH_INTERNATIONAL) - add_definitions(-DINTERNATIONAL) -endif() - blender_add_lib(bf_python_ext "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/python/generic/IDProp.c b/source/blender/python/generic/IDProp.c index 2543d34f58c..e6883eb30af 100644 --- a/source/blender/python/generic/IDProp.c +++ b/source/blender/python/generic/IDProp.c @@ -269,7 +269,7 @@ static int idp_sequence_type(PyObject *seq) PyObject *item; int type= IDP_INT; - int i, len = PySequence_Size(seq); + Py_ssize_t i, len = PySequence_Size(seq); for (i=0; i < len; i++) { item = PySequence_GetItem(seq, i); if (PyFloat_Check(item)) { diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index 44d42a479ec..35c211d5424 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -286,8 +286,8 @@ static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject Buffer *buffer; int dimensions[MAX_DIMENSIONS]; - int i, type; - int ndimensions = 0; + int type; + Py_ssize_t i, ndimensions = 0; if(kwds && PyDict_Size(kwds)) { PyErr_SetString(PyExc_TypeError, diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c index 87e4a301eff..b16efdf5a3d 100644 --- a/source/blender/python/generic/blf_py_api.c +++ b/source/blender/python/generic/blf_py_api.c @@ -31,15 +31,9 @@ #include "blf_py_api.h" #include "../../blenfont/BLF_api.h" -#include "../../blenfont/BLF_translation.h" #include "BLI_utildefines.h" -#ifdef INTERNATIONAL -#include "DNA_userdef_types.h" /* is it bad level? */ -#endif - - PyDoc_STRVAR(py_blf_position_doc, ".. function:: position(fontid, x, y, z)\n" "\n" @@ -371,33 +365,24 @@ static PyObject *py_blf_load(PyObject *UNUSED(self), PyObject *args) return PyLong_FromLong(BLF_load(filename)); } -PyDoc_STRVAR(py_blf_gettext_doc, -".. function:: gettext(msgid)\n" +PyDoc_STRVAR(py_blf_unload_doc, +".. function:: unload(filename)\n" "\n" -" Get a msg in local language.\n" +" Unload an existing font.\n" "\n" -" :arg msgid: the source string.\n" -" :type msgid: string\n" -" :return: the localized string.\n" -" :rtype: string\n" +" :arg filename: the filename of the font.\n" +" :type filename: string\n" ); -static PyObject *py_blf_gettext(PyObject *UNUSED(self), PyObject *value) +static PyObject *py_blf_unload(PyObject *UNUSED(self), PyObject *args) { -#ifdef INTERNATIONAL - if ((U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_IFACE)) { - const char *msgid= _PyUnicode_AsString(value); - if(msgid == NULL) { - PyErr_SetString(PyExc_TypeError, "blf.gettext expects a single string argument"); - return NULL; - } - - return PyUnicode_FromString(BLF_gettext(msgid)); - } - else -#endif /* INTERNATIONAL */ - { - return Py_INCREF(value), value; - } + char* filename; + + if (!PyArg_ParseTuple(args, "s:blf.unload", &filename)) + return NULL; + + BLF_unload(filename); + + Py_RETURN_NONE; } /*----------------------------MODULE INIT-------------------------*/ @@ -415,7 +400,7 @@ static PyMethodDef BLF_methods[] = { {"shadow_offset", (PyCFunction) py_blf_shadow_offset, METH_VARARGS, py_blf_shadow_offset_doc}, {"size", (PyCFunction) py_blf_size, METH_VARARGS, py_blf_size_doc}, {"load", (PyCFunction) py_blf_load, METH_VARARGS, py_blf_load_doc}, - {"gettext", (PyCFunction) py_blf_gettext, METH_O, py_blf_gettext_doc}, + {"unload", (PyCFunction) py_blf_unload, METH_VARARGS, py_blf_unload_doc}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c index 67ed90c79eb..d29bc798399 100644 --- a/source/blender/python/generic/bpy_internal_import.c +++ b/source/blender/python/generic/bpy_internal_import.c @@ -93,7 +93,7 @@ void bpy_import_main_set(struct Main *maggie) /* returns a dummy filename for a textblock so we can tell what file a text block comes from */ void bpy_text_filename_get(char *fn, size_t fn_len, Text *text) { - BLI_snprintf(fn, fn_len, "%s%c%s", text->id.lib ? text->id.lib->filepath : bpy_import_main->name, SEP, text->id.name+2); + BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bpy_import_main, &text->id), SEP, text->id.name+2); } PyObject *bpy_text_import(Text *text) @@ -120,7 +120,7 @@ PyObject *bpy_text_import(Text *text) } len= strlen(text->id.name+2); - strncpy(modulename, text->id.name+2, len); + BLI_strncpy(modulename, text->id.name+2, len); modulename[len - 3]= '\0'; /* remove .py */ return PyImport_ExecCodeModule(modulename, text->compiled); } diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index d5bd44fc288..bf14102bb0d 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -107,7 +107,8 @@ int PyC_AsArray(void *array, PyObject *value, const int length, const PyTypeObje /* for debugging */ -void PyC_ObSpit(const char *name, PyObject *var) { +void PyC_ObSpit(const char *name, PyObject *var) +{ fprintf(stderr, "<%s> : ", name); if (var==NULL) { fprintf(stderr, "<NIL>"); @@ -126,7 +127,8 @@ void PyC_ObSpit(const char *name, PyObject *var) { fprintf(stderr, "\n"); } -void PyC_LineSpit(void) { +void PyC_LineSpit(void) +{ const char *filename; int lineno; @@ -363,12 +365,15 @@ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) * chars since blender doesnt limit this */ return result; } - else if(PyBytes_Check(py_str)) { - PyErr_Clear(); - return PyBytes_AS_STRING(py_str); - } else { - return PyBytes_AS_STRING((*coerce= PyUnicode_EncodeFSDefault(py_str))); + PyErr_Clear(); + + if(PyBytes_Check(py_str)) { + return PyBytes_AS_STRING(py_str); + } + else { + return PyBytes_AS_STRING((*coerce= PyUnicode_EncodeFSDefault(py_str))); + } } } diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 807074b92ce..9a214718e73 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -99,4 +99,8 @@ if(WITH_CYCLES) add_definitions(-DWITH_CYCLES) endif() +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + blender_add_lib(bf_python "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index b909a0d5f55..cd3d78410f2 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -40,6 +40,8 @@ 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", NULL}, + {(char *)"frame_change_post", NULL}, {(char *)"render_pre", NULL}, {(char *)"render_post", NULL}, {(char *)"render_stats", NULL}, diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index f3ef55d29c4..319790340ca 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -41,6 +41,9 @@ #include "bpy_driver.h" +extern void BPY_update_rna_module(void); + + /* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */ PyObject *bpy_pydriver_Dict= NULL; @@ -164,6 +167,10 @@ float BPY_driver_exec(ChannelDriver *driver) 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) { diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 7327679cc7e..dedc5df1f1c 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -408,12 +408,51 @@ static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value) return (PyObject *)pyrna; } +static PyObject *pyop_getinstance(PyObject *UNUSED(self), PyObject *value) +{ + wmOperatorType *ot; + wmOperator *op; + PointerRNA ptr; + char *opname= _PyUnicode_AsString(value); + BPy_StructRNA *pyrna= NULL; + + if(opname==NULL) { + PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_instance() expects a string argument"); + return NULL; + } + ot= WM_operatortype_find(opname, TRUE); + if(ot==NULL) { + PyErr_Format(PyExc_KeyError, "_bpy.ops.get_instance(\"%s\") not found", opname); + return NULL; + } + +#ifdef PYRNA_FREE_SUPPORT + op= MEM_callocN(sizeof(wmOperator), __func__); +#else + op= PyMem_MALLOC(sizeof(wmOperator)); + memset(op, 0, sizeof(wmOperator)); +#endif + BLI_strncpy(op->idname, op->idname, sizeof(op->idname)); /* incase its needed */ + op->type= ot; + + RNA_pointer_create(NULL, &RNA_Operator, op, &ptr); + + pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); +#ifdef PYRNA_FREE_SUPPORT + pyrna->freeptr= TRUE; +#endif + op->ptr= &pyrna->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", (PyCFunction) pyop_getrna, METH_O, NULL}, + {"get_rna", (PyCFunction) pyop_getrna, METH_O, NULL}, /* only for introspection, leaks memory */ + {"get_instance", (PyCFunction) pyop_getinstance, METH_O, NULL}, /* only for introspection, leaks memory */ {"macro_define", (PyCFunction) PYOP_wrap_macro_define, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index de29cb2aeac..b5ded8b3a65 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -125,7 +125,7 @@ PyObject *PYOP_wrap_macro_define(PyObject *UNUSED(self), PyObject *args) otmacro= WM_operatortype_macro_define(ot, opname); - RNA_pointer_create(NULL, &RNA_OperatorTypeMacro, otmacro, &ptr_otmacro); + RNA_pointer_create(NULL, &RNA_OperatorMacro, otmacro, &ptr_otmacro); return pyrna_struct_CreatePyObject(&ptr_otmacro); } diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 5da142aeea7..5c668590dff 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -56,13 +56,13 @@ extern BPy_StructRNA *bpy_context_module; static EnumPropertyItem property_flag_items[]= { {PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""}, - {PROP_SKIP_SAVE, "SKIP_SAVE", 0, "Skip Save", ""}, + {PROP_SKIP_SAVE, "SKIP_SAVE", 0, "Skip Save", ""}, {PROP_ANIMATABLE, "ANIMATABLE", 0, "Animateable", ""}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem property_flag_enum_items[]= { {PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""}, - {PROP_SKIP_SAVE, "SKIP_SAVE", 0, "Skip Save", ""}, + {PROP_SKIP_SAVE, "SKIP_SAVE", 0, "Skip Save", ""}, {PROP_ANIMATABLE, "ANIMATABLE", 0, "Animateable", ""}, {PROP_ENUM_FLAG, "ENUM_FLAG", 0, "Enum Flag", ""}, {0, NULL, 0, NULL, NULL}}; @@ -72,6 +72,7 @@ static EnumPropertyItem property_subtype_string_items[]= { {PROP_FILEPATH, "FILE_PATH", 0, "File Path", ""}, {PROP_DIRPATH, "DIR_PATH", 0, "Directory Path", ""}, {PROP_FILENAME, "FILENAME", 0, "Filename", ""}, + {PROP_TRANSLATE, "TRANSLATE", 0, "Translate", ""}, {PROP_NONE, "NONE", 0, "None", ""}, {0, NULL, 0, NULL, NULL}}; @@ -266,6 +267,18 @@ static int bpy_prop_callback_assign(struct PropertyRNA *prop, PyObject *update_c return 0; } +/* 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; + } +} + /* 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) \ @@ -913,6 +926,7 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i for(i=0; i<seq_len; i++) { EnumPropertyItem tmp= {0, "", 0, "", ""}; + Py_ssize_t item_size; Py_ssize_t id_str_size; Py_ssize_t name_str_size; Py_ssize_t desc_str_size; @@ -920,13 +934,17 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i item= PySequence_Fast_GET_ITEM(seq_fast, i); if( (PyTuple_CheckExact(item)) && - (PyTuple_GET_SIZE(item) == 3) && + (item_size= PyTuple_GET_SIZE(item)) && + (item_size == 3 || item_size == 4) && (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)) + (tmp.description= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) && + (item_size < 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1) /* TODO, number isnt ensured to be unique from the script author */ ) { if(is_enum_flag) { - tmp.value= 1<<i; + if(item_size < 4) { + tmp.value= 1<<i; + } if(def && PySet_Contains(def, PyTuple_GET_ITEM(item, 0))) { *defvalue |= tmp.value; @@ -934,7 +952,9 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i } } else { - tmp.value= i; + if(item_size < 4) { + tmp.value= i; + } if(def && def_used == 0 && strcmp(def_cmp, tmp.identifier)==0) { *defvalue= tmp.value; @@ -949,7 +969,10 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i } else { MEM_freeN(items); - PyErr_SetString(PyExc_TypeError, "EnumProperty(...): expected an tuple containing (identifier, name description)"); + PyErr_SetString(PyExc_TypeError, + "EnumProperty(...): expected an tuple containing " + "(identifier, name description) and optionally a " + "unique number"); return NULL; } @@ -972,7 +995,7 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i PyErr_Format(PyExc_TypeError, "EnumProperty(..., default=\'%s\'): not found in enum members", - def); + def_cmp); return NULL; } } @@ -1080,8 +1103,9 @@ BPY_PROPDEF_DESC_DOC " :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'ENUM_FLAG'].\n" " :type options: set\n" " :arg items: sequence of enum items formatted:\n" -" [(identifier, name, description), ...] where the identifier is used\n" +" [(identifier, name, description, number), ...] where the identifier is used\n" " for python access and other values are used for the interface.\n" +" Note the item is optional.\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)\n" diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index a63cee4e505..ba7e2d41e69 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -73,6 +73,10 @@ #include "../generic/IDProp.h" /* for IDprop lookups */ #include "../generic/py_capi_utils.h" +#ifdef WITH_INTERNATIONAL +#include "UI_interface.h" /* bad level call into editors */ +#endif + #define USE_PEDANTIC_WRITE #define USE_MATHUTILS #define USE_STRING_COERCE @@ -80,6 +84,11 @@ static PyObject* pyrna_struct_Subtype(PointerRNA *ptr); static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self); +#define BPY_DOC_ID_PROP_TYPE_NOTE \ +" .. note:: 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) @@ -366,7 +375,7 @@ static int mathutils_rna_generic_check(BaseMathObject *bmo) { BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self) + PYRNA_PROP_CHECK_INT(self); return self->prop ? 0 : -1; } @@ -375,7 +384,7 @@ static int mathutils_rna_vector_get(BaseMathObject *bmo, int subtype) { BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self) + PYRNA_PROP_CHECK_INT(self); if(self->prop==NULL) return -1; @@ -397,7 +406,7 @@ 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) + PYRNA_PROP_CHECK_INT(self); if(self->prop==NULL) return -1; @@ -448,7 +457,7 @@ static int mathutils_rna_vector_get_index(BaseMathObject *bmo, int UNUSED(subtyp { BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self) + PYRNA_PROP_CHECK_INT(self); if(self->prop==NULL) return -1; @@ -461,7 +470,7 @@ static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int UNUSED(subtyp { BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self) + PYRNA_PROP_CHECK_INT(self); if(self->prop==NULL) return -1; @@ -505,7 +514,7 @@ static int mathutils_rna_matrix_get(BaseMathObject *bmo, int UNUSED(subtype)) { BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self) + PYRNA_PROP_CHECK_INT(self); if(self->prop==NULL) return -1; @@ -518,7 +527,7 @@ static int mathutils_rna_matrix_set(BaseMathObject *bmo, int UNUSED(subtype)) { BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self) + PYRNA_PROP_CHECK_INT(self); if(self->prop==NULL) return -1; @@ -859,7 +868,7 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self) char type_fmt[64]= ""; int type; - PYRNA_PROP_CHECK_OBJ(self) + PYRNA_PROP_CHECK_OBJ(self); type= RNA_property_type(self->prop); @@ -922,7 +931,7 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self) PyObject *ret; const char *path; - PYRNA_PROP_CHECK_OBJ(self) + PYRNA_PROP_CHECK_OBJ(self); if(id == NULL) return pyrna_prop_str(self); /* fallback */ @@ -1519,6 +1528,12 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb } else { param= _PyUnicode_AsString(value); +#ifdef WITH_INTERNATIONAL + if(subtype == PROP_TRANSLATE) { + param= UI_translate_do_iface(param); + } +#endif // WITH_INTERNATIONAL + } #else // USE_STRING_COERCE param= _PyUnicode_AsString(value); @@ -1708,7 +1723,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb } case PROP_COLLECTION: { - int seq_len, i; + Py_ssize_t seq_len, i; PyObject *item; PointerRNA itemptr; ListBase *lb; @@ -1726,7 +1741,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb } seq_len= PySequence_Size(value); - for(i=0; i<seq_len; i++) { + for(i=0; i < seq_len; i++) { item= PySequence_GetItem(value, i); if(item==NULL) { @@ -1795,7 +1810,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb static PyObject *pyrna_prop_array_to_py_index(BPy_PropertyArrayRNA *self, int index) { - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self) + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); return pyrna_py_from_array_index(self, &self->ptr, self->prop, index); } @@ -1874,7 +1889,7 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P //---------------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); @@ -1884,7 +1899,7 @@ static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self) 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); } @@ -1893,7 +1908,7 @@ static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self) * 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; } @@ -1904,7 +1919,7 @@ static int pyrna_prop_collection_bool(BPy_PropertyRNA *self) 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; @@ -1912,25 +1927,30 @@ static int pyrna_prop_collection_bool(BPy_PropertyRNA *self) 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; \ + } \ + } \ + + /* 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_CHECK_OBJ(self); - /* 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. */ - 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 NULL; - } - } + PYRNA_PROP_COLLECTION_ABS_INDEX(NULL); if(RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum_abs, &newptr)) { return pyrna_struct_CreatePyObject(&newptr); @@ -1953,11 +1973,40 @@ static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_s } } +/* values type must have been already checked */ +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; + + PYRNA_PROP_CHECK_INT(self); + + 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 { + + PyErr_Format(PyExc_IndexError, + "bpy_prop_collection[index] = value: " + "failed assignment (unknown reason)", keynum); + } + return -1; + } + + return 0; +} + static PyObject *pyrna_prop_array_subscript_int(BPy_PropertyArrayRNA *self, int keynum) { int len; - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self) + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); len= pyrna_prop_array_length(self); @@ -1974,7 +2023,7 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons { 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); @@ -1992,7 +2041,7 @@ static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py PyObject *list; PyObject *item; - PYRNA_PROP_CHECK_OBJ(self) + PYRNA_PROP_CHECK_OBJ(self); list= PyList_New(0); @@ -2031,11 +2080,11 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po int count, totdim; PyObject *tuple; - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self) + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); tuple= PyTuple_New(stop - start); - /* PYRNA_PROP_CHECK_OBJ(self) isn't needed, internal use only */ + /* PYRNA_PROP_CHECK_OBJ(self); isn't needed, internal use only */ totdim= RNA_property_array_dimension(ptr, prop, NULL); @@ -2106,7 +2155,7 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject *key) { - PYRNA_PROP_CHECK_OBJ(self) + PYRNA_PROP_CHECK_OBJ(self); if (PyUnicode_Check(key)) { return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); @@ -2163,9 +2212,131 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject } } +/* generic check to see if a PyObject is compatible with a collection + * -1 on failier, 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 doesnt 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 indicies later */ +static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, PyObject *key, PyObject *value) +{ + 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 */ + } + +#if 0 + 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 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) start += 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; + } +} + 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 (PyUnicode_Check(key)) { return pyrna_prop_array_subscript_str(self, _PyUnicode_AsString(key)); @@ -2321,7 +2492,7 @@ static int prop_subscript_ass_array_int(BPy_PropertyArrayRNA *self, Py_ssize_t k { int len; - PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self) + PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); len= pyrna_prop_array_length(self); @@ -2399,7 +2570,7 @@ static PyMappingMethods pyrna_prop_array_as_mapping= { static PyMappingMethods pyrna_prop_collection_as_mapping= { (lenfunc) pyrna_prop_collection_length, /* mp_length */ (binaryfunc) pyrna_prop_collection_subscript, /* mp_subscript */ - (objobjargproc) NULL, /* mp_ass_subscript */ + (objobjargproc) pyrna_prop_collection_ass_subscript, /* mp_ass_subscript */ }; /* only for fast bool's, large structs, assign nb_bool on init */ @@ -2456,7 +2627,7 @@ static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *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"); @@ -2495,7 +2666,7 @@ static PySequenceMethods pyrna_prop_collection_as_sequence= { NULL, /* sq_repeat */ (ssizeargfunc)pyrna_prop_collection_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */ NULL, /* *was* sq_slice */ - NULL, /* sq_ass_item */ + (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 */ @@ -2521,7 +2692,7 @@ static PyObject *pyrna_struct_subscript(BPy_StructRNA *self, PyObject *key) 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"); @@ -2554,7 +2725,7 @@ static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObje { IDProperty *group; - PYRNA_STRUCT_CHECK_INT(self) + PYRNA_STRUCT_CHECK_INT(self); group= RNA_struct_idprops(&self->ptr, 1); @@ -2587,8 +2758,7 @@ PyDoc_STRVAR(pyrna_struct_keys_doc, " :return: custom property keys.\n" " :rtype: list of strings\n" "\n" -" .. note:: Only :class:`ID`, :class:`Bone` and :class:`PoseBone` classes\n" -" support custom properties.\n" +BPY_DOC_ID_PROP_TYPE_NOTE ); static PyObject *pyrna_struct_keys(BPy_PropertyRNA *self) { @@ -2616,8 +2786,7 @@ PyDoc_STRVAR(pyrna_struct_items_doc, " :return: custom property key, value pairs.\n" " :rtype: list of key, value tuples\n" "\n" -" .. note:: Only :class:`ID`, :class:`Bone` and :class:`PoseBone`\n" -" classes support custom properties.\n" +BPY_DOC_ID_PROP_TYPE_NOTE ); static PyObject *pyrna_struct_items(BPy_PropertyRNA *self) { @@ -2645,8 +2814,7 @@ PyDoc_STRVAR(pyrna_struct_values_doc, " :return: custom property values.\n" " :rtype: list\n" "\n" -" .. note:: Only :class:`ID`, :class:`Bone` and :class:`PoseBone`\n" -" classes support custom properties.\n" +BPY_DOC_ID_PROP_TYPE_NOTE ); static PyObject *pyrna_struct_values(BPy_PropertyRNA *self) { @@ -2680,7 +2848,7 @@ static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *arg const char *name; int ret; - PYRNA_STRUCT_CHECK_OBJ(self) + PYRNA_STRUCT_CHECK_OBJ(self); if (!PyArg_ParseTuple(args, "s:is_property_set", &name)) return NULL; @@ -2723,7 +2891,7 @@ static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA *self, PyObject * 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; @@ -2757,7 +2925,7 @@ static PyObject *pyrna_struct_path_resolve(BPy_StructRNA *self, PyObject *args) PropertyRNA *r_prop; int index= -1; - PYRNA_STRUCT_CHECK_OBJ(self) + PYRNA_STRUCT_CHECK_OBJ(self); if (!PyArg_ParseTuple(args, "s|O!:path_resolve", &path, &PyBool_Type, &coerce)) return NULL; @@ -2815,7 +2983,7 @@ static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args) PropertyRNA *prop; PyObject *ret; - PYRNA_STRUCT_CHECK_OBJ(self) + PYRNA_STRUCT_CHECK_OBJ(self); if (!PyArg_ParseTuple(args, "|s:path_from_id", &name)) return NULL; @@ -2897,7 +3065,7 @@ static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self) { 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); @@ -2978,7 +3146,7 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self) PyObject *ret; PyObject *pystring; - PYRNA_STRUCT_CHECK_OBJ(self) + PYRNA_STRUCT_CHECK_OBJ(self); /* Include this incase 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 @@ -3025,7 +3193,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) PropertyRNA *prop; FunctionRNA *func; - PYRNA_STRUCT_CHECK_OBJ(self) + PYRNA_STRUCT_CHECK_OBJ(self); if(name == NULL) { PyErr_SetString(PyExc_AttributeError, "bpy_struct: __getattr__ must be a string"); @@ -3246,7 +3414,7 @@ static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject 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)) { @@ -3496,18 +3664,28 @@ static PyObject *pyrna_struct_get_id_data(BPy_DummyPointerRNA *self) Py_RETURN_NONE; } +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); +} + + + /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef pyrna_prop_getseters[]= { - {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)"The :class:`ID` object this datablock is from or None, (not available for all data types)", NULL}, + {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)"The :class:`bpy.types.ID` object this datablock is from or None, (not available for all data types)", NULL}, + {(char *)"rna_type", (getter)pyrna_struct_get_rna_type, (setter)NULL, (char *)"The property type for introspection", NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; static PyGetSetDef pyrna_struct_getseters[]= { - {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)"The :class:`ID` object this datablock is from or None, (not available for all data types)", NULL}, + {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)"The :class:`bpy.types.ID` object this datablock is from or None, (not available for all data types)", NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; @@ -3614,8 +3792,7 @@ PyDoc_STRVAR(pyrna_struct_get_doc, " *key* is not found.\n" " :type default: Undefined\n" "\n" -" .. note:: Only :class:`ID`, :class:`Bone` and :class:`PoseBone`\n" -" classes support custom properties.\n" +BPY_DOC_ID_PROP_TYPE_NOTE ); static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args) { @@ -3624,7 +3801,7 @@ static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args) 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; @@ -3681,7 +3858,7 @@ static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args const char *key; PyObject* def= Py_None; - PYRNA_PROP_CHECK_OBJ(self) + PYRNA_PROP_CHECK_OBJ(self); if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) return NULL; @@ -3954,7 +4131,7 @@ PyDoc_STRVAR(pyrna_prop_collection_foreach_get_doc, ); 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); } @@ -3974,7 +4151,7 @@ PyDoc_STRVAR(pyrna_prop_collection_foreach_set_doc, ); 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); } @@ -3988,7 +4165,7 @@ static PyObject *pyrna_prop_array_iter(BPy_PropertyArrayRNA *self) 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); @@ -4130,8 +4307,8 @@ static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject * /* 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)) { - +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)) @@ -4696,7 +4873,11 @@ PyTypeObject pyrna_struct_meta_idprop_Type= { NULL, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ NULL, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ +#if defined(_MSC_VER) || defined(FREE_WINDOWS) + NULL, /* defer assignment */ +#else + &PyType_Type, /* struct _typeobject *tp_base; */ +#endif NULL, /* PyObject *tp_dict; */ NULL, /* descrgetfunc tp_descr_get; */ NULL, /* descrsetfunc tp_descr_set; */ @@ -5267,7 +5448,11 @@ PyTypeObject pyrna_prop_collection_iter_Type= { NULL, /* reprfunc tp_str; */ /* will only use these if this is a subtype of a py class */ +#if defined(_MSC_VER) || defined(FREE_WINDOWS) + NULL, /* defer assignment */ +#else PyObject_GenericGetAttr, /* getattrofunc tp_getattro; */ +#endif NULL, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ @@ -5296,7 +5481,11 @@ PyTypeObject pyrna_prop_collection_iter_Type= { #endif /*** Added in release 2.2 ***/ /* Iterators */ +#if defined(_MSC_VER) || defined(FREE_WINDOWS) + NULL, /* defer assignment */ +#else PyObject_SelfIter, /* getiterfunc tp_iter; */ +#endif (iternextfunc) pyrna_prop_collection_iter_next, /* iternextfunc tp_iternext; */ /*** Attribute descriptor and subclassing stuff ***/ @@ -5682,8 +5871,15 @@ void BPY_rna_init(void) mathutils_rna_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_rna_matrix_cb); #endif - /* metaclass */ + /* for some reason MSVC complains of these */ +#if defined(_MSC_VER) || defined(FREE_WINDOWS) 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; +#endif + + /* metaclass */ if(PyType_Ready(&pyrna_struct_meta_idprop_Type) < 0) return; @@ -5728,7 +5924,11 @@ PyObject *BPY_rna_module(void) void BPY_update_rna_module(void) { +#if 0 RNA_main_pointer_create(G.main, rna_module_ptr); +#else + rna_module_ptr->data= G.main; /* just set data is enough */ +#endif } #if 0 @@ -6228,7 +6428,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param ParameterIterator iter; PointerRNA funcptr; int err= 0, i, flag, ret_len=0; - int is_static= RNA_function_flag(func) & FUNC_NO_SELF; + const char is_static= (RNA_function_flag(func) & FUNC_NO_SELF) != 0; + + /* annoying!, need to check if the screen gets set to NULL which is a + * hint that the file was actually re-loaded. */ + char is_valid_wm; PropertyRNA *pret_single= NULL; void *retdata_single= NULL; @@ -6255,6 +6459,8 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param if(C==NULL) C= BPy_GetContext(); + is_valid_wm= (CTX_wm_manager(C) != NULL); + bpy_context_set(C, &gilstate); if (!is_static) { @@ -6488,7 +6694,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param if(err != 0) { ReportList *reports; /* alert the user, else they wont know unless they see the console. */ - if (!is_static && ptr->data && RNA_struct_is_a(ptr->type, &RNA_Operator)) { + if ( (!is_static) && + (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; } diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 30f6c02115a..502fa25c872 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -44,9 +44,6 @@ /* support for inter references, currently only needed for corner case */ #define USE_PYRNA_STRUCT_REFERENCE -/* use real collection iterators rather than faking with a list */ -#define USE_PYRNA_ITER - #else /* WITH_PYTHON_SAFETY */ /* default, no defines! */ @@ -67,6 +64,11 @@ * so prefer the leak to the memory bloat for now. */ // #define PYRNA_FREE_SUPPORT +/* use real collection iterators rather than faking with a list + * this is needed so enums can be iterated over without crashing, + * since finishing the iteration frees temp allocated enums */ +#define USE_PYRNA_ITER + /* --- end bpy build options --- */ struct ID; diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index 8bde1db96ca..c87a141f5bd 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -189,7 +189,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb float cfra= FLT_MAX; const char *group_name= NULL; - PYRNA_STRUCT_CHECK_OBJ(self) + PYRNA_STRUCT_CHECK_OBJ(self); if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()", @@ -237,7 +237,7 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb float cfra= FLT_MAX; const char *group_name= NULL; - PYRNA_STRUCT_CHECK_OBJ(self) + PYRNA_STRUCT_CHECK_OBJ(self); if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_delete()", @@ -273,14 +273,14 @@ char pyrna_struct_driver_add_doc[] = " :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:`FCurve` or list if index is -1 with an array property.\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) + PYRNA_STRUCT_CHECK_OBJ(self); if (!PyArg_ParseTuple(args, "s|i:driver_add", &path, &index)) return NULL; @@ -356,7 +356,7 @@ PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args) 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; diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index e50ce233671..cab57724d6d 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -61,12 +61,12 @@ typedef void (*RNA_SetIndexFunc)(PointerRNA *, PropertyRNA *, int index, void *) static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[], ItemTypeCheckFunc check_item_type, const char *item_type_str, const char *error_prefix) { - int i; + 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); + const Py_ssize_t seq_size= PySequence_Size(seq); if(seq_size == -1) { PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'", error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name); @@ -147,8 +147,8 @@ static int count_items(PyObject *seq, int dim) int totitem= 0; if(dim > 1) { - const int seq_size= PySequence_Size(seq); - int i; + 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) { @@ -281,9 +281,9 @@ static char *copy_value_single(PyObject *item, PointerRNA *ptr, PropertyRNA *pro static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int dim, char *data, unsigned int item_size, int *index, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index) { - unsigned int i; int totdim= RNA_property_array_dimension(ptr, prop, NULL); - const int seq_size= PySequence_Size(seq); + const Py_ssize_t seq_size= PySequence_Size(seq); + Py_ssize_t i; /* Regarding PySequence_GetItem() failing. * diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 50b75b09cb2..9adeae9dc29 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -94,11 +94,11 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject * #if 1 /* approx 6x speedup for mathutils types */ int size; - if( (VectorObject_Check(value) && (size= ((VectorObject *)value)->size)) || - (EulerObject_Check(value) && (size= 3)) || - (QuaternionObject_Check(value) && (size= 4)) || - (ColorObject_Check(value) && (size= 3)) - ) { + if( (size= VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || + (size= EulerObject_Check(value) ? 3 : 0) || + (size= QuaternionObject_Check(value) ? 4 : 0) || + (size= ColorObject_Check(value) ? 3 : 0)) + { if(BaseMath_ReadCallback((BaseMathObject *)value) == -1) { return -1; } diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 947e4425d3f..9d1cfb1948a 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -193,7 +193,7 @@ static PyObject *Quaternion_dot(QuaternionObject *self, PyObject *value) } PyDoc_STRVAR(Quaternion_rotation_difference_doc, -".. function:: difference(other)\n" +".. function:: rotation_difference(other)\n" "\n" " Returns a quaternion representing the rotational difference.\n" "\n" |