diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-03-02 14:35:28 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-03-02 14:35:28 +0300 |
commit | 46d50b0d1f27857453d4810141f86ab2e5f49208 (patch) | |
tree | f8bcbbdd36f2144ca5a8879a1a38cb61d4a04804 /source/blender | |
parent | 1444cb99280a20a2c544bcee69effbaa33ec8e6a (diff) |
bugfix for displaying ID properties
- fixed memleak from 2.4x with setting arrays from python
- basic support for IDPropertyArrays
context.object["foo"] = [{"smap": 10}, {"foo": 2}]
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/makesrna/intern/rna_access.c | 4 | ||||
-rw-r--r-- | source/blender/python/generic/IDProp.c | 154 |
2 files changed, 129 insertions, 29 deletions
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 4a50be6f58b..4cc5ca6f9df 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -2080,7 +2080,7 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA item= IDP_New(IDP_GROUP, val, ""); IDP_AppendArray(idprop, item); - IDP_FreeProperty(item); + // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory MEM_freeN(item); } else if(prop->flag & PROP_IDPROPERTY) { @@ -2094,7 +2094,7 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA item= IDP_New(IDP_GROUP, val, ""); IDP_AppendArray(idprop, item); - IDP_FreeProperty(item); + // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory MEM_freeN(item); } } diff --git a/source/blender/python/generic/IDProp.c b/source/blender/python/generic/IDProp.c index 69fc6f98bd3..30b3de0575b 100644 --- a/source/blender/python/generic/IDProp.c +++ b/source/blender/python/generic/IDProp.c @@ -75,6 +75,29 @@ PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop ) array->prop = prop; return (PyObject*) array; } + case IDP_IDPARRAY: /* this could be better a internal type */ + { + PyObject *seq = PyList_New(prop->len), *wrap; + IDProperty *array= IDP_IDPArray(prop); + int i; + + if (!seq) { + PyErr_Format( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_IDPARRAY: PyList_New(%d) failed", prop->len); + return NULL; + } + + for (i=0; i<prop->len; i++) { + wrap= BPy_IDGroup_WrapData(id, array++); + + if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */ + return NULL; + + PyList_SET_ITEM(seq, i, wrap); + } + + return seq; + } + /* case IDP_IDPARRAY: TODO */ } Py_RETURN_NONE; } @@ -210,6 +233,46 @@ static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item) } /*returns NULL on success, error string on failure*/ +static int idp_sequence_type(PyObject *seq) +{ + PyObject *item; + int type= IDP_INT; + + int i, len = PySequence_Length(seq); + for (i=0; i < len; i++) { + item = PySequence_GetItem(seq, i); + if (PyFloat_Check(item)) { + if(type == IDP_IDPARRAY) { /* mixed dict/int */ + Py_DECREF(item); + return -1; + } + type= IDP_DOUBLE; + } + else if (PyLong_Check(item)) { + if(type == IDP_IDPARRAY) { /* mixed dict/int */ + Py_DECREF(item); + return -1; + } + } + else if (PyMapping_Check(item)) { /*do nothing */ + if(i != 0 && (type != IDP_IDPARRAY)) { /* mixed dict/int */ + Py_DECREF(item); + return -1; + } + type= IDP_IDPARRAY; + } + else { + Py_XDECREF(item); + return -1; + } + + Py_DECREF(item); + } + + return type; +} + +/* note: group can be a pointer array or a group */ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObject *ob) { IDProperty *prop = NULL; @@ -231,29 +294,44 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje PyObject *item; int i; + if((val.array.type= idp_sequence_type(ob)) == -1) + return "only floats, ints and dicts are allowed in ID property arrays"; + /*validate sequence and derive type. we assume IDP_INT unless we hit a float number; then we assume it's */ - val.array.type = IDP_INT; + val.array.len = PySequence_Length(ob); - for (i=0; i<val.array.len; i++) { - item = PySequence_GetItem(ob, i); - if (PyFloat_Check(item)) val.array.type = IDP_DOUBLE; - else if (!PyLong_Check(item)) { - Py_XDECREF(item); - return "only floats and ints are allowed in ID property arrays"; - } - Py_XDECREF(item); - } - prop = IDP_New(IDP_ARRAY, val, name); - for (i=0; i<val.array.len; i++) { - item = PySequence_GetItem(ob, i); - if (val.array.type == IDP_INT) { - ((int*)prop->data.pointer)[i] = (int)PyLong_AsSsize_t(item); - } else { + switch(val.array.type) { + case IDP_DOUBLE: + prop = IDP_New(IDP_ARRAY, val, name); + for (i=0; i<val.array.len; i++) { + item = PySequence_GetItem(ob, i); ((double*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item); + Py_DECREF(item); + } + break; + case IDP_INT: + prop = IDP_New(IDP_ARRAY, val, name); + for (i=0; i<val.array.len; i++) { + item = PySequence_GetItem(ob, i); + ((int*)prop->data.pointer)[i] = (int)PyLong_AsSsize_t(item); + Py_DECREF(item); + } + break; + case IDP_IDPARRAY: + prop= IDP_NewIDPArray(name); + for (i=0; i<val.array.len; i++) { + char *error; + item = PySequence_GetItem(ob, i); + error= BPy_IDProperty_Map_ValidateAndCreate("", prop, item); + Py_DECREF(item); + + if(error) + return error; } + break; } } else if (PyMapping_Check(ob)) { PyObject *keys, *vals, *key, *pval; @@ -294,7 +372,14 @@ char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObje Py_XDECREF(vals); } else return "invalid property value"; - IDP_ReplaceInGroup(group, prop); + if(group->type==IDP_IDPARRAY) { + IDP_AppendArray(group, prop); + // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory + MEM_freeN(prop); + } else { + IDP_ReplaceInGroup(group, prop); + } + return NULL; } @@ -371,7 +456,7 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop) int i; if (!seq) { - PyErr_SetString( PyExc_RuntimeError, "PyList_New() failed" ); + PyErr_Format( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_ARRAY: PyList_New(%d) failed", prop->len); return NULL; } @@ -389,22 +474,37 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop) } return seq; } - case IDP_GROUP: + case IDP_IDPARRAY: { - PyObject *dict = PyDict_New(), *wrap; - IDProperty *loop; + PyObject *seq = PyList_New(prop->len), *wrap; + IDProperty *array= IDP_IDPArray(prop); + int i; - if (!dict) { - PyErr_SetString( PyExc_RuntimeError, "PyDict_New() failed" ); + if (!seq) { + PyErr_Format( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy, IDP_IDPARRAY: PyList_New(%d) failed", prop->len); return NULL; } + for (i=0; i<prop->len; i++) { + wrap= BPy_IDGroup_MapDataToPy(array++); + + if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */ + return NULL; + + PyList_SET_ITEM(seq, i, wrap); + } + return seq; + } + case IDP_GROUP: + { + PyObject *dict = PyDict_New(), *wrap; + IDProperty *loop; + for (loop=prop->data.group.first; loop; loop=loop->next) { wrap = BPy_IDGroup_MapDataToPy(loop); - if (!wrap) { - PyErr_SetString( PyExc_RuntimeError, "BPy_IDGroup_MapDataToPy() failed" ); + + if (!wrap) /* BPy_IDGroup_MapDataToPy sets the error */ return NULL; - } PyDict_SetItemString(dict, loop->name, wrap); } @@ -412,7 +512,7 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop) } } - PyErr_SetString( PyExc_RuntimeError, "eek!! a property exists with a bad type code!!!" ); + PyErr_Format(PyExc_RuntimeError, "eek!! '%s' property exists with a bad type code '%d' !!!", prop->name, prop->type); return NULL; } |