IDProperty python module update

- add support for IDProp array slicing, but not resizing.
- rename array attribute type to typecode and use chars 'f', 'd', 'i' which match pythons array module. (was using int's which only have a meaning internally).
- rename function 'convert_to_pyobject' to 'to_dict' and 'to_list' for IDProp group and array types respectively.
- remove 'len' array attribute, calling len(array) is fine.
This commit is contained in:
Campbell Barton 2011-06-17 05:45:46 +00:00
parent ac089ddd15
commit 7cbc4c0dd7
7 changed files with 342 additions and 141 deletions

@ -111,12 +111,16 @@ def draw(layout, context, context_member, property_type, use_edit=True):
continue
row = layout.row()
convert_to_pyobject = getattr(val, "convert_to_pyobject", None)
to_dict = getattr(val, "to_dict", None)
to_list = getattr(val, "to_list", None)
val_orig = val
if convert_to_pyobject:
val_draw = val = val.convert_to_pyobject()
val_draw = str(val_draw)
if to_dict:
val = to_dict()
val_draw = str(val)
elif to_list:
val = to_list()
val_draw = str(val)
else:
val_draw = val
@ -131,7 +135,7 @@ def draw(layout, context, context_member, property_type, use_edit=True):
row.label(text=key)
# explicit exception for arrays
if convert_to_pyobject and not hasattr(val_orig, "len"):
if to_dict or to_list:
row.label(text=val_draw)
else:
if key in rna_properties:

@ -45,26 +45,31 @@
#include "py_capi_utils.h"
#endif
extern PyTypeObject IDArray_Type;
extern PyTypeObject IDGroup_Iter_Type;
extern PyTypeObject BPy_IDArray_Type;
extern PyTypeObject BPy_IDGroup_Iter_Type;
extern PyTypeObject BPy_IDGroup_Type;
/*********************** ID Property Main Wrapper Stuff ***************/
static PyObject *IDGroup_repr( BPy_IDProperty *self )
/* use for both array and group */
static long BPy_IDGroup_hash(BPy_IDProperty *self)
{
return PyUnicode_FromFormat( "<bpy ID property from \"%s\">", self->id->name);
return _Py_HashPointer(self->prop);
}
extern PyTypeObject IDGroup_Type;
static PyObject *BPy_IDGroup_repr(BPy_IDProperty *self)
{
return PyUnicode_FromFormat( "<bpy id property from \"%s\">", self->id->name);
}
PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop )
{
switch ( prop->type ) {
case IDP_STRING:
#ifdef USE_STRING_COERCE
return PyC_UnicodeFromByte(prop->data.pointer);
return PyC_UnicodeFromByte(IDP_Array(prop));
#else
return PyUnicode_FromString(prop->data.pointer);
return PyUnicode_FromString(IDP_Array(prop));
#endif
case IDP_INT:
return PyLong_FromLong( (long)prop->data.val );
@ -75,14 +80,14 @@ PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop )
case IDP_GROUP:
/*blegh*/
{
BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &IDGroup_Type);
BPy_IDProperty *group = PyObject_New(BPy_IDProperty, &BPy_IDGroup_Type);
group->id = id;
group->prop = prop;
return (PyObject*) group;
}
case IDP_ARRAY:
{
BPy_IDProperty *array = PyObject_New(BPy_IDProperty, &IDArray_Type);
BPy_IDProperty *array = PyObject_New(BPy_IDProperty, &BPy_IDArray_Type);
array->id = id;
array->prop = prop;
return (PyObject*) array;
@ -135,13 +140,13 @@ static int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject
st = _PyUnicode_AsString(value);
IDP_ResizeArray(prop, alloc_len);
memcpy(prop->data.pointer, st, alloc_len);
memcpy(IDP_Array(prop), st, alloc_len);
Py_XDECREF(value_coerce);
}
#else
st = _PyUnicode_AsString(value);
IDP_ResizeArray(prop, strlen(st)+1);
strcpy(prop->data.pointer, st);
strcpy(IDP_Array(prop), st);
#endif
return 0;
@ -344,7 +349,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(const char *name, IDProperty *g
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);
((double*)IDP_Array(prop))[i] = (float)PyFloat_AsDouble(item);
Py_DECREF(item);
}
break;
@ -352,7 +357,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(const char *name, IDProperty *g
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);
((int*)IDP_Array(prop))[i] = (int)PyLong_AsSsize_t(item);
Py_DECREF(item);
}
break;
@ -465,9 +470,9 @@ static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject
return BPy_Wrap_SetMapItem(self->prop, key, val);
}
static PyObject *BPy_IDGroup_SpawnIterator(BPy_IDProperty *self)
static PyObject *BPy_IDGroup_iter(BPy_IDProperty *self)
{
BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &IDGroup_Iter_Type);
BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type);
iter->group = self;
iter->mode = IDPROP_ITER_KEYS;
iter->cur = self->prop->data.group.first;
@ -480,9 +485,9 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
switch (prop->type) {
case IDP_STRING:
#ifdef USE_STRING_COERCE
return PyC_UnicodeFromByte(prop->data.pointer);
return PyC_UnicodeFromByte(IDP_Array(prop));
#else
return PyUnicode_FromString(prop->data.pointer);
return PyUnicode_FromString(IDP_Array(prop));
#endif
break;
case IDP_FLOAT:
@ -504,20 +509,37 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
return NULL;
}
for (i=0; i<prop->len; i++) {
if (prop->subtype == IDP_FLOAT) {
PyList_SET_ITEM(seq, i,
PyFloat_FromDouble(((float*)prop->data.pointer)[i]));
switch(prop->subtype) {
case IDP_FLOAT:
{
float *array= (float*)IDP_Array(prop);
for (i=0; i<prop->len; i++) {
PyList_SET_ITEM(seq, i, PyFloat_FromDouble(array[i]));
}
break;
}
else if (prop->subtype == IDP_DOUBLE) {
PyList_SET_ITEM(seq, i,
PyFloat_FromDouble(((double*)prop->data.pointer)[i]));
case IDP_DOUBLE:
{
double *array= (double*)IDP_Array(prop);
for (i=0; i<prop->len; i++) {
PyList_SET_ITEM(seq, i, PyFloat_FromDouble(array[i]));
}
break;
}
else {
PyList_SET_ITEM(seq, i,
PyLong_FromLong(((int*)prop->data.pointer)[i]));
case IDP_INT:
{
int *array= (int*)IDP_Array(prop);
for (i=0; i<prop->len; i++) {
PyList_SET_ITEM(seq, i, PyLong_FromLong(array[i]));
}
break;
}
default:
PyErr_SetString(PyExc_RuntimeError, "invalid/corrupt array type!");
Py_DECREF(seq);
return NULL;
}
return seq;
}
case IDP_IDPARRAY:
@ -595,7 +617,7 @@ static PyObject *BPy_IDGroup_Pop(BPy_IDProperty *self, PyObject *value)
static PyObject *BPy_IDGroup_IterItems(BPy_IDProperty *self)
{
BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &IDGroup_Iter_Type);
BPy_IDGroup_Iter *iter = PyObject_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type);
iter->group = self;
iter->mode = IDPROP_ITER_ITEMS;
iter->cur = self->prop->data.group.first;
@ -731,7 +753,7 @@ static PyObject *BPy_IDGroup_Update(BPy_IDProperty *self, PyObject *value)
Py_RETURN_NONE;
}
static PyObject *BPy_IDGroup_ConvertToPy(BPy_IDProperty *self)
static PyObject *BPy_IDGroup_to_dict(BPy_IDProperty *self)
{
return BPy_IDGroup_MapDataToPy(self->prop);
}
@ -773,7 +795,7 @@ static struct PyMethodDef BPy_IDGroup_methods[] = {
"updates the values in the group with the values of another or a dict"},
{"get", (PyCFunction)BPy_IDGroup_Get, METH_VARARGS,
"idprop.get(k[,d]) -> idprop[k] if k in idprop, else d. d defaults to None"},
{"convert_to_pyobject", (PyCFunction)BPy_IDGroup_ConvertToPy, METH_NOARGS,
{"to_dict", (PyCFunction)BPy_IDGroup_to_dict, METH_NOARGS,
"return a purely python version of the group"},
{NULL, NULL, 0, NULL}
};
@ -792,16 +814,16 @@ static PySequenceMethods BPy_IDGroup_Seq = {
};
static PyMappingMethods BPy_IDGroup_Mapping = {
(lenfunc)BPy_IDGroup_Map_Len, /*inquiry mp_length */
(binaryfunc)BPy_IDGroup_Map_GetItem, /*binaryfunc mp_subscript */
(lenfunc)BPy_IDGroup_Map_Len, /*inquiry mp_length */
(binaryfunc)BPy_IDGroup_Map_GetItem,/*binaryfunc mp_subscript */
(objobjargproc)BPy_IDGroup_Map_SetItem, /*objobjargproc mp_ass_subscript */
};
PyTypeObject IDGroup_Type = {
PyTypeObject BPy_IDGroup_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format "<module>.<name>" */
"Blender IDProperty", /* char *tp_name; */
sizeof( BPy_IDProperty ), /* int tp_basicsize; */
"Blender IDProperty", /* char *tp_name; */
sizeof(BPy_IDProperty), /* int tp_basicsize; */
0, /* tp_itemsize; For allocation */
/* Methods to implement standard operations */
@ -811,7 +833,7 @@ PyTypeObject IDGroup_Type = {
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
( reprfunc ) IDGroup_repr, /* reprfunc tp_repr; */
(reprfunc)BPy_IDGroup_repr, /* reprfunc tp_repr; */
/* Method suites for standard classes */
@ -821,7 +843,7 @@ PyTypeObject IDGroup_Type = {
/* More standard operations (here for binary compatibility) */
NULL, /* hashfunc tp_hash; */
(hashfunc)BPy_IDGroup_hash, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* getattrofunc tp_getattro; */
@ -850,7 +872,7 @@ PyTypeObject IDGroup_Type = {
/*** Added in release 2.2 ***/
/* Iterators */
(getiterfunc)BPy_IDGroup_SpawnIterator, /* getiterfunc tp_iter; */
(getiterfunc)BPy_IDGroup_iter, /* getiterfunc tp_iter; */
NULL, /* iternextfunc tp_iternext; */
/*** Attribute descriptor and subclassing stuff ***/
BPy_IDGroup_methods, /* struct PyMethodDef *tp_methods; */
@ -861,7 +883,7 @@ PyTypeObject IDGroup_Type = {
/*********** Main external wrapping function *******/
PyObject *BPy_Wrap_IDProperty(ID *id, IDProperty *prop, IDProperty *parent)
{
BPy_IDProperty *wrap = PyObject_New(BPy_IDProperty, &IDGroup_Type);
BPy_IDProperty *wrap = PyObject_New(BPy_IDProperty, &BPy_IDGroup_Type);
wrap->prop = prop;
wrap->parent = parent;
wrap->id = id;
@ -872,36 +894,58 @@ PyObject *BPy_Wrap_IDProperty(ID *id, IDProperty *prop, IDProperty *parent)
/********Array Wrapper********/
static PyObject *IDArray_repr(BPy_IDArray *self)
static PyTypeObject *idp_array_py_type(BPy_IDArray *self, short *is_double)
{
return PyUnicode_FromFormat("(ID Array [%d])", self->prop->len);
switch (self->prop->subtype) {
case IDP_FLOAT:
*is_double= 0;
return &PyFloat_Type;
case IDP_DOUBLE:
*is_double= 1;
return &PyFloat_Type;
case IDP_INT:
*is_double= 0;
return &PyLong_Type;
}
*is_double= 0;
return NULL;
}
static PyObject *BPy_IDArray_repr(BPy_IDArray *self)
{
return PyUnicode_FromFormat("<bpy id property array [%d]>", self->prop->len);
}
static PyObject *BPy_IDArray_GetType(BPy_IDArray *self)
{
return PyLong_FromSsize_t( self->prop->subtype );
}
switch(self->prop->subtype) {
case IDP_FLOAT:
return PyUnicode_FromString("f");
case IDP_DOUBLE:
return PyUnicode_FromString("d");
case IDP_INT:
return PyUnicode_FromString("i");
}
static PyObject *BPy_IDArray_GetLen(BPy_IDArray *self)
{
return PyLong_FromSsize_t( self->prop->len );
PyErr_SetString(PyExc_RuntimeError, "invalid/corrupt array type!");
return NULL;
}
static PyGetSetDef BPy_IDArray_getseters[] = {
{(char *)"len", (getter)BPy_IDArray_GetLen, (setter)NULL, (char *)"The length of the array, can also be gotten with len(array).", NULL},
{(char *)"type", (getter)BPy_IDArray_GetType, (setter)NULL, (char *)"The type of the data in the array, is an ant.", NULL},
/* matches pythons array.typecode */
{(char *)"typecode", (getter)BPy_IDArray_GetType, (setter)NULL, (char *)"The type of the data in the array, is an int.", NULL},
{NULL, NULL, NULL, NULL, NULL},
};
static PyObject *BPy_IDArray_ConvertToPy(BPy_IDArray *self)
static PyObject *BPy_IDArray_to_list(BPy_IDArray *self)
{
return BPy_IDGroup_MapDataToPy(self->prop);
}
static PyMethodDef BPy_IDArray_methods[] = {
{"convert_to_pyobject", (PyCFunction)BPy_IDArray_ConvertToPy, METH_NOARGS,
"return a purely python version of the group"},
{"to_list", (PyCFunction)BPy_IDArray_to_list, METH_NOARGS,
"return the array as a list"},
{NULL, NULL, 0, NULL}
};
@ -919,14 +963,11 @@ static PyObject *BPy_IDArray_GetItem(BPy_IDArray *self, int index)
switch (self->prop->subtype) {
case IDP_FLOAT:
return PyFloat_FromDouble( (double)(((float*)self->prop->data.pointer)[index]));
break;
return PyFloat_FromDouble(((float*)IDP_Array(self->prop))[index]);
case IDP_DOUBLE:
return PyFloat_FromDouble( (((double*)self->prop->data.pointer)[index]));
break;
return PyFloat_FromDouble(((double*)IDP_Array(self->prop))[index]);
case IDP_INT:
return PyLong_FromLong( (long)((int*)self->prop->data.pointer)[index] );
break;
return PyLong_FromLong((long)((int*)IDP_Array(self->prop))[index]);
}
PyErr_SetString(PyExc_RuntimeError, "invalid/corrupt array type!");
@ -951,7 +992,7 @@ static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value)
PyErr_SetString(PyExc_TypeError, "expected a float");
return -1;
}
((float*)self->prop->data.pointer)[index] = f;
((float*)IDP_Array(self->prop))[index] = f;
break;
case IDP_DOUBLE:
d= PyFloat_AsDouble(value);
@ -959,7 +1000,7 @@ static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value)
PyErr_SetString(PyExc_TypeError, "expected a float");
return -1;
}
((double*)self->prop->data.pointer)[index] = d;
((double*)IDP_Array(self->prop))[index] = d;
break;
case IDP_INT:
i= PyLong_AsSsize_t(value);
@ -968,7 +1009,7 @@ static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value)
return -1;
}
((int*)self->prop->data.pointer)[index] = i;
((int*)IDP_Array(self->prop))[index] = i;
break;
}
return 0;
@ -988,11 +1029,156 @@ static PySequenceMethods BPy_IDArray_Seq = {
NULL, /* intargfunc sq_inplace_repeat */
};
PyTypeObject IDArray_Type = {
/* sequence slice (get): idparr[a:b] */
static PyObject *BPy_IDArray_slice(BPy_IDArray *self, int begin, int end)
{
IDProperty *prop= self->prop;
PyObject *tuple;
int count;
CLAMP(begin, 0, prop->len);
if (end<0) end= prop->len+end+1;
CLAMP(end, 0, prop->len);
begin= MIN2(begin, end);
tuple= PyTuple_New(end - begin);
switch (prop->subtype) {
case IDP_FLOAT:
{
float *array= (float*)IDP_Array(prop);
for(count = begin; count < end; count++) {
PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(array[count]));
}
break;
}
case IDP_DOUBLE:
{
double *array= (double*)IDP_Array(prop);
for(count = begin; count < end; count++) {
PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(array[count]));
}
break;
}
case IDP_INT:
{
int *array= (int*)IDP_Array(prop);
for(count = begin; count < end; count++) {
PyTuple_SET_ITEM(tuple, count - begin, PyLong_FromLong(array[count]));
}
break;
}
}
return tuple;
}
/* sequence slice (set): idparr[a:b] = value */
static int BPy_IDArray_ass_slice(BPy_IDArray *self, int begin, int end, PyObject *seq)
{
IDProperty *prop= self->prop;
short is_double= 0;
const PyTypeObject *py_type= idp_array_py_type(self, &is_double);
const size_t elem_size= is_double ? sizeof(double) : sizeof(float);
size_t alloc_len;
size_t size;
void *vec;
CLAMP(begin, 0, prop->len);
CLAMP(end, 0, prop->len);
begin = MIN2(begin, end);
size = (end - begin);
alloc_len= size * elem_size;
vec= MEM_mallocN(alloc_len, "array assignment"); /* NOTE: we count on int/float being the same size here */
if(PyC_AsArray(vec, seq, size, py_type, is_double, "slice assignment: ") == -1) {
MEM_freeN(vec);
return -1;
}
memcpy((void *)(((char *)IDP_Array(prop)) + (begin * elem_size)), vec, alloc_len);
MEM_freeN(vec);
return 0;
}
static PyObject *BPy_IDArray_subscript(BPy_IDArray* self, PyObject* item)
{
if (PyIndex_Check(item)) {
Py_ssize_t i;
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return NULL;
if (i < 0)
i += self->prop->len;
return BPy_IDArray_GetItem(self, i);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, self->prop->len, &start, &stop, &step, &slicelength) < 0)
return NULL;
if (slicelength <= 0) {
return PyTuple_New(0);
}
else if (step == 1) {
return BPy_IDArray_slice(self, start, stop);
}
else {
PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors");
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
return NULL;
}
}
static int BPy_IDArray_ass_subscript(BPy_IDArray* self, PyObject* item, PyObject* value)
{
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
return -1;
if (i < 0)
i += self->prop->len;
return BPy_IDArray_SetItem(self, i, value);
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelength;
if (PySlice_GetIndicesEx((void *)item, self->prop->len, &start, &stop, &step, &slicelength) < 0)
return -1;
if (step == 1)
return BPy_IDArray_ass_slice(self, start, stop, value);
else {
PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors");
return -1;
}
}
else {
PyErr_Format(PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
return -1;
}
}
static PyMappingMethods BPy_IDArray_AsMapping = {
(lenfunc)BPy_IDArray_Len,
(binaryfunc)BPy_IDArray_subscript,
(objobjargproc)BPy_IDArray_ass_subscript
};
PyTypeObject BPy_IDArray_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format "<module>.<name>" */
"Blender IDArray", /* char *tp_name; */
sizeof( BPy_IDArray ), /* int tp_basicsize; */
sizeof(BPy_IDArray), /* int tp_basicsize; */
0, /* tp_itemsize; For allocation */
/* Methods to implement standard operations */
@ -1002,17 +1188,17 @@ PyTypeObject IDArray_Type = {
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* cmpfunc tp_compare; */
( reprfunc ) IDArray_repr, /* reprfunc tp_repr; */
(reprfunc)BPy_IDArray_repr, /* reprfunc tp_repr; */
/* Method suites for standard classes */
NULL, /* PyNumberMethods *tp_as_number; */
&BPy_IDArray_Seq, /* PySequenceMethods *tp_as_sequence; */
NULL, /* PyMappingMethods *tp_as_mapping; */
&BPy_IDArray_Seq, /* PySequenceMethods *tp_as_sequence; */
&BPy_IDArray_AsMapping, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
NULL, /* hashfunc tp_hash; */
NULL, /* hashfunc tp_hash; */
NULL, /* ternaryfunc tp_call; */
NULL, /* reprfunc tp_str; */
NULL, /* getattrofunc tp_getattro; */
@ -1106,7 +1292,7 @@ static PyObject *BPy_Group_Iter_Next(BPy_IDGroup_Iter *self)
}
}
PyTypeObject IDGroup_Iter_Type = {
PyTypeObject BPy_IDGroup_Iter_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
/* For printing, in format "<module>.<name>" */
"Blender IDGroup_Iter", /* char *tp_name; */
@ -1165,7 +1351,7 @@ PyTypeObject IDGroup_Iter_Type = {
void IDProp_Init_Types(void)
{
PyType_Ready( &IDGroup_Type );
PyType_Ready( &IDGroup_Iter_Type );
PyType_Ready( &IDArray_Type );
PyType_Ready(&BPy_IDGroup_Type);
PyType_Ready(&BPy_IDGroup_Iter_Type);
PyType_Ready(&BPy_IDArray_Type);
}

@ -37,14 +37,15 @@ struct BPy_IDGroup_Iter;
typedef struct BPy_IDProperty {
PyObject_VAR_HEAD
struct ID *id;
struct IDProperty *prop, *parent;
struct IDProperty *prop; /* must be second member */
struct IDProperty *parent;
PyObject *data_wrap;
} BPy_IDProperty;
typedef struct BPy_IDArray {
PyObject_VAR_HEAD
struct ID *id;
struct IDProperty *prop;
struct IDProperty *prop; /* must be second member */
} BPy_IDArray;
typedef struct BPy_IDGroup_Iter {

@ -38,6 +38,76 @@
#define PYC_INTERPRETER_ACTIVE (((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL)
/* array utility function */
int PyC_AsArray(void *array, PyObject *value, const int length, const PyTypeObject *type, const short is_double, const char *error_prefix)
{
PyObject *value_fast;
int value_len;
int i;
if(!(value_fast=PySequence_Fast(value, error_prefix))) {
return -1;
}
value_len= PySequence_Fast_GET_SIZE(value_fast);
if(value_len != length) {
Py_DECREF(value);
PyErr_Format(PyExc_TypeError,
"%.200s: invalid sequence length. expected %d, got %d",
error_prefix, length, value_len);
return -1;
}
/* for each type */
if(type == &PyFloat_Type) {
if(is_double) {
double *array_double= array;
for(i=0; i<length; i++) {
array_double[i]= PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
}
}
else {
float *array_float= array;
for(i=0; i<length; i++) {
array_float[i]= PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
}
}
}
else if(type == &PyLong_Type) {
/* could use is_double for 'long int' but no use now */
int *array_int= array;
for(i=0; i<length; i++) {
array_int[i]= PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i));
}
}
else if(type == &PyBool_Type) {
int *array_bool= array;
for(i=0; i<length; i++) {
array_bool[i]= (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0);
}
}
else {
Py_DECREF(value_fast);
PyErr_Format(PyExc_TypeError,
"%s: internal error %s is invalid",
error_prefix, type->tp_name);
return -1;
}
Py_DECREF(value_fast);
if(PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
"%s: one or more items could not be used as a %s",
error_prefix, type->tp_name);
return -1;
}
return 0;
}
/* for debugging */
void PyC_ObSpit(const char *name, PyObject *var) {
fprintf(stderr, "<%s> : ", name);

@ -35,7 +35,7 @@ void PyC_LineSpit(void);
PyObject * PyC_ExceptionBuffer(void);
PyObject * PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...);
void PyC_FileAndNum(const char **filename, int *lineno);
int PyC_AsArray(void *array, PyObject *value, int length, PyTypeObject *type, const char *error_prefix);
int PyC_AsArray(void *array, PyObject *value, const int length, const PyTypeObject *type, const short is_double, const char *error_prefix);
/* follow http://www.python.org/dev/peps/pep-0383/ */
PyObject * PyC_UnicodeFromByte(const char *str);

@ -459,7 +459,7 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject
return NULL;
}
if(pydef && PyC_AsArray(def, pydef, size, &PyBool_Type, "BoolVectorProperty(default=sequence)") < 0)
if(pydef && PyC_AsArray(def, pydef, size, &PyBool_Type, FALSE, "BoolVectorProperty(default=sequence)") < 0)
return NULL;
if (bpy_prop_callback_check(update_cb, 2) == -1) {
@ -603,7 +603,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject
return NULL;
}
if(pydef && PyC_AsArray(def, pydef, size, &PyLong_Type, "IntVectorProperty(default=sequence)") < 0)
if(pydef && PyC_AsArray(def, pydef, size, &PyLong_Type, FALSE, "IntVectorProperty(default=sequence)") < 0)
return NULL;
if (bpy_prop_callback_check(update_cb, 2) == -1) {
@ -759,7 +759,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec
return NULL;
}
if(pydef && PyC_AsArray(def, pydef, size, &PyFloat_Type, "FloatVectorProperty(default=sequence)") < 0)
if(pydef && PyC_AsArray(def, pydef, size, &PyFloat_Type, FALSE, "FloatVectorProperty(default=sequence)") < 0)
return NULL;
if (bpy_prop_callback_check(update_cb, 2) == -1) {

@ -122,63 +122,3 @@ short BPy_errors_to_report(ReportList *reports)
Py_DECREF(pystring_format); // workaround
return 1;
}
/* array utility function */
int PyC_AsArray(void *array, PyObject *value, int length, PyTypeObject *type, const char *error_prefix)
{
PyObject *value_fast;
int value_len;
int i;
if(!(value_fast=PySequence_Fast(value, error_prefix))) {
return -1;
}
value_len= PySequence_Fast_GET_SIZE(value_fast);
if(value_len != length) {
Py_DECREF(value);
PyErr_Format(PyExc_TypeError,
"%.200s: invalid sequence length. expected %d, got %d",
error_prefix, length, value_len);
return -1;
}
/* for each type */
if(type == &PyFloat_Type) {
float *array_float= array;
for(i=0; i<length; i++) {
array_float[i]= PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
}
}
else if(type == &PyLong_Type) {
int *array_int= array;
for(i=0; i<length; i++) {
array_int[i]= PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i));
}
}
else if(type == &PyBool_Type) {
int *array_bool= array;
for(i=0; i<length; i++) {
array_bool[i]= (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0);
}
}
else {
Py_DECREF(value_fast);
PyErr_Format(PyExc_TypeError,
"%s: internal error %s is invalid",
error_prefix, type->tp_name);
return -1;
}
Py_DECREF(value_fast);
if(PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
"%s: one or more items could not be used as a %s",
error_prefix, type->tp_name);
return -1;
}
return 0;
}