diff options
Diffstat (limited to 'source/blender/python/intern/bpy_rna.c')
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 1286 |
1 files changed, 808 insertions, 478 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index b0ae13640ba..c21fbaae9c0 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -21,21 +21,23 @@ * * ***** END GPL LICENSE BLOCK ***** */ +#include <float.h> /* FLT_MIN/MAX */ #include "bpy_rna.h" #include "bpy_props.h" #include "bpy_util.h" #include "bpy_rna_callback.h" -//#include "blendef.h" + #include "BLI_dynstr.h" +#include "BLI_string.h" #include "BLI_listbase.h" -#include "float.h" /* FLT_MIN/MAX */ +#include "BLI_utildefines.h" #include "RNA_enum_types.h" #include "RNA_define.h" /* RNA_def_property_free_identifier */ #include "MEM_guardedalloc.h" -#include "BKE_utildefines.h" + #include "BKE_idcode.h" #include "BKE_context.h" #include "BKE_global.h" /* evil G.* */ @@ -49,20 +51,63 @@ #include "DNA_anim_types.h" #include "ED_keyframing.h" +#include "../generic/IDProp.h" /* for IDprop lookups */ +#include "../generic/py_capi_utils.h" + +#define USE_PEDANTIC_WRITE #define USE_MATHUTILS #define USE_STRING_COERCE +static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self); + +#ifdef USE_PEDANTIC_WRITE +static short rna_disallow_writes= FALSE; + +static int 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)) { /* 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_RuntimeError, "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 +int pyrna_write_check(void) +{ + return !rna_disallow_writes; +} +#else // USE_PEDANTIC_WRITE +int pyrna_write_check(void) +{ + return TRUE; +} +#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 deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item); + #ifdef USE_MATHUTILS #include "../generic/mathutils.h" /* so we can have mathutils callbacks */ -#include "../generic/IDProp.h" /* for IDprop lookups */ -#include "../generic/py_capi_utils.h" -static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, void *data, PyObject *value, const char *error_prefix); -static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length); -static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self); -static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self); +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, PropertyRNA **prop_eul_order, short order_fallback); -static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item); /* bpyrna vector/euler/quat callbacks */ static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */ @@ -84,16 +129,16 @@ static int mathutils_rna_vector_get(BaseMathObject *bmo, int subtype) BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; if(self->prop==NULL) return 0; - + 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, &prop_eul_order, eul->order); } - + return 1; } @@ -103,7 +148,13 @@ static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype) float min, max; if(self->prop==NULL) return 0; - + +#ifdef USE_PEDANTIC_WRITE + if(rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return 0; + } +#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 0; @@ -119,7 +170,9 @@ static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype) } RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); - 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); + } /* Euler order exception */ if(subtype==MATHUTILS_CB_SUBTYPE_EUL) { @@ -128,30 +181,38 @@ static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype) short order= pyrna_rotation_euler_order_get(&self->ptr, &prop_eul_order, eul->order); if(order != eul->order) { RNA_property_enum_set(&self->ptr, prop_eul_order, eul->order); - RNA_property_update(BPy_GetContext(), &self->ptr, prop_eul_order); + if(RNA_property_update_check(prop_eul_order)) { + RNA_property_update(BPy_GetContext(), &self->ptr, prop_eul_order); + } } } return 1; } -static int mathutils_rna_vector_get_index(BaseMathObject *bmo, int subtype, int index) +static int mathutils_rna_vector_get_index(BaseMathObject *bmo, int UNUSED(subtype), int index) { BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; if(self->prop==NULL) return 0; - + bmo->data[index]= RNA_property_float_get_index(&self->ptr, self->prop, index); return 1; } -static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int subtype, int index) +static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int UNUSED(subtype), int index) { BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; if(self->prop==NULL) return 0; - + +#ifdef USE_PEDANTIC_WRITE + if(rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return 0; + } +#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 0; @@ -159,7 +220,11 @@ static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int subtype, int 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_update(BPy_GetContext(), &self->ptr, self->prop); + + if(RNA_property_update_check(self->prop)) { + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + } + return 1; } @@ -175,7 +240,7 @@ Mathutils_Callback mathutils_rna_array_cb = { /* bpyrna matrix callbacks */ static int mathutils_rna_matrix_cb_index= -1; /* index for our callbacks */ -static int mathutils_rna_matrix_get(BaseMathObject *bmo, int subtype) +static int mathutils_rna_matrix_get(BaseMathObject *bmo, int UNUSED(subtype)) { BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; @@ -186,21 +251,30 @@ static int mathutils_rna_matrix_get(BaseMathObject *bmo, int subtype) return 1; } -static int mathutils_rna_matrix_set(BaseMathObject *bmo, int subtype) +static int mathutils_rna_matrix_set(BaseMathObject *bmo, int UNUSED(subtype)) { BPy_PropertyRNA *self= (BPy_PropertyRNA *)bmo->cb_user; - + if(self->prop==NULL) return 0; - + +#ifdef USE_PEDANTIC_WRITE + if(rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return 0; + } +#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 0; } - + /* can ignore clamping here */ RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); - 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 1; } @@ -212,19 +286,23 @@ Mathutils_Callback mathutils_rna_matrix_cb = { NULL }; -/* same as RNA_enum_value_from_id but raises an exception */ -int pyrna_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value, const char *error_prefix) +static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_eul_order, short order_fallback) { - if(RNA_enum_value_from_id(item, identifier, value) == 0) { - char *enum_str= BPy_enum_as_string(item); - PyErr_Format(PyExc_TypeError, "%s: '%.200s' not found in (%s)", error_prefix, identifier, enum_str); - MEM_freeN(enum_str); - return -1; + /* attempt to get order */ + if(*prop_eul_order==NULL) + *prop_eul_order= RNA_struct_find_property(ptr, "rotation_mode"); + + if(*prop_eul_order) { + short order= RNA_property_enum_get(ptr, *prop_eul_order); + if (order >= ROT_MODE_XYZ && order <= ROT_MODE_ZYX) /* could be quat or axisangle */ + return order; } - return 0; + return order_fallback; } +#endif // USE_MATHUTILS + #define PROP_ALL_VECTOR_SUBTYPES 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) @@ -293,7 +371,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) case PROP_QUATERNION: if(len==3) { /* euler */ if(is_thick) { - /* attempt to get order, only needed for thixk types since wrapped with update via callbacks */ + /* 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, &prop_eul_order, ROT_MODE_XYZ); @@ -345,27 +423,25 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the Mathutils PyObject */ } } - -#endif +#else // USE_MATHUTILS + (void)ptr; + (void)prop; +#endif // USE_MATHUTILS return ret; } -#endif - -static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_eul_order, short order_fallback) +/* same as RNA_enum_value_from_id but raises an exception */ +int pyrna_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value, const char *error_prefix) { - /* attempt to get order */ - if(*prop_eul_order==NULL) - *prop_eul_order= RNA_struct_find_property(ptr, "rotation_mode"); - - if(*prop_eul_order) { - short order= RNA_property_enum_get(ptr, *prop_eul_order); - if (order >= ROT_MODE_XYZ && order <= ROT_MODE_ZYX) /* could be quat or axisangle */ - return order; + if(RNA_enum_value_from_id(item, identifier, value) == 0) { + const char *enum_str= BPy_enum_as_string(item); + PyErr_Format(PyExc_TypeError, "%s: '%.200s' not found in (%s)", error_prefix, identifier, enum_str); + MEM_freeN((void *)enum_str); + return -1; } - return order_fallback; + return 0; } static int pyrna_struct_compare( BPy_StructRNA * a, BPy_StructRNA * b ) @@ -440,13 +516,13 @@ static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op) static PyObject *pyrna_struct_str( BPy_StructRNA *self ) { PyObject *ret; - char *name; + const char *name; /* print name if available */ name= RNA_struct_name_get_alloc(&self->ptr, NULL, FALSE); if(name) { ret= PyUnicode_FromFormat( "<bpy_struct, %.200s(\"%.200s\")>", RNA_struct_identifier(self->ptr.type), name); - MEM_freeN(name); + MEM_freeN((void *)name); return ret; } @@ -458,22 +534,22 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self) ID *id= self->ptr.id.data; if(id == NULL) return pyrna_struct_str(self); /* fallback */ - + if(RNA_struct_is_ID(self->ptr.type)) { return PyUnicode_FromFormat( "bpy.data.%s[\"%s\"]", BKE_idcode_to_name_plural(GS(id->name)), id->name+2); } else { PyObject *ret; - char *path; + const char *path; path= RNA_path_from_ID_to_struct(&self->ptr); if(path) { ret= PyUnicode_FromFormat( "bpy.data.%s[\"%s\"].%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, path); - MEM_freeN(path); + MEM_freeN((void *)path); } else { /* cant find, print something sane */ ret= PyUnicode_FromFormat( "bpy.data.%s[\"%s\"]...%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, RNA_struct_identifier(self->ptr.type)); } - + return ret; } } @@ -482,7 +558,7 @@ static PyObject *pyrna_prop_str( BPy_PropertyRNA *self ) { PyObject *ret; PointerRNA ptr; - char *name; + const char *name; const char *type_id= NULL; char type_fmt[64]= ""; int type= RNA_property_type(self->prop); @@ -515,7 +591,7 @@ static PyObject *pyrna_prop_str( BPy_PropertyRNA *self ) 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(name); + MEM_freeN((void *)name); return ret; } } @@ -527,20 +603,20 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self) { ID *id= self->ptr.id.data; PyObject *ret; - char *path; - + const char *path; + if(id == NULL) return pyrna_prop_str(self); /* fallback */ - + path= RNA_path_from_ID_to_property(&self->ptr, self->prop); if(path) { ret= PyUnicode_FromFormat( "bpy.data.%s[\"%s\"].%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, path); - MEM_freeN(path); + MEM_freeN((void *)path); } else { /* cant find, print something sane */ ret= PyUnicode_FromFormat( "bpy.data.%s[\"%s\"]...%s", BKE_idcode_to_name_plural(GS(id->name)), id->name+2, RNA_property_identifier(self->prop)); } - + return ret; } @@ -551,7 +627,7 @@ static long pyrna_struct_hash( BPy_StructRNA *self ) /* 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; @@ -583,12 +659,12 @@ static void pyrna_struct_dealloc( BPy_StructRNA *self ) return; } -static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) +static const char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) { EnumPropertyItem *item; - char *result; + const char *result; int free= FALSE; - + RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); if(item) { result= BPy_enum_as_string(item); @@ -596,28 +672,28 @@ static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) else { result= ""; } - + if(free) MEM_freeN(item); - + return result; } static int pyrna_string_to_enum(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *val, const char *error_prefix) { - char *param= _PyUnicode_AsString(item); + const char *param= _PyUnicode_AsString(item); if (param==NULL) { - char *enum_str= pyrna_enum_as_string(ptr, prop); + const char *enum_str= pyrna_enum_as_string(ptr, prop); PyErr_Format(PyExc_TypeError, "%.200s expected a string enum type in (%.200s)", error_prefix, enum_str); - MEM_freeN(enum_str); + MEM_freeN((void *)enum_str); return 0; } else { if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, val)) { - char *enum_str= pyrna_enum_as_string(ptr, prop); + const char *enum_str= pyrna_enum_as_string(ptr, prop); PyErr_Format(PyExc_TypeError, "%.200s enum \"%.200s\" not found in (%.200s)", error_prefix, param, enum_str); - MEM_freeN(enum_str); + MEM_freeN((void *)enum_str); return 0; } } @@ -638,7 +714,7 @@ int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_ *r_value= 0; while (_PySet_NextEntry(value, &pos, &key, &hash)) { - char *param= _PyUnicode_AsString(key); + const char *param= _PyUnicode_AsString(key); if(param==NULL) { PyErr_Format(PyExc_TypeError, "%.200s expected a string. found a %.200s", error_prefix, Py_TYPE(key)->tp_name); @@ -669,7 +745,7 @@ static int pyrna_prop_to_enum_bitfield(PointerRNA *ptr, PropertyRNA *prop, PyObj } 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)); + PyErr_Format(PyExc_TypeError, "%.200s: empty enum \"%.200s\" could not have any values assigned", error_prefix, RNA_property_identifier(prop)); ret= -1; } else { @@ -736,7 +812,7 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val) ret= PyUnicode_FromString(item->identifier); } else { - char *ptr_name= RNA_struct_name_get_alloc(ptr, NULL, FALSE); + const char *ptr_name= RNA_struct_name_get_alloc(ptr, NULL, FALSE); /* prefer not fail silently incase of api errors, maybe disable it later */ printf("RNA Warning: Current value \"%d\" matches no enum in '%s', '%s', '%s'\n", val, RNA_struct_identifier(ptr->type), ptr_name, RNA_property_identifier(prop)); @@ -748,9 +824,9 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val) #endif if(ptr_name) - MEM_freeN(ptr_name); + MEM_freeN((void *)ptr_name); - ret = PyUnicode_FromString( "" ); + ret = PyUnicode_FromString(""); } if(free) @@ -772,7 +848,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) if (RNA_property_array_check(ptr, prop)) { return pyrna_py_from_array(ptr, prop); } - + /* see if we can coorce into a python type - PropertyType */ switch (type) { case PROP_BOOLEAN: @@ -787,7 +863,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) case PROP_STRING: { int subtype= RNA_property_subtype(prop); - char *buf; + const char *buf; buf = RNA_property_string_get_alloc(ptr, prop, NULL, -1); #ifdef USE_STRING_COERCE /* only file paths get special treatment, they may contain non utf-8 chars */ @@ -797,10 +873,10 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) else { ret= PyUnicode_FromString(buf); } -#else +#else // USE_STRING_COERCE ret= PyUnicode_FromString(buf); -#endif - MEM_freeN(buf); +#endif // USE_STRING_COERCE + MEM_freeN((void *)buf); break; } case PROP_ENUM: @@ -828,7 +904,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) ret = NULL; break; } - + return ret; } @@ -849,7 +925,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha if (strcmp(arg_name, "rna_type")==0) continue; if (kw==NULL) { - PyErr_Format( PyExc_TypeError, "%.200s: no keywords, expected \"%.200s\"", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); + PyErr_Format(PyExc_TypeError, "%.200s: no keywords, expected \"%.200s\"", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); error_val= -1; break; } @@ -858,12 +934,12 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha if (item == NULL) { if(all_args) { - PyErr_Format( PyExc_TypeError, "%.200s: keyword \"%.200s\" missing", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); + 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, NULL, item, error_prefix)) { + if (pyrna_py_to_prop(ptr, prop, NULL, item, error_prefix)) { error_val= -1; break; } @@ -882,7 +958,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha arg_name= NULL; } - PyErr_Format( PyExc_TypeError, "%.200s: keyword \"%.200s\" unrecognized", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); + PyErr_Format(PyExc_TypeError, "%.200s: keyword \"%.200s\" unrecognized", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); error_val = -1; } @@ -896,32 +972,32 @@ static PyObject *pyrna_func_to_py(BPy_DummyPointerRNA *pyrna, FunctionRNA *func) static PyMethodDef func_meth = {"<generic rna function>", (PyCFunction)pyrna_func_call, METH_VARARGS|METH_KEYWORDS, "python rna function"}; PyObject *self; PyObject *ret; - + if(func==NULL) { - PyErr_Format( PyExc_RuntimeError, "%.200s: type attempted to get NULL function", RNA_struct_identifier(pyrna->ptr.type)); + PyErr_Format(PyExc_RuntimeError, "%.200s: type attempted to get NULL function", RNA_struct_identifier(pyrna->ptr.type)); return NULL; } self= PyTuple_New(2); - + PyTuple_SET_ITEM(self, 0, (PyObject *)pyrna); Py_INCREF(pyrna); PyTuple_SET_ITEM(self, 1, PyCapsule_New((void *)func, NULL, NULL)); - + ret= PyCFunction_New(&func_meth, self); Py_DECREF(self); - + return ret; } -static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *parms, 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) { /* XXX hard limits should be checked here */ int type = RNA_property_type(prop); - + if (RNA_property_array_check(ptr, prop)) { @@ -934,13 +1010,13 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p if(!BaseMath_ReadCallback(mat)) return -1; } else /* continue... */ -#endif +#endif // USE_MATHUTILS if (!PySequence_Check(value)) { - PyErr_Format(PyExc_TypeError, "%.200s RNA array assignment to %.200s.%.200s expected a sequence instead of %.200s instance.", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), Py_TYPE(value)->tp_name); + PyErr_Format(PyExc_TypeError, "%.200s RNA array assignment to %.200s.%.200s expected a sequence instead of %.200s instance", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), Py_TYPE(value)->tp_name); return -1; } /* done getting the length */ - ok= pyrna_py_to_array(ptr, prop, parms, data, value, error_prefix); + ok= pyrna_py_to_array(ptr, prop, data, value, error_prefix); if (!ok) { /* PyErr_Format(PyExc_AttributeError, "%.200s %s", error_prefix, error_str); */ @@ -949,7 +1025,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p } else { /* Normal Property (not an array) */ - + /* see if we can coorce into a python type - PropertyType */ switch (type) { case PROP_BOOLEAN: @@ -961,9 +1037,9 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p if(RNA_property_flag(prop) & PROP_OUTPUT) param = PyObject_IsTrue( value ); else - param = PyLong_AsSsize_t( value ); - - if( param < 0 || param > 1) { + param = PyLong_AsLong( value ); + + if(param < 0) { PyErr_Format(PyExc_TypeError, "%.200s %.200s.%.200s expected True/False or 0/1", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop)); return -1; } else { @@ -974,14 +1050,20 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p } case PROP_INT: { - int param = PyLong_AsSsize_t(value); - if (param==-1 && PyErr_Occurred()) { + int overflow; + long param= PyLong_AsLongAndOverflow(value, &overflow); + if(overflow || (param > INT_MAX) || (param < INT_MIN)) { + PyErr_Format(PyExc_TypeError, "%.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", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop)); return -1; } else { - RNA_property_int_clamp(ptr, prop, ¶m); - if(data) *((int*)data)= param; - else RNA_property_int_set(ptr, prop, param); + int param_i= (int)param; + RNA_property_int_clamp(ptr, prop, ¶m_i); + if(data) *((int*)data)= param_i; + else RNA_property_int_set(ptr, prop, param_i); } break; } @@ -1005,14 +1087,15 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p PyObject *value_coerce= NULL; int subtype= RNA_property_subtype(prop); if(ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - param= PuC_UnicodeAsByte(value, &value_coerce); + /* TODO, get size */ + param= PyC_UnicodeAsByte(value, &value_coerce); } else { param= _PyUnicode_AsString(value); } -#else - param= _PyUnicode_AsString(value); -#endif +#else // USE_STRING_COERCE + param= _PyUnicode_AsStringSize(value); +#endif // USE_STRING_COERCE if (param==NULL) { PyErr_Format(PyExc_TypeError, "%.200s %.200s.%.200s expected a string type", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop)); @@ -1024,7 +1107,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p } #ifdef USE_STRING_COERCE Py_XDECREF(value_coerce); -#endif +#endif // USE_STRING_COERCE break; } case PROP_ENUM: @@ -1047,21 +1130,21 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p } } else { - char *enum_str= pyrna_enum_as_string(ptr, prop); + const char *enum_str= pyrna_enum_as_string(ptr, prop); PyErr_Format(PyExc_TypeError, "%.200s %.200s.%.200s expected a string enum or a set of strings in (%.2000s)", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), enum_str); - MEM_freeN(enum_str); + MEM_freeN((void *)enum_str); return -1; } if(data) *((int*)data)= val; else RNA_property_enum_set(ptr, prop, val); - + break; } case PROP_POINTER: { PyObject *value_new= NULL; - + StructRNA *ptype= RNA_property_pointer_type(ptr, prop); int flag = RNA_property_flag(prop); @@ -1069,10 +1152,10 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p * layout.prop(self, "filepath") * ... which infact 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. */ @@ -1138,8 +1221,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p else { /* data==NULL, assign to RNA */ if(value == Py_None) { - PointerRNA valueptr; - memset(&valueptr, 0, sizeof(valueptr)); + PointerRNA valueptr= {{0}}; RNA_property_pointer_set(ptr, prop, valueptr); } else if(RNA_struct_is_a(param->ptr.type, ptype)) { @@ -1152,7 +1234,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p Py_XDECREF(value_new); return -1; } } - + if(raise_error) { PointerRNA tmp; RNA_pointer_create(NULL, ptype, NULL, &tmp); @@ -1160,7 +1242,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p Py_XDECREF(value_new); return -1; } } - + Py_XDECREF(value_new); break; @@ -1174,14 +1256,14 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p 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, found a '%.200s' instead", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), Py_TYPE(value)->tp_name); return -1; } - seq_len = PySequence_Length(value); + seq_len = PySequence_Size(value); for(i=0; i<seq_len; i++) { item= PySequence_GetItem(value, i); @@ -1207,7 +1289,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p if(pyrna_pydict_to_props(&itemptr, item, 1, "Converting a python list to an RNA collection")==-1) { PyObject *msg= PyC_ExceptionBuffer(); - char *msg_char= _PyUnicode_AsString(msg); + 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); @@ -1217,7 +1299,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p } Py_DECREF(item); } - + break; } default: @@ -1228,7 +1310,9 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, ParameterList *p } /* Run rna property functions */ - RNA_property_update(BPy_GetContext(), ptr, prop); + if(RNA_property_update_check(prop)) { + RNA_property_update(BPy_GetContext(), ptr, prop); + } return 0; } @@ -1241,12 +1325,10 @@ static PyObject * pyrna_prop_array_to_py_index(BPy_PropertyArrayRNA *self, int i static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, PyObject *value) { int ret = 0; - int totdim; PointerRNA *ptr= &self->ptr; PropertyRNA *prop= self->prop; - int type = RNA_property_type(prop); - totdim= RNA_property_array_dimension(ptr, prop, NULL); + const int totdim= RNA_property_array_dimension(ptr, prop, NULL); if (totdim > 1) { /* char error_str[512]; */ @@ -1257,11 +1339,11 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P } else { /* see if we can coorce into a python type - PropertyType */ - switch (type) { + switch (RNA_property_type(prop)) { case PROP_BOOLEAN: { - int param = PyLong_AsSsize_t( value ); - + int param = PyLong_AsLong( value ); + if( param < 0 || param > 1) { PyErr_SetString(PyExc_TypeError, "expected True/False or 0/1"); ret = -1; @@ -1272,7 +1354,7 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P } case PROP_INT: { - int param = PyLong_AsSsize_t(value); + int param = PyLong_AsLong(value); if (param==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "expected an int type"); ret = -1; @@ -1302,8 +1384,10 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P } /* Run rna property functions */ - RNA_property_update(BPy_GetContext(), ptr, prop); - + if(RNA_property_update_check(prop)) { + RNA_property_update(BPy_GetContext(), ptr, prop); + } + return ret; } @@ -1344,20 +1428,34 @@ static int pyrna_prop_collection_bool( BPy_PropertyRNA *self ) static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum) { PointerRNA newptr; - int len= RNA_property_collection_length(&self->ptr, self->prop); + Py_ssize_t keynum_abs= keynum; - if(keynum < 0) keynum += len; + /* 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; + } + } - if(keynum >= 0 && keynum < len) { - if(RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr)) { - return pyrna_struct_CreatePyObject(&newptr); + 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 { /* fail's if ptr.data == NULL, valid for mesh.materials */ - Py_RETURN_NONE; + 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; } - PyErr_Format(PyExc_IndexError, "bpy_prop_collection[index]: index %d out of range, size %d", keynum, len); - return NULL; } static PyObject *pyrna_prop_array_subscript_int(BPy_PropertyArrayRNA *self, int keynum) @@ -1384,26 +1482,37 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons } /* static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) */ -static PyObject *pyrna_prop_collection_subscript_slice(PointerRNA *ptr, PropertyRNA *prop, int start, int stop, int length) +static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py_ssize_t start, Py_ssize_t stop) { - PointerRNA newptr; - PyObject *list = PyList_New(stop - start); - int count; + int count= 0; - start = MIN2(start,stop); /* values are clamped from */ + PyObject *list= PyList_New(0); + PyObject *item; - for(count = start; count < stop; count++) { - if(RNA_property_collection_lookup_int(ptr, prop, count - start, &newptr)) { - PyList_SET_ITEM(list, count - start, pyrna_struct_CreatePyObject(&newptr)); + /* first loop up-until the start */ + CollectionPropertyIterator rna_macro_iter; + for(RNA_property_collection_begin(&self->ptr, self->prop, &rna_macro_iter); rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) { + /* PointerRNA itemptr= rna_macro_iter.ptr; */ + if(count == start) { + break; } - else { - Py_DECREF(list); + count++; + } - PyErr_SetString(PyExc_RuntimeError, "error getting an rna struct from a collection"); - return NULL; + /* add items until stop */ + for(; rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) { + item= pyrna_struct_CreatePyObject(&rna_macro_iter.ptr); + PyList_Append(list, item); + Py_DECREF(item); + + count++; + if(count == stop) { + break; } } + RNA_property_collection_end(&rna_macro_iter); + return list; } @@ -1411,17 +1520,17 @@ static PyObject *pyrna_prop_collection_subscript_slice(PointerRNA *ptr, Property * 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, int start, int stop, int length) +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 *list = PyList_New(stop - start); + PyObject *tuple= PyTuple_New(stop - start); totdim = RNA_property_array_dimension(ptr, prop, NULL); if (totdim > 1) { for (count = start; count < stop; count++) - PyList_SET_ITEM(list, count - start, pyrna_prop_array_to_py_index(self, count)); + PyTuple_SET_ITEM(tuple, count - start, pyrna_prop_array_to_py_index(self, count)); } else { switch (RNA_property_type(prop)) { @@ -1432,9 +1541,9 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po 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++) - PyList_SET_ITEM(list, count-start, PyFloat_FromDouble(values[count])); + PyTuple_SET_ITEM(tuple, count-start, PyFloat_FromDouble(values[count])); if(values != values_stack) { PyMem_FREE(values); @@ -1450,7 +1559,7 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po RNA_property_boolean_get_array(ptr, prop, values); for(count=start; count<stop; count++) - PyList_SET_ITEM(list, count-start, PyBool_FromLong(values[count])); + PyTuple_SET_ITEM(tuple, count-start, PyBool_FromLong(values[count])); if(values != values_stack) { PyMem_FREE(values); @@ -1466,7 +1575,7 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po RNA_property_int_get_array(ptr, prop, values); for(count=start; count<stop; count++) - PyList_SET_ITEM(list, count-start, PyLong_FromSsize_t(values[count])); + PyTuple_SET_ITEM(tuple, count-start, PyLong_FromSsize_t(values[count])); if(values != values_stack) { PyMem_FREE(values); @@ -1474,13 +1583,14 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po break; } default: - /* probably will never happen */ + BLI_assert(!"Invalid array type"); + PyErr_SetString(PyExc_TypeError, "not an array type"); - Py_DECREF(list); - list= NULL; + Py_DECREF(tuple); + tuple= NULL; } } - return list; + return tuple; } static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject *key) @@ -1496,25 +1606,43 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject return pyrna_prop_collection_subscript_int(self, i); } else if (PySlice_Check(key)) { - int len= RNA_property_collection_length(&self->ptr, self->prop); - Py_ssize_t start, stop, step, slicelength; + PySliceObject *key_slice= (PySliceObject *)key; + Py_ssize_t step= 1; - if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) + if(key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { return NULL; - - if (slicelength <= 0) { - return PyList_New(0); } - else if (step == 1) { - return pyrna_prop_collection_subscript_slice(&self->ptr, self->prop, start, stop, len); + 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 { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported with rna"); - return NULL; + 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); + } } } else { - PyErr_Format(PyExc_TypeError, "bpy_prop_collection[key]: invalid key, must be a string or an int instead of %.200s instance.", Py_TYPE(key)->tp_name); + PyErr_Format(PyExc_TypeError, "bpy_prop_collection[key]: invalid key, must be a string or an int instead of %.200s instance", Py_TYPE(key)->tp_name); return NULL; } } @@ -1528,24 +1656,37 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return NULL; - return pyrna_prop_array_subscript_int(self, PyLong_AsSsize_t(key)); + return pyrna_prop_array_subscript_int(self, PyLong_AsLong(key)); } else if (PySlice_Check(key)) { - Py_ssize_t start, stop, step, slicelength; - int len = pyrna_prop_array_length(self); + Py_ssize_t step= 1; + PySliceObject *key_slice= (PySliceObject *)key; - if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) + if(key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { return NULL; - - if (slicelength <= 0) { - return PyList_New(0); } - else if (step == 1) { - return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, start, stop, len); + 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 { - PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]: slice steps not supported with rna"); - return NULL; + int len= pyrna_prop_array_length(self); + Py_ssize_t start, stop, slicelength; + + if (PySlice_GetIndicesEx((void *)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 { @@ -1563,7 +1704,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, in 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."); + PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice] = value: deleting with list types is not supported by bpy_struct"); return -1; } @@ -1573,7 +1714,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, in if(PySequence_Fast_GET_SIZE(value) != stop-start) { Py_DECREF(value); - PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice] = value: resizing bpy_struct arrays isn't supported."); + PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice] = value: resizing bpy_struct arrays isn't supported"); return -1; } @@ -1590,7 +1731,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, in else { values= values_stack; } if(start != 0 || stop != length) /* partial assignment? - need to get the array */ RNA_property_float_get_array(ptr, prop, values); - + for(count=start; count<stop; count++) { fval = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, count-start)); CLAMP(fval, min, max); @@ -1610,9 +1751,9 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, in if(start != 0 || stop != length) /* partial assignment? - need to get the array */ RNA_property_boolean_get_array(ptr, prop, values); - + for(count=start; count<stop; count++) - values[count] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, count-start)); + values[count] = PyLong_AsLong(PySequence_Fast_GET_ITEM(value, count-start)); if(PyErr_Occurred()) ret= -1; else RNA_property_boolean_set_array(ptr, prop, values); @@ -1633,7 +1774,7 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, in RNA_property_int_get_array(ptr, prop, values); for(count=start; count<stop; count++) { - ival = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, count-start)); + ival = PyLong_AsLong(PySequence_Fast_GET_ITEM(value, count-start)); CLAMP(ival, min, max); values[count] = ival; } @@ -1648,11 +1789,11 @@ static int prop_subscript_ass_array_slice(PointerRNA *ptr, PropertyRNA *prop, in } Py_DECREF(value); - + if(values_alloc) { PyMem_FREE(values_alloc); } - + return ret; } @@ -1693,7 +1834,7 @@ static int pyrna_prop_array_ass_subscript( BPy_PropertyArrayRNA *self, PyObject int len= RNA_property_array_length(&self->ptr, self->prop); Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0) { + if (PySlice_GetIndicesEx((void *)key, len, &start, &stop, &step, &slicelength) < 0) { ret= -1; } else if (slicelength <= 0) { @@ -1713,7 +1854,9 @@ static int pyrna_prop_array_ass_subscript( BPy_PropertyArrayRNA *self, PyObject } if(ret != -1) { - 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 ret; @@ -1768,7 +1911,7 @@ static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *value PointerRNA newptr; /* not used, just so RNA_property_collection_lookup_string runs */ /* key in dict style check */ - char *keyname = _PyUnicode_AsString(value); + const char *keyname = _PyUnicode_AsString(value); if(keyname==NULL) { PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.__contains__: expected a string"); @@ -1784,23 +1927,23 @@ static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *value static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value) { IDProperty *group; - char *name = _PyUnicode_AsString(value); + const char *name = _PyUnicode_AsString(value); if (!name) { - PyErr_SetString( PyExc_TypeError, "bpy_struct.__contains__: expected a string"); + 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 doesnt support IDProperties"); + PyErr_SetString(PyExc_TypeError, "bpy_struct: this type doesnt support IDProperties"); return -1; } group= RNA_struct_idprops(&self->ptr, 0); - + if(!group) return 0; - + return IDP_GetPropertyFromGroup(group, name) ? 1:0; } @@ -1847,29 +1990,29 @@ static PyObject *pyrna_struct_subscript( BPy_StructRNA *self, PyObject *key ) { /* mostly copied from BPy_IDGroup_Map_GetItem */ IDProperty *group, *idprop; - char *name= _PyUnicode_AsString(key); + const char *name= _PyUnicode_AsString(key); if(RNA_struct_idprops_check(self->ptr.type)==0) { - PyErr_SetString( PyExc_TypeError, "this type doesn't support IDProperties"); + 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"); + 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); if(group==NULL) { - PyErr_Format( PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); + PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); return NULL; } idprop= IDP_GetPropertyFromGroup(group, name); if(idprop==NULL) { - PyErr_Format( PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); + PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); return NULL; } @@ -1880,6 +2023,12 @@ static int pyrna_struct_ass_subscript( BPy_StructRNA *self, PyObject *key, PyObj { IDProperty *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_STRING_COERCE + if(group==NULL) { PyErr_SetString(PyExc_TypeError, "bpy_struct[key] = val: id properties not supported for this type"); return -1; @@ -1909,7 +2058,7 @@ static PyObject *pyrna_struct_keys(BPy_PropertyRNA *self) IDProperty *group; if(RNA_struct_idprops_check(self->ptr.type)==0) { - PyErr_SetString( PyExc_TypeError, "bpy_struct.keys(): this type doesn't support IDProperties"); + PyErr_SetString(PyExc_TypeError, "bpy_struct.keys(): this type doesn't support IDProperties"); return NULL; } @@ -1936,7 +2085,7 @@ static PyObject *pyrna_struct_items(BPy_PropertyRNA *self) IDProperty *group; if(RNA_struct_idprops_check(self->ptr.type)==0) { - PyErr_SetString( PyExc_TypeError, "bpy_struct.items(): this type doesn't support IDProperties"); + PyErr_SetString(PyExc_TypeError, "bpy_struct.items(): this type doesn't support IDProperties"); return NULL; } @@ -1963,7 +2112,7 @@ static PyObject *pyrna_struct_values(BPy_PropertyRNA *self) IDProperty *group; if(RNA_struct_idprops_check(self->ptr.type)==0) { - PyErr_SetString( PyExc_TypeError, "bpy_struct.values(): this type doesn't support IDProperties"); + PyErr_SetString(PyExc_TypeError, "bpy_struct.values(): this type doesn't support IDProperties"); return NULL; } @@ -1977,17 +2126,17 @@ static PyObject *pyrna_struct_values(BPy_PropertyRNA *self) /* for keyframes and drivers */ static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefix, const char *path, - char **path_full, int *index) + const char **path_full, int *index) { const int 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 r_index= -1; @@ -2003,13 +2152,13 @@ static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefi return -1; } } - else { + else { prop = RNA_struct_find_property(ptr, path); r_ptr= *ptr; - } + } if (prop==NULL) { - PyErr_Format( PyExc_TypeError, "%.200s property \"%s\" not found", error_prefix, path); + PyErr_Format(PyExc_TypeError, "%.200s property \"%s\" not found", error_prefix, path); return -1; } @@ -2030,19 +2179,19 @@ static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefi else { int array_len= RNA_property_array_length(&r_ptr, prop); if((*index) < -1 || (*index) >= array_len) { - PyErr_Format( PyExc_TypeError, "%.200s index out of range \"%s\", given %d, array length is %d", error_prefix, path, *index, array_len); + PyErr_Format(PyExc_TypeError, "%.200s index out of range \"%s\", given %d, array length is %d", error_prefix, path, *index, array_len); return -1; } } - + if(is_idbase) { *path_full= BLI_strdup(path); } else { *path_full= RNA_path_from_ID_to_property(&r_ptr, prop); - + if (*path_full==NULL) { - PyErr_Format( PyExc_TypeError, "%.200s could not make path to \"%s\"", error_prefix, path); + PyErr_Format(PyExc_TypeError, "%.200s could not make path to \"%s\"", error_prefix, path); return -1; } } @@ -2052,18 +2201,18 @@ static int pyrna_struct_anim_args_parse(PointerRNA *ptr, const char *error_prefi /* 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, - char **path_full, int *index, float *cfra, char **group_name) /* return values */ + const char **path_full, int *index, float *cfra, const char **group_name) /* return values */ { - static char *kwlist[] = {"data_path", "index", "frame", "group", NULL}; - char *path; + static const char *kwlist[] = {"data_path", "index", "frame", "group", NULL}; + const char *path; /* note, parse_str MUST start with 's|ifs' */ if (!PyArg_ParseTupleAndKeywords(args, kw, parse_str, (char **)kwlist, &path, index, cfra, group_name)) return -1; - if(pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) < 0) + if(pyrna_struct_anim_args_parse(ptr, error_prefix, path, path_full, index) < 0) return -1; - + if(*cfra==FLT_MAX) *cfra= CTX_data_scene(BPy_GetContext())->r.cfra; @@ -2077,7 +2226,7 @@ static char pyrna_struct_keyframe_insert_doc[] = "\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. Defaults to -1 which will key all indicies or a single channel if the property is not an array.\n" +" :arg index: array index of the property to key. 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" @@ -2088,20 +2237,29 @@ static char pyrna_struct_keyframe_insert_doc[] = static PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyObject *kw) { - PyObject *result; /* args, pyrna_struct_keyframe_parse handles these */ - char *path_full= NULL; + const char *path_full= NULL; int index= -1; float cfra= FLT_MAX; - char *group_name= NULL; + const char *group_name= NULL; - if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1) + if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_insert()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1) { return NULL; + } + else { + short result; + ReportList reports; - result= PyBool_FromLong(insert_keyframe((ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0)); - MEM_freeN(path_full); + BKE_reports_init(&reports, RPT_STORE); - return result; + result= insert_keyframe(&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, TRUE)) + return NULL; + + return PyBool_FromLong(result); + } } static char pyrna_struct_keyframe_delete_doc[] = @@ -2111,7 +2269,7 @@ static char pyrna_struct_keyframe_delete_doc[] = "\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 indicies or a single channel if the property is not an array.\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" @@ -2122,20 +2280,30 @@ static char pyrna_struct_keyframe_delete_doc[] = static PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyObject *kw) { - PyObject *result; /* args, pyrna_struct_keyframe_parse handles these */ - char *path_full= NULL; + const char *path_full= NULL; int index= -1; float cfra= FLT_MAX; - char *group_name= NULL; + const char *group_name= NULL; - if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_delete()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1) + if(pyrna_struct_keyframe_parse(&self->ptr, args, kw, "s|ifs:bpy_struct.keyframe_delete()", "bpy_struct.keyframe_insert()", &path_full, &index, &cfra, &group_name) == -1) { return NULL; + } + else { + short result; + ReportList reports; - result= PyBool_FromLong(delete_keyframe((ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0)); - MEM_freeN(path_full); + BKE_reports_init(&reports, RPT_STORE); + + result= delete_keyframe(&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, TRUE)) + return NULL; + + return PyBool_FromLong(result); + } - return result; } static char pyrna_struct_driver_add_doc[] = @@ -2145,55 +2313,68 @@ static char pyrna_struct_driver_add_doc[] = "\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 indicies or a single channel if the property is not an array.\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:`FCurve` or list if index is -1 with an array property."; static PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) { - char *path, *path_full; + const char *path, *path_full; int index= -1; - PyObject *ret; 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) < 0) + if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) < 0) { return NULL; + } + else { + PyObject *ret= NULL; + ReportList reports; + int result; - if(ANIM_add_driver((ID *)self->ptr.id.data, path_full, index, 0, DRIVER_TYPE_PYTHON)) { - ID *id= self->ptr.id.data; - AnimData *adt= BKE_animdata_from_id(id); - FCurve *fcu; + BKE_reports_init(&reports, RPT_STORE); - PointerRNA tptr; - PyObject *item; + result= ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0, DRIVER_TYPE_PYTHON); + + if(BPy_reports_to_error(&reports, TRUE)) + return NULL; + + if(result) { + ID *id= self->ptr.id.data; + AnimData *adt= BKE_animdata_from_id(id); + FCurve *fcu; - if(index == -1) { /* all, use a list */ - int i= 0; - ret= PyList_New(0); - while((fcu= list_find_fcurve(&adt->drivers, path_full, i++))) { + PointerRNA tptr; + PyObject *item; + + 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); + item= pyrna_struct_CreatePyObject(&tptr); + PyList_Append(ret, item); + Py_DECREF(item); + } + } + else { + fcu= list_find_fcurve(&adt->drivers, path_full, index); RNA_pointer_create(id, &RNA_FCurve, fcu, &tptr); - item= pyrna_struct_CreatePyObject(&tptr); - PyList_Append(ret, item); - Py_DECREF(item); + 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); + /* XXX, should be handled by reports, */ + PyErr_SetString(PyExc_TypeError, "bpy_struct.driver_add(): failed because of an internal error"); + return NULL; } - } - else { - PyErr_SetString(PyExc_TypeError, "bpy_struct.driver_add(): failed because of an internal error"); - return NULL; - } - MEM_freeN(path_full); + MEM_freeN((void *)path_full); - return ret; + return ret; + } } @@ -2204,28 +2385,37 @@ static char pyrna_struct_driver_remove_doc[] = "\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 indicies or a single channel if the property is not an array.\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"; static PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args) { - char *path, *path_full; + const char *path, *path_full; int index= -1; - PyObject *ret; if (!PyArg_ParseTuple(args, "s|i:driver_remove", &path, &index)) return NULL; - if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) < 0) + if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) < 0) { return NULL; + } + else { + short result; + ReportList reports; - ret= PyBool_FromLong(ANIM_remove_driver((ID *)self->ptr.id.data, path_full, index, 0)); + BKE_reports_init(&reports, RPT_STORE); - MEM_freeN(path_full); + result= ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0); - return ret; + MEM_freeN((void *)path_full); + + if(BPy_reports_to_error(&reports, TRUE)) + return NULL; + + return PyBool_FromLong(result); + } } @@ -2240,7 +2430,7 @@ static char pyrna_struct_is_property_set_doc[] = static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *args) { PropertyRNA *prop; - char *name; + const char *name; int ret; if (!PyArg_ParseTuple(args, "s:is_property_set", &name)) @@ -2254,7 +2444,7 @@ static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *arg /* double property lookup, could speed up */ /* return PyBool_FromLong(RNA_property_is_set(&self->ptr, name)); */ if(RNA_property_flag(prop) & PROP_IDPROPERTY) { - IDProperty *group= RNA_struct_idprops(&self->ptr, 0); + IDProperty *group= RNA_struct_idprops(&self->ptr, 0); if(group) { ret= IDP_GetPropertyFromGroup(group, name) ? 1:0; } @@ -2265,7 +2455,7 @@ static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *arg else { ret= 1; } - + return PyBool_FromLong(ret); } @@ -2280,7 +2470,7 @@ static char pyrna_struct_is_property_hidden_doc[] = static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA *self, PyObject *args) { PropertyRNA *prop; - char *name; + const char *name; if (!PyArg_ParseTuple(args, "s:is_property_hidden", &name)) return NULL; @@ -2305,7 +2495,7 @@ static char pyrna_struct_path_resolve_doc[] = static PyObject *pyrna_struct_path_resolve(BPy_StructRNA *self, PyObject *args) { - char *path; + const char *path; PyObject *coerce= Py_True; PointerRNA r_ptr; PropertyRNA *r_prop; @@ -2356,8 +2546,8 @@ static char pyrna_struct_path_from_id_doc[] = static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args) { - char *name= NULL; - char *path; + const char *name= NULL; + const char *path; PropertyRNA *prop; PyObject *ret; @@ -2384,7 +2574,7 @@ static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args) } ret= PyUnicode_FromString(path); - MEM_freeN(path); + MEM_freeN((void *)path); return ret; } @@ -2399,7 +2589,7 @@ static char pyrna_prop_path_from_id_doc[] = static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self) { - char *path; + const char *path; PropertyRNA *prop = self->prop; PyObject *ret; @@ -2411,7 +2601,7 @@ static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self) } ret= PyUnicode_FromString(path); - MEM_freeN(path); + MEM_freeN((void *)path); return ret; } @@ -2424,7 +2614,7 @@ static char pyrna_struct_type_recast_doc[] = " :return: a new instance of this object with the type initialized again.\n" " :rtype: subclass of :class:`bpy_struct`"; -static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self, PyObject *args) +static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self) { PointerRNA r_ptr; RNA_pointer_recast(&self->ptr, &r_ptr); @@ -2528,17 +2718,29 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self) 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 */ + + PyObject *set= PySet_New(ret); + + Py_DECREF(ret); + ret= PySequence_List(set); + Py_DECREF(set); + } + return ret; } //---------------getattr-------------------------------------------- static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname ) { - char *name = _PyUnicode_AsString(pyname); + const char *name = _PyUnicode_AsString(pyname); PyObject *ret; PropertyRNA *prop; FunctionRNA *func; - + if(name == NULL) { PyErr_SetString(PyExc_AttributeError, "bpy_struct: __getattr__ must be a string"); ret = NULL; @@ -2563,7 +2765,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname ) 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); + PyErr_Format(PyExc_AttributeError, "bpy_struct: Context is 'NULL', can't get \"%.200s\" from context", name); ret= NULL; } else { @@ -2588,9 +2790,9 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname ) { CollectionPointerLink *link; PyObject *linkptr; - + ret = PyList_New(0); - + for(link=newlb.first; link; link=link->next) { linkptr= pyrna_struct_CreatePyObject(&link->ptr); PyList_Append(ret, linkptr); @@ -2600,6 +2802,8 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname ) 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; } @@ -2618,7 +2822,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname ) } else { #if 0 - PyErr_Format( PyExc_AttributeError, "bpy_struct: attribute \"%.200s\" not found", name); + PyErr_Format(PyExc_AttributeError, "bpy_struct: attribute \"%.200s\" not found", name); ret = NULL; #endif /* Include this incase this instance is a subtype of a python class @@ -2630,7 +2834,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA *self, PyObject *pyname ) /* The error raised here will be displayed */ ret = PyObject_GenericGetAttr((PyObject *)self, pyname); } - + return ret; } @@ -2651,14 +2855,38 @@ static int pyrna_is_deferred_prop(PyObject *value) return PyTuple_CheckExact(value) && PyTuple_GET_SIZE(value)==2 && PyCallable_Check(PyTuple_GET_ITEM(value, 0)) && PyDict_CheckExact(PyTuple_GET_ITEM(value, 1)); } -static PyObject *pyrna_struct_meta_idprop_getattro(PyObject *cls, PyObject *pyname) +static PyObject *pyrna_struct_meta_idprop_getattro(PyObject *cls, PyObject *attr) { - return PyType_Type.tp_getattro(cls, pyname); + PyObject *ret= PyType_Type.tp_getattro(cls, attr); + + /* Allows: + * >>> bpy.types.Scene.foo = BoolProperty() + * >>> bpy.types.Scene.foo + * <bpy_struct, BooleanProperty("foo")> + * ...rather then returning the defered class register tuple as checked by pyrna_is_deferred_prop() + * + * Disable for now, this is faking internal behavior in a way thats 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; } static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyObject *value) { - StructRNA *srna= srna_from_self(cls, ""); + StructRNA *srna= srna_from_self(cls, "StructRNA.__setattr__"); if(srna == NULL) { if(value && pyrna_is_deferred_prop(value)) { @@ -2667,7 +2895,7 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb } /* srna_from_self may set an error */ - PyErr_Clear(); + PyErr_Clear(); return PyType_Type.tp_setattro(cls, attr, value); } @@ -2675,42 +2903,53 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb /* check if the value is a property */ if(pyrna_is_deferred_prop(value)) { int ret= deferred_register_prop(srna, attr, value); - if(ret < 0) + if(ret == -1) { + /* error set */ return ret; - /* pass through, when the value isn't assigned it still works but gets confusing from script writers POV */ + } + + /* 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 confusement */ - char *attr_str= _PyUnicode_AsString(attr); + const char *attr_str= _PyUnicode_AsString(attr); RNA_def_property_free_identifier(srna, attr_str); /* ignore on failier */ } } else { /* __delattr__ */ /* first find if this is a registered property */ - char *attr_str= _PyUnicode_AsString(attr); + const char *attr_str= _PyUnicode_AsString(attr); 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); + 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 ) { - char *name = _PyUnicode_AsString(pyname); + const char *name = _PyUnicode_AsString(pyname); PropertyRNA *prop= NULL; +#ifdef USE_PEDANTIC_WRITE + if(rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { + return -1; + } +#endif // USE_STRING_COERCE + 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) ); + 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; } } @@ -2744,7 +2983,7 @@ static int pyrna_struct_setattro( BPy_StructRNA *self, PyObject *pyname, PyObjec PyErr_SetString(PyExc_AttributeError, "bpy_struct: del not supported"); return -1; } - return pyrna_py_to_prop(&self->ptr, prop, NULL, NULL, value, "bpy_struct: item.attr = val:"); + return pyrna_py_to_prop(&self->ptr, prop, NULL, value, "bpy_struct: item.attr = val:"); } else { return PyObject_GenericSetAttr((PyObject *)self, pyname, value); @@ -2778,7 +3017,7 @@ static PyObject *pyrna_prop_array_getattro( BPy_PropertyRNA *self, PyObject *pyn static PyObject *pyrna_prop_collection_getattro( BPy_PropertyRNA *self, PyObject *pyname ) { - char *name = _PyUnicode_AsString(pyname); + const char *name = _PyUnicode_AsString(pyname); if(name == NULL) { PyErr_SetString(PyExc_AttributeError, "bpy_prop_collection: __getattr__ must be a string"); @@ -2813,10 +3052,16 @@ static PyObject *pyrna_prop_collection_getattro( BPy_PropertyRNA *self, PyObject //--------------- setattr------------------------------------------- static int pyrna_prop_collection_setattro( BPy_PropertyRNA *self, PyObject *pyname, PyObject *value ) { - char *name = _PyUnicode_AsString(pyname); + 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_STRING_COERCE + if(name == NULL) { PyErr_SetString(PyExc_AttributeError, "bpy_prop: __setattr__ must be a string"); return -1; @@ -2828,11 +3073,11 @@ static int pyrna_prop_collection_setattro( BPy_PropertyRNA *self, PyObject *pyna 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, NULL, value, "BPy_PropertyRNA - Attribute (setattr):"); + 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); + PyErr_Format(PyExc_AttributeError, "bpy_prop_collection: attribute \"%.200s\" not found", name); return -1; } @@ -2843,7 +3088,7 @@ static PyObject *pyrna_prop_collection_idprop_add(BPy_PropertyRNA *self) 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"); + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.add(): not supported for this collection"); return NULL; } else { @@ -2853,15 +3098,15 @@ static PyObject *pyrna_prop_collection_idprop_add(BPy_PropertyRNA *self) static PyObject *pyrna_prop_collection_idprop_remove(BPy_PropertyRNA *self, PyObject *value) { - int key= PyLong_AsSsize_t(value); + int key= PyLong_AsLong(value); if (key==-1 && PyErr_Occurred()) { - PyErr_SetString( PyExc_TypeError, "bpy_prop_collection.remove(): expected one int argument"); + 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"); + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.remove() not supported for this collection"); return NULL; } @@ -2873,12 +3118,12 @@ static PyObject *pyrna_prop_collection_idprop_move(BPy_PropertyRNA *self, PyObje int key=0, pos=0; if (!PyArg_ParseTuple(args, "ii", &key, &pos)) { - PyErr_SetString( PyExc_TypeError, "bpy_prop_collection.move(): expected two ints as arguments"); + 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"); + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.move() not supported for this collection"); return NULL; } @@ -2902,17 +3147,17 @@ static PyObject *pyrna_struct_get_id_data(BPy_DummyPointerRNA *self) /*****************************************************************************/ static PyGetSetDef pyrna_prop_getseters[] = { - {"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, "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:`ID` object this datablock is from or None, (not available for all data types)", NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; static PyGetSetDef pyrna_struct_getseters[] = { - {"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, "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:`ID` object this datablock is from or None, (not available for all data types)", NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; -static PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) +static PyObject *pyrna_prop_collection_keys(BPy_PropertyRNA *self) { PyObject *ret= PyList_New(0); PyObject *item; @@ -2933,11 +3178,11 @@ static PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) } } RNA_PROP_END; - + return ret; } -static PyObject *pyrna_prop_items(BPy_PropertyRNA *self) +static PyObject *pyrna_prop_collection_items(BPy_PropertyRNA *self) { PyObject *ret= PyList_New(0); PyObject *item; @@ -2966,23 +3211,14 @@ static PyObject *pyrna_prop_items(BPy_PropertyRNA *self) } } RNA_PROP_END; - + return ret; } -static PyObject *pyrna_prop_values(BPy_PropertyRNA *self) +static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self) { - PyObject *ret= PyList_New(0); - PyObject *item; - - RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { - item = pyrna_struct_CreatePyObject(&itemptr); - PyList_Append(ret, item); - Py_DECREF(item); - } - RNA_PROP_END; - - return ret; + /* re-use slice*/ + return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); } static char pyrna_struct_get_doc[] = @@ -3001,7 +3237,7 @@ static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args) { IDProperty *group, *idprop; - char *key; + const char *key; PyObject* def = Py_None; if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) @@ -3009,7 +3245,7 @@ static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args) /* 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"); + PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); return NULL; } @@ -3039,23 +3275,23 @@ static PyObject *pyrna_struct_as_pointer(BPy_StructRNA *self) return PyLong_FromVoidPtr(self->ptr.data); } -static PyObject *pyrna_prop_get(BPy_PropertyRNA *self, PyObject *args) +static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args) { PointerRNA newptr; - - char *key; + + const char *key; PyObject* def = Py_None; if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) return NULL; - + if(RNA_property_collection_lookup_string(&self->ptr, self->prop, key, &newptr)) return pyrna_struct_CreatePyObject(&newptr); return Py_INCREF(def), def; } -static void foreach_attr_type( BPy_PropertyRNA *self, char *attr, +static void foreach_attr_type( BPy_PropertyRNA *self, const char *attr, /* values to assign */ RawPropertyType *raw_type, int *attr_tot, int *attr_signed ) { @@ -3075,12 +3311,12 @@ static void foreach_attr_type( BPy_PropertyRNA *self, char *attr, RNA_PROP_END; } -/* pyrna_prop_foreach_get/set both use this */ +/* pyrna_prop_collection_foreach_get/set both use this */ static int foreach_parse_args( BPy_PropertyRNA *self, PyObject *args, /*values to assign */ - char **attr, PyObject **seq, int *tot, int *size, RawPropertyType *raw_type, int *attr_tot, int *attr_signed) + const char **attr, PyObject **seq, int *tot, int *size, RawPropertyType *raw_type, int *attr_tot, int *attr_signed) { #if 0 int array_tot; @@ -3091,11 +3327,11 @@ static int foreach_parse_args( *raw_type= PROP_RAW_UNSET; if(!PyArg_ParseTuple(args, "sO", attr, seq) || (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq))) { - PyErr_SetString( PyExc_TypeError, "foreach_get(attr, sequence) expects a string and a sequence" ); + PyErr_SetString(PyExc_TypeError, "foreach_get(attr, sequence) expects a string and a sequence"); return -1; } - *tot= PySequence_Length(*seq); // TODO - buffer may not be a sequence! array.array() is tho. + *tot= PySequence_Size(*seq); // TODO - buffer may not be a sequence! array.array() is tho. if(*tot>0) { foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed); @@ -3115,7 +3351,7 @@ static int foreach_parse_args( /* 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); + PyErr_Format(PyExc_TypeError, "foreach_get(attr, sequence) sequence length mismatch given %d, needed %d", *tot, target_tot); return -1; } #endif @@ -3124,7 +3360,7 @@ static int foreach_parse_args( /* check 'attr_tot' otherwise we dont know if any values were set * this isnt 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" ); + PyErr_SetString(PyExc_AttributeError, "attribute does not support foreach method"); return -1; } return 0; @@ -3162,7 +3398,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) void *array= NULL; /* get/set both take the same args currently */ - char *attr; + const char *attr; PyObject *seq; int tot, size, attr_tot, attr_signed; RawPropertyType raw_type; @@ -3200,13 +3436,13 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) item= PySequence_GetItem(seq, i); switch(raw_type) { case PROP_RAW_CHAR: - ((char *)array)[i]= (char)PyLong_AsSsize_t(item); + ((char *)array)[i]= (char)PyLong_AsLong(item); break; case PROP_RAW_SHORT: - ((short *)array)[i]= (short)PyLong_AsSsize_t(item); + ((short *)array)[i]= (short)PyLong_AsLong(item); break; case PROP_RAW_INT: - ((int *)array)[i]= (int)PyLong_AsSsize_t(item); + ((int *)array)[i]= (int)PyLong_AsLong(item); break; case PROP_RAW_FLOAT: ((float *)array)[i]= (float)PyFloat_AsDouble(item); @@ -3216,6 +3452,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) break; case PROP_RAW_UNSET: /* should never happen */ + BLI_assert(!"Invalid array type - set"); break; } @@ -3270,6 +3507,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) break; case PROP_RAW_UNSET: /* should never happen */ + BLI_assert(!"Invalid array type - get"); break; } @@ -3296,12 +3534,38 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) Py_RETURN_NONE; } -static PyObject *pyrna_prop_foreach_get(BPy_PropertyRNA *self, PyObject *args) +static char pyrna_prop_collection_foreach_get_doc[] = +".. method:: foreach_get(attr, seq)\n" +"\n" +" This is a function to give fast access to attribites within a collection.\n" +"\n" +" .. code-block:: python\n" +"\n" +" collection.foreach_get(someseq, attr)\n" +"\n" +" # Python equivelent\n" +" for i in range(len(seq)): someseq[i] = getattr(collection, attr)\n" +"\n" +; +static PyObject *pyrna_prop_collection_foreach_get(BPy_PropertyRNA *self, PyObject *args) { return foreach_getset(self, args, 0); } -static PyObject *pyrna_prop_foreach_set(BPy_PropertyRNA *self, PyObject *args) +static char pyrna_prop_collection_foreach_set_doc[] = +".. method:: foreach_set(attr, seq)\n" +"\n" +" This is a function to give fast access to attribites within a collection.\n" +"\n" +" .. code-block:: python\n" +"\n" +" collection.foreach_set(seq, attr)\n" +"\n" +" # Python equivelent\n" +" for i in range(len(seq)): setattr(collection[i], attr, seq[i])\n" +"\n" +; +static PyObject *pyrna_prop_collection_foreach_set(BPy_PropertyRNA *self, PyObject *args) { return foreach_getset(self, args, 1); } @@ -3315,7 +3579,7 @@ PyObject *pyrna_prop_array_iter(BPy_PropertyArrayRNA *self) PyObject *iter= NULL; int 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) { @@ -3331,8 +3595,8 @@ PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self) /* Try get values from a collection */ PyObject *ret; PyObject *iter= NULL; - ret = pyrna_prop_values(self); - + 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) { @@ -3343,6 +3607,11 @@ PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self) return iter; } +static PyObject *pyrna_struct_is_registered(PyObject *cls) +{ + return PyBool_FromLong(PyDict_GetItemString((((PyTypeObject *)cls)->tp_dict), "bl_rna") != NULL); +} + static struct PyMethodDef pyrna_struct_methods[] = { /* only for PointerRNA's with ID'props */ @@ -3368,6 +3637,9 @@ static struct PyMethodDef pyrna_struct_methods[] = { /* experemental */ {"callback_add", (PyCFunction)pyrna_callback_add, METH_VARARGS, NULL}, {"callback_remove", (PyCFunction)pyrna_callback_remove, METH_VARARGS, NULL}, + + /* class method */ + {"is_registered", (PyCFunction) pyrna_struct_is_registered, METH_NOARGS | METH_CLASS, NULL}, {NULL, NULL, 0, NULL} }; @@ -3382,14 +3654,14 @@ static struct PyMethodDef pyrna_prop_array_methods[] = { }; static struct PyMethodDef pyrna_prop_collection_methods[] = { - {"foreach_get", (PyCFunction)pyrna_prop_foreach_get, METH_VARARGS, NULL}, - {"foreach_set", (PyCFunction)pyrna_prop_foreach_set, METH_VARARGS, 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_keys, METH_NOARGS, NULL}, - {"items", (PyCFunction)pyrna_prop_items, METH_NOARGS,NULL}, - {"values", (PyCFunction)pyrna_prop_values, METH_NOARGS, NULL}, - - {"get", (PyCFunction)pyrna_prop_get, METH_VARARGS, NULL}, + {"keys", (PyCFunction)pyrna_prop_collection_keys, METH_NOARGS, NULL}, + {"items", (PyCFunction)pyrna_prop_collection_items, METH_NOARGS,NULL}, + {"values", (PyCFunction)pyrna_prop_collection_values, METH_NOARGS, NULL}, + + {"get", (PyCFunction)pyrna_prop_collection_get, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; @@ -3402,10 +3674,10 @@ static struct PyMethodDef pyrna_prop_collection_idprop_methods[] = { /* 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 *kwds) { +static PyObject * pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds)) { BPy_StructRNA *base; - + if (!PyArg_ParseTuple(args, "O!:bpy_struct.__new__", &pyrna_struct_Type, &base)) return NULL; @@ -3418,20 +3690,20 @@ static PyObject * pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject return (PyObject *)ret; } else { - PyErr_Format(PyExc_TypeError, "bpy_struct.__new__(type): type '%.200s' is not a subtype of bpy_struct.", type->tp_name); + PyErr_Format(PyExc_TypeError, "bpy_struct.__new__(type): type '%.200s' is not a subtype of bpy_struct", type->tp_name); 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 *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)) return NULL; - + if (type == Py_TYPE(base)) { Py_INCREF(base); return (PyObject *)base; @@ -3442,20 +3714,19 @@ static PyObject * pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *k return (PyObject *)ret; } else { - PyErr_Format(PyExc_TypeError, "bpy_prop.__new__(type): type '%.200s' is not a subtype of bpy_prop.", type->tp_name); + PyErr_Format(PyExc_TypeError, "bpy_prop.__new__(type): type '%.200s' is not a subtype of bpy_prop", type->tp_name); return NULL; } } -PyObject *pyrna_param_to_py(PointerRNA *ptr, ParameterList *parms, PropertyRNA *prop, void *data) +PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) { PyObject *ret; int type = RNA_property_type(prop); int flag = RNA_property_flag(prop); - int a; if(RNA_property_array_check(ptr, prop)) { - int len; + int a, len; if (flag & PROP_DYNAMIC) { ParameterDynAlloc *data_alloc= data; @@ -3482,6 +3753,7 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, ParameterList *parms, PropertyRNA * break; case PROP_FLOAT: switch(RNA_property_subtype(prop)) { +#ifdef USE_MATHUTILS case PROP_ALL_VECTOR_SUBTYPES: ret= newVectorObject(data, len, Py_NEW, NULL); break; @@ -3495,6 +3767,7 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, ParameterList *parms, PropertyRNA * break; } /* pass through */ +#endif default: ret = PyTuple_New(len); for(a=0; a<len; a++) @@ -3626,16 +3899,18 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) void *retdata_single= 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_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; } - + /* 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. */ @@ -3698,7 +3973,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) continue; } - err= pyrna_py_to_prop(&funcptr, parm, &parms, iter.data, item, ""); + err= pyrna_py_to_prop(&funcptr, parm, iter.data, item, ""); if(err!=0) { /* the error generated isnt that useful, so generate it again with a useful prefix @@ -3711,12 +3986,12 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) else snprintf(error_prefix, sizeof(error_prefix), "%s.%s(): error with argument %d, \"%s\" - ", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), i, parm_id); - pyrna_py_to_prop(&funcptr, parm, &parms, iter.data, item, error_prefix); + pyrna_py_to_prop(&funcptr, parm, iter.data, item, error_prefix); break; } } - + RNA_parameter_list_end(&iter); /* Check if we gave args that dont exist in the function @@ -3731,7 +4006,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) DynStr *bad_args= BLI_dynstr_new(); DynStr *good_args= BLI_dynstr_new(); - char *arg_name, *bad_args_str, *good_args_str; + const char *arg_name, *bad_args_str, *good_args_str; int found= FALSE, first= TRUE; while (PyDict_Next(kw, &pos, &key, &value)) { @@ -3784,8 +4059,8 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) BLI_dynstr_free(bad_args); BLI_dynstr_free(good_args); - MEM_freeN(bad_args_str); - MEM_freeN(good_args_str); + MEM_freeN((void *)bad_args_str); + MEM_freeN((void *)good_args_str); err= -1; } @@ -3799,8 +4074,7 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) BKE_reports_init(&reports, RPT_STORE); RNA_function_call(C, &reports, self_ptr, self_func, &parms); - err= (BPy_reports_to_error(&reports))? -1: 0; - BKE_reports_clear(&reports); + err= (BPy_reports_to_error(&reports, TRUE))? -1: 0; /* return value */ if(err==0) { @@ -3816,13 +4090,13 @@ static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) flag= RNA_property_flag(parm); if (flag & PROP_OUTPUT) - PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, &parms, parm, iter.data)); + 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, &parms, pret_single, retdata_single); + ret= pyrna_param_to_py(&funcptr, pret_single, retdata_single); /* possible there is an error in conversion */ if(ret==NULL) @@ -4345,7 +4619,7 @@ static PyObject* pyrna_srna_ExternalType(StructRNA *srna) PyObject *newclass; if(bpy_types_dict==NULL) { - PyObject *bpy_types= PyImport_ImportModuleLevel("bpy_types", NULL, NULL, NULL, 0); + PyObject *bpy_types= PyImport_ImportModuleLevel((char *)"bpy_types", NULL, NULL, NULL, 0); if(bpy_types==NULL) { PyErr_Print(); @@ -4430,7 +4704,7 @@ static PyObject* pyrna_srna_Subtype(StructRNA *srna) } /* always use O not N when calling, N causes refcount errors */ - newclass = PyObject_CallFunction(metaclass, "s(O){sss()}", idname, py_base, "__module__","bpy.types", "__slots__"); + newclass = PyObject_CallFunction(metaclass, (char *)"s(O){sss()}", idname, py_base, "__module__","bpy.types", "__slots__"); /* newclass will now have 2 ref's, ???, probably 1 is internal since decrefing here segfaults */ @@ -4494,7 +4768,7 @@ PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr ) } if( !pyrna ) { - PyErr_SetString( PyExc_MemoryError, "couldn't create bpy_struct object" ); + PyErr_SetString(PyExc_MemoryError, "couldn't create bpy_struct object"); return NULL; } @@ -4534,7 +4808,7 @@ PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop ) } if( !pyrna ) { - PyErr_SetString( PyExc_MemoryError, "couldn't create BPy_rna object" ); + PyErr_SetString(PyExc_MemoryError, "couldn't create BPy_rna object"); return NULL; } @@ -4614,16 +4888,12 @@ static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA *self, PyObject *pynam { PointerRNA newptr; PyObject *ret; - char *name= _PyUnicode_AsString(pyname); + const char *name= _PyUnicode_AsString(pyname); if(name == NULL) { PyErr_SetString(PyExc_AttributeError, "bpy.types: __getattr__ must be a string"); ret = NULL; } - else if(strcmp(name, "register")==0) { - /* this is called so often, make an exception and save a full lookup on all types */ - ret= PyObject_GenericGetAttr((PyObject *)self, pyname); - } else if (RNA_property_collection_lookup_string(&self->ptr, self->prop, name, &newptr)) { ret= pyrna_struct_Subtype(&newptr); if (ret==NULL) { @@ -4643,29 +4913,31 @@ static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA *self, PyObject *pynam } static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self); -static PyObject *pyrna_basetype_register(PyObject *self, PyObject *py_class); -static PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *py_class); +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, ""}, - {"register", (PyCFunction)pyrna_basetype_register, METH_O, ""}, - {"unregister", (PyCFunction)pyrna_basetype_unregister, METH_O, ""}, {NULL, NULL, 0, NULL} }; static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self) { - PyObject *list, *name; + PyObject *list; +#if 0 + PyObject *name; PyMethodDef *meth; - - list= pyrna_prop_keys(self); /* like calling structs.keys(), avoids looping here */ +#endif + + 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++) { name = PyUnicode_FromString(meth->ml_name); PyList_Append(list, name); Py_DECREF(name); } - +#endif return list; } @@ -4738,12 +5010,10 @@ StructRNA *pyrna_struct_as_srna(PyObject *self, int parent, const char *error_pr /* Orphan functions, not sure where they should go */ /* get the srna for methods attached to types */ -/* */ +/* + * Caller needs to raise error.*/ StructRNA *srna_from_self(PyObject *self, const char *error_prefix) { - /* a bit sloppy but would cause a very confusing bug if - * an error happened to be set here */ - PyErr_Clear(); if(self==NULL) { return NULL; @@ -4754,10 +5024,24 @@ StructRNA *srna_from_self(PyObject *self, const char *error_prefix) else if (PyType_Check(self)==0) { return NULL; } - /* These cases above not errors, they just mean the type was not compatible - * After this any errors will be raised in the script */ + else { + /* These cases above not errors, they just mean the type was not compatible + * After this any errors will be raised in the script */ - return pyrna_struct_as_srna(self, 0, error_prefix); + PyObject *error_type, *error_value, *error_traceback; + StructRNA *srna; + + PyErr_Fetch(&error_type, &error_value, &error_traceback); + PyErr_Clear(); + + srna= pyrna_struct_as_srna(self, 0, error_prefix); + + if(!PyErr_Occurred()) { + PyErr_Restore(error_type, error_value, error_traceback); + } + + return srna; + } } static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item) @@ -4817,17 +5101,17 @@ static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict) PyObject *item, *key; PyObject *order; Py_ssize_t pos = 0; - int ret; + int ret= 0; - if( !PyDict_CheckExact(class_dict) && - (order= PyDict_GetItemString(class_dict, "order")) && - PyList_CheckExact(order) - ) { + /* in both cases PyDict_CheckExact(class_dict) will be true even + * though Operators have a metaclass dict namespace */ + + if((order= PyDict_GetItemString(class_dict, "order")) && PyList_CheckExact(order)) { for(pos= 0; pos<PyList_GET_SIZE(order); pos++) { key= PyList_GET_ITEM(order, pos); item= PyDict_GetItem(class_dict, key); ret= deferred_register_prop(srna, key, item); - if(ret==-1) + if(ret != 0) break; } } @@ -4835,12 +5119,12 @@ static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict) while (PyDict_Next(class_dict, &pos, &key, &item)) { ret= deferred_register_prop(srna, key, item); - if(ret==-1) + if(ret != 0) break; } } - return 0; + return ret; } static int pyrna_deferred_register_class_recursive(StructRNA *srna, PyTypeObject *py_class) @@ -4922,13 +5206,13 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun 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); + PyErr_Format(PyExc_TypeError, "expected %.200s subclass of class \"%.200s\"", class_type, py_class_name); return -1; } } /* verify callback functions */ - lb= RNA_struct_defined_functions(srna); + lb= RNA_struct_type_functions(srna); i= 0; for(link=lb->first; link; link=link->next) { func= (FunctionRNA*)link; @@ -4944,7 +5228,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun if (item==NULL) { if ((flag & FUNC_REGISTER_OPTIONAL)==0) { - PyErr_Format( PyExc_AttributeError, "expected %.200s, %.200s class to have an \"%.200s\" attribute", class_type, py_class_name, RNA_function_identifier(func)); + PyErr_Format(PyExc_AttributeError, "expected %.200s, %.200s class to have an \"%.200s\" attribute", class_type, py_class_name, RNA_function_identifier(func)); return -1; } @@ -4954,14 +5238,14 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun Py_DECREF(item); /* no need to keep a ref, the class owns it (technically we should keep a ref but...) */ if(flag & FUNC_NO_SELF) { if (PyMethod_Check(item)==0) { - PyErr_Format( PyExc_TypeError, "expected %.200s, %.200s class \"%.200s\" attribute to be a method, not a %.200s", class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name); + PyErr_Format(PyExc_TypeError, "expected %.200s, %.200s class \"%.200s\" attribute to be a 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); + 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; } } @@ -4970,7 +5254,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun if (func_arg_count >= 0) { /* -1 if we dont care*/ py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(item), "co_argcount"); - arg_count = PyLong_AsSsize_t(py_arg_count); + arg_count = PyLong_AsLong(py_arg_count); Py_DECREF(py_arg_count); /* note, the number of args we check for and the number of args we give to @@ -4979,7 +5263,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun func_arg_count++; if (arg_count != func_arg_count) { - PyErr_Format( PyExc_AttributeError, "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); + PyErr_Format(PyExc_AttributeError, "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; } } @@ -4987,7 +5271,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun } /* verify properties */ - lb= RNA_struct_defined_properties(srna); + lb= RNA_struct_type_properties(srna); for(link=lb->first; link; link=link->next) { const char *identifier; prop= (PropertyRNA*)link; @@ -5006,7 +5290,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun if(strcmp(identifier, rna_attr) == 0) { \ item= PyObject_GetAttrString(py_class, py_attr); \ if(item && item != Py_None) { \ - if(pyrna_py_to_prop(dummyptr, prop, NULL, NULL, item, "validating class error:") != 0) { \ + if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0) { \ Py_DECREF(item); \ return -1; \ } \ @@ -5021,7 +5305,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun #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); + PyErr_Format(PyExc_AttributeError, "expected %.200s, %.200s class to have an \"%.200s\" attribute", class_type, py_class_name, identifier); return -1; } @@ -5030,7 +5314,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun else { Py_DECREF(item); /* no need to keep a ref, the class owns it */ - if(pyrna_py_to_prop(dummyptr, prop, NULL, NULL, item, "validating class error:") != 0) + if(pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class error:") != 0) return -1; } } @@ -5038,10 +5322,8 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun return 0; } -extern void BPY_update_modules( void ); //XXX temp solution - /* TODO - multiple return values like with rna functions */ -static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *parms) +static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms) { PyObject *args; PyObject *ret= NULL, *py_srna= NULL, *py_class, *py_class_instance= NULL, *parmitem; @@ -5057,8 +5339,12 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par PyGILState_STATE gilstate; - bContext *C= BPy_GetContext(); // XXX - NEEDS FIXING, QUITE BAD. - +#ifdef USE_PEDANTIC_WRITE + const char *func_id= RNA_function_identifier(func); + /* testing, for correctness, not operator and not draw function */ + const short is_readonly= strstr("draw", func_id) || /*strstr("render", func_id) ||*/ !RNA_struct_is_a(ptr->type, &RNA_Operator); +#endif + py_class= RNA_struct_py_type_get(ptr->type); /* rare case. can happen when registering subclasses */ @@ -5067,6 +5353,11 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par 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(); + bpy_context_set(C, &gilstate); if (!is_static) { @@ -5150,13 +5441,24 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par continue; } - parmitem= pyrna_param_to_py(&funcptr, parms, parm, iter.data); + 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; +#endif + /* *** Main Caller *** */ + ret = PyObject_Call(item, args, NULL); + /* *** Done Calling *** */ + +#ifdef USE_PEDANTIC_WRITE + rna_disallow_writes= FALSE; +#endif + RNA_parameter_list_end(&iter); Py_DECREF(item); Py_DECREF(args); @@ -5164,14 +5466,14 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par 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)); + 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 alredy set if the class instance couldnt 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)); + 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; } } @@ -5181,20 +5483,20 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par } else { if(ret_len==0 && ret != Py_None) { - PyErr_Format(PyExc_RuntimeError, "expected class %.200s, function %.200s to return None, got a %.200s type instead.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func), Py_TYPE(ret)->tp_name); + PyErr_Format(PyExc_RuntimeError, "expected class %.200s, function %.200s to return None, got a %.200s type instead", 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, parms, retdata_single, ret, "calling class function:"); + err= pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, "calling class function:"); } 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, got a %.200s type instead.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func), ret_len, Py_TYPE(ret)->tp_name); + PyErr_Format(PyExc_RuntimeError, "expected class %.200s, function %.200s to return a tuple of size %d, got a %.200s type instead", 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); + 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 { @@ -5208,7 +5510,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par /* only useful for single argument returns, we'll need another list loop for multiple */ if (flag & PROP_OUTPUT) { - err= pyrna_py_to_prop(&funcptr, parm, parms, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:"); + err= pyrna_py_to_prop(&funcptr, parm, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:"); if(err) break; } @@ -5221,6 +5523,20 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par } 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)) { + 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(); } @@ -5245,12 +5561,13 @@ static void bpy_class_free(void *pyob_ptr) if(PyErr_Occurred()) PyErr_Clear(); +#if 0 /* needs further investigation, too annoying so quiet for now */ if(G.f&G_DEBUG) { if(self->ob_refcnt > 1) { PyC_ObSpit("zombie class - ref should be 1", self); } } - +#endif Py_DECREF((PyObject *)pyob_ptr); PyGILState_Release(gilstate); @@ -5321,8 +5638,16 @@ void pyrna_free_types(void) * the decref. This is not so bad because the leak only happens when re-registering (hold F8) * - Should still be fixed - Campbell * */ - -static PyObject *pyrna_basetype_register(PyObject *self, PyObject *py_class) +static char pyrna_register_class_doc[] = +".. method:: register_class(cls)\n" +"\n" +" Register a subclass of a blender type in (:class:`Panel`, :class:`Menu`, :class:`Header`, :class:`Operator`, :class:`KeyingSetInfo`, :class:`RenderEngine`).\n" +"\n" +" .. note:: :exc:`ValueError` exception is raised if the class is not a 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; @@ -5332,19 +5657,19 @@ static PyObject *pyrna_basetype_register(PyObject *self, PyObject *py_class) const char *identifier; if(PyDict_GetItemString(((PyTypeObject*)py_class)->tp_dict, "bl_rna")) { - PyErr_SetString(PyExc_AttributeError, "bpy.types.register(...): already registered as a subclass."); + PyErr_SetString(PyExc_AttributeError, "register_class(...): already registered as a subclass"); return NULL; } /* warning: gets parent classes srna, only for the register function */ - srna= pyrna_struct_as_srna(py_class, 1, "bpy.types.register(...):"); + srna= pyrna_struct_as_srna(py_class, 1, "register_class(...):"); if(srna==NULL) return NULL; /* fails in cases, cant use this check but would like to :| */ /* if(RNA_struct_py_type_get(srna)) { - PyErr_Format(PyExc_ValueError, "bpy.types.register(...): %.200s's parent class %.200s is alredy registered, this is not allowed.", ((PyTypeObject*)py_class)->tp_name, RNA_struct_identifier(srna)); + PyErr_Format(PyExc_ValueError, "register_class(...): %.200s's parent class %.200s is alredy registered, this is not allowed", ((PyTypeObject*)py_class)->tp_name, RNA_struct_identifier(srna)); return NULL; } */ @@ -5353,7 +5678,7 @@ static PyObject *pyrna_basetype_register(PyObject *self, PyObject *py_class) reg= RNA_struct_register(srna); if(!reg) { - PyErr_Format(PyExc_ValueError, "bpy.types.register(...): expected a subclass of a registerable rna type (%.200s does not support registration).", RNA_struct_identifier(srna)); + 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; } @@ -5367,13 +5692,13 @@ static PyObject *pyrna_basetype_register(PyObject *self, PyObject *py_class) srna_new= reg(C, &reports, py_class, identifier, bpy_class_validate, bpy_class_call, bpy_class_free); - if(!srna_new) { - BPy_reports_to_error(&reports); - BKE_reports_clear(&reports); + if(BPy_reports_to_error(&reports, TRUE)) return NULL; - } - BKE_reports_clear(&reports); + /* 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 */ @@ -5396,30 +5721,35 @@ static PyObject *pyrna_basetype_register(PyObject *self, PyObject *py_class) static int pyrna_srna_contains_pointer_prop_srna(StructRNA *srna_props, StructRNA *srna, const char **prop_identifier) { - PointerRNA tptr; - PropertyRNA *iterprop; - RNA_pointer_create(NULL, &RNA_Struct, srna_props, &tptr); - - iterprop= RNA_struct_find_property(&tptr, "properties"); + PropertyRNA *prop; + LinkData *link; - RNA_PROP_BEGIN(&tptr, itemptr, iterprop) { - PropertyRNA *prop= itemptr.data; - if(RNA_property_type(prop) == PROP_POINTER) { - if (strcmp(RNA_property_identifier(prop), "rna_type") == 0) { - /* pass */ - } - else if(RNA_property_pointer_type(&tptr, prop) == srna) { + /* 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_flag(prop) & PROP_BUILTIN)) { + PointerRNA tptr; + RNA_pointer_create(NULL, &RNA_Struct, srna_props, &tptr); + + if(RNA_property_pointer_type(&tptr, prop) == srna) { *prop_identifier= RNA_property_identifier(prop); return 1; } } } - RNA_PROP_END; - + return 0; } -static PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *py_class) +static char pyrna_unregister_class_doc[] = +".. method:: unregister_class(cls)\n" +"\n" +" Unload the python class from blender.\n" +; +PyMethodDef meth_bpy_unregister_class = {"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; @@ -5427,11 +5757,11 @@ static PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *py_class) /*if(PyDict_GetItemString(((PyTypeObject*)py_class)->tp_dict, "bl_rna")==NULL) { PWM_cursor_wait(0); - PyErr_SetString(PyExc_ValueError, "bpy.types.unregister(): not a registered as a subclass."); + PyErr_SetString(PyExc_ValueError, "unregister_class(): not a registered as a subclass"); return NULL; }*/ - srna= pyrna_struct_as_srna(py_class, 0, "bpy.types.unregister(...):"); + srna= pyrna_struct_as_srna(py_class, 0, "unregister_class(...):"); if(srna==NULL) return NULL; @@ -5439,7 +5769,7 @@ static PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *py_class) unreg= RNA_struct_unregister(srna); if(!unreg) { - PyErr_SetString(PyExc_ValueError, "bpy.types.unregister(...): expected a Type subclassed from a registerable rna type (no unregister supported)."); + PyErr_SetString(PyExc_ValueError, "unregister_class(...): expected a Type subclassed from a registerable rna type (no unregister supported)"); return NULL; } @@ -5466,7 +5796,7 @@ static PyObject *pyrna_basetype_unregister(PyObject *self, PyObject *py_class) RNA_PROP_END; if(prop_identifier) { - PyErr_Format(PyExc_SystemError, "bpy.types.unregister(...): Cant unregister %s because %s.%s pointer property is using this.", RNA_struct_identifier(srna), RNA_struct_identifier(srna_iter), prop_identifier); + PyErr_Format(PyExc_SystemError, "unregister_class(...): Cant unregister %s because %s.%s pointer property is using this", RNA_struct_identifier(srna), RNA_struct_identifier(srna_iter), prop_identifier); return NULL; } } |