[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [27215] trunk/blender/source/blender: bugfix for displaying ID properties
Campbell Barton
ideasman42 at gmail.com
Tue Mar 2 12:35:28 CET 2010
Revision: 27215
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=27215
Author: campbellbarton
Date: 2010-03-02 12:35:28 +0100 (Tue, 02 Mar 2010)
Log Message:
-----------
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}]
Modified Paths:
--------------
trunk/blender/source/blender/makesrna/intern/rna_access.c
trunk/blender/source/blender/python/generic/IDProp.c
Modified: trunk/blender/source/blender/makesrna/intern/rna_access.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/rna_access.c 2010-03-02 09:45:12 UTC (rev 27214)
+++ trunk/blender/source/blender/makesrna/intern/rna_access.c 2010-03-02 11:35:28 UTC (rev 27215)
@@ -2080,7 +2080,7 @@
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 @@
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);
}
}
Modified: trunk/blender/source/blender/python/generic/IDProp.c
===================================================================
--- trunk/blender/source/blender/python/generic/IDProp.c 2010-03-02 09:45:12 UTC (rev 27214)
+++ trunk/blender/source/blender/python/generic/IDProp.c 2010-03-02 11:35:28 UTC (rev 27215)
@@ -75,6 +75,29 @@
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 @@
}
/*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 @@
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 @@
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 @@
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 @@
}
return seq;
}
+ case IDP_IDPARRAY:
+ {
+ 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_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;
- if (!dict) {
- PyErr_SetString( PyExc_RuntimeError, "PyDict_New() failed" );
- return NULL;
- }
-
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 @@
}
}
- 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;
}
More information about the Bf-blender-cvs
mailing list