merge from trunk #37722

This commit is contained in:
Xiao Xiangquan
2011-06-24 03:30:50 +00:00
parent 9a2f36b50f
commit b429af10d0
219 changed files with 16786 additions and 16625 deletions

View File

@@ -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:
@@ -553,6 +575,7 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
return NULL;
PyDict_SetItemString(dict, loop->name, wrap);
Py_DECREF(wrap);
}
return dict;
}
@@ -595,7 +618,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 +754,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 +796,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 +815,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 +834,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 +844,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 +873,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 +884,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 +895,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 +964,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 +993,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 +1001,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 +1010,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 +1030,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 +1189,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 +1293,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 +1352,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);
}

View File

@@ -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 {

View File

@@ -1634,7 +1634,7 @@ static int Vector_setSwizzle(VectorObject *self, PyObject *value, void *closure)
size_from= axis_from;
}
else if((size_from=mathutils_array_parse(vec_assign, 2, 4, value, "mathutils.Vector.**** = swizzle assignment")) == -1) {
else if(PyErr_Clear(), (size_from=mathutils_array_parse(vec_assign, 2, 4, value, "mathutils.Vector.**** = swizzle assignment")) == -1) {
return -1;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -45,6 +45,7 @@ set(SRC
bpy_app.c
bpy_driver.c
bpy_interface.c
bpy_intern_string.c
bpy_library.c
bpy_operator.c
bpy_operator_wrap.c
@@ -60,6 +61,7 @@ set(SRC
bpy.h
bpy_app.h
bpy_driver.h
bpy_intern_string.h
bpy_operator.h
bpy_operator_wrap.h
bpy_props.h

View File

@@ -43,6 +43,7 @@
#include "bpy_rna.h"
#include "bpy_util.h"
#include "bpy_traceback.h"
#include "bpy_intern_string.h"
#include "DNA_space_types.h"
#include "DNA_text_types.h"
@@ -199,13 +200,15 @@ void BPY_python_start(int argc, const char **argv)
/* allow to use our own included python */
PyC_SetHomePath(BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL));
/* Python 3.2 now looks for '2.57/python/include/python3.2d/pyconfig.h' to parse
/* Python 3.2 now looks for '2.58/python/include/python3.2d/pyconfig.h' to parse
* from the 'sysconfig' module which is used by 'site', so for now disable site.
* alternatively we could copy the file. */
Py_NoSiteFlag= 1;
Py_Initialize();
bpy_intern_string_init();
// PySys_SetArgv(argc, argv); // broken in py3, not a huge deal
/* sigh, why do python guys not have a char** version anymore? :( */
{
@@ -251,7 +254,9 @@ void BPY_python_end(void)
pyrna_free_types();
/* clear all python data from structs */
bpy_intern_string_exit();
Py_Finalize();
#ifdef TIME_PY_RUN

View File

@@ -0,0 +1,57 @@
/*
* $Id: bpy_intern_string.c 37626 2011-06-18 23:22:55Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/intern/bpy_intern_string.c
* \ingroup pythonintern
*/
#include <Python.h>
PyObject *bpy_intern_str_register;
PyObject *bpy_intern_str_unregister;
PyObject *bpy_intern_str_bl_rna;
PyObject *bpy_intern_str_order;
PyObject *bpy_intern_str_attr;
PyObject *bpy_intern_str___slots__;
PyObject *bpy_intern_str___bases__;
void bpy_intern_string_init(void)
{
bpy_intern_str_register= PyUnicode_FromString("register");
bpy_intern_str_unregister= PyUnicode_FromString("unregister");;
bpy_intern_str_bl_rna= PyUnicode_FromString("bl_rna");
bpy_intern_str_order= PyUnicode_FromString("order");
bpy_intern_str_attr= PyUnicode_FromString("attr");
bpy_intern_str___slots__= PyUnicode_FromString("__slots__");
}
void bpy_intern_string_exit(void)
{
Py_DECREF(bpy_intern_str_register);
Py_DECREF(bpy_intern_str_unregister);
Py_DECREF(bpy_intern_str_bl_rna);
Py_DECREF(bpy_intern_str_order);
Py_DECREF(bpy_intern_str_attr);
Py_DECREF(bpy_intern_str___slots__);
}

View File

@@ -0,0 +1,37 @@
/*
* $Id: bpy_intern_string.h 37626 2011-06-18 23:22:55Z gsrb3d $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/python/intern/bpy_intern_string.h
* \ingroup pythonintern
*/
void bpy_intern_string_init(void);
void bpy_intern_string_exit(void);
extern PyObject *bpy_intern_str_register;
extern PyObject *bpy_intern_str_unregister;
extern PyObject *bpy_intern_str_bl_rna;
extern PyObject *bpy_intern_str_order;
extern PyObject *bpy_intern_str_attr;
extern PyObject *bpy_intern_str___slots__;

View File

@@ -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) {

View File

@@ -39,6 +39,7 @@
#include "bpy_props.h"
#include "bpy_util.h"
#include "bpy_rna_callback.h"
#include "bpy_intern_string.h"
#ifdef USE_PYRNA_INVALIDATE_WEAKREF
#include "MEM_guardedalloc.h"
@@ -1380,12 +1381,8 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
if (RNA_property_array_check(ptr, prop)) {
int ok= 1;
/* done getting the length */
ok= pyrna_py_to_array(ptr, prop, data, value, error_prefix);
if (!ok) {
if(pyrna_py_to_array(ptr, prop, data, value, error_prefix) == -1) {
return -1;
}
}
@@ -1476,7 +1473,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
param= _PyUnicode_AsString(value);
}
#else // USE_STRING_COERCE
param= _PyUnicode_AsStringSize(value);
param= _PyUnicode_AsString(value);
#endif // USE_STRING_COERCE
if (param==NULL) {
@@ -1767,8 +1764,8 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P
if (totdim > 1) {
/* char error_str[512]; */
if (!pyrna_py_to_array_index(&self->ptr, self->prop, self->arraydim, self->arrayoffset, index, value, "")) {
/* PyErr_SetString(PyExc_AttributeError, error_str); */
if (pyrna_py_to_array_index(&self->ptr, self->prop, self->arraydim, self->arrayoffset, index, value, "") == -1) {
/* error is set */
ret= -1;
}
}
@@ -5221,7 +5218,7 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
item= pyrna_struct_CreatePyObject(&ptr);
/* note, must set the class not the __dict__ else the internal slots are not updated correctly */
PyObject_SetAttrString(newclass, "bl_rna", item);
PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item);
Py_DECREF(item);
/* done with rna instance */
@@ -5283,7 +5280,7 @@ static PyObject* pyrna_srna_ExternalType(StructRNA *srna)
//PyObject *slots= PyObject_GetAttrString(newclass, "__slots__"); // cant do this because it gets superclasses values!
//PyObject *bases= PyObject_GetAttrString(newclass, "__bases__"); // can do this but faster not to.
PyObject *bases= ((PyTypeObject *)newclass)->tp_bases;
PyObject *slots= PyDict_GetItemString(((PyTypeObject *)newclass)->tp_dict, "__slots__");
PyObject *slots= PyDict_GetItem(((PyTypeObject *)newclass)->tp_dict, bpy_intern_str___slots__);
if(slots==NULL) {
fprintf(stderr, "pyrna_srna_ExternalType: expected class '%s' to have __slots__ defined\n\nSee bpy_types.py\n", idname);
@@ -5653,7 +5650,7 @@ StructRNA *pyrna_struct_as_srna(PyObject *self, int parent, const char *error_pr
/* ack, PyObject_GetAttrString wont look up this types tp_dict first :/ */
if(PyType_Check(self)) {
py_srna= (BPy_StructRNA *)PyDict_GetItemString(((PyTypeObject *)self)->tp_dict, "bl_rna");
py_srna= (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna);
Py_XINCREF(py_srna);
}
@@ -5661,7 +5658,7 @@ StructRNA *pyrna_struct_as_srna(PyObject *self, int parent, const char *error_pr
/* be very careful with this since it will return a parent classes srna.
* modifying this will do confusing stuff! */
if(py_srna==NULL)
py_srna= (BPy_StructRNA*)PyObject_GetAttrString(self, "bl_rna");
py_srna= (BPy_StructRNA*)PyObject_GetAttr(self, bpy_intern_str_bl_rna);
}
if(py_srna==NULL) {
@@ -5751,7 +5748,7 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item
py_srna_cobject= PyCapsule_New(srna, NULL, NULL);
/* not 100% nice :/, modifies the dict passed, should be ok */
PyDict_SetItemString(py_kw, "attr", key);
PyDict_SetItem(py_kw, bpy_intern_str_attr, key);
args_fake= PyTuple_New(1);
PyTuple_SET_ITEM(args_fake, 0, py_srna_cobject);
@@ -5798,7 +5795,7 @@ static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict)
/* 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)) {
if((order= PyDict_GetItem(class_dict, bpy_intern_str_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);
@@ -6044,9 +6041,10 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PyGILState_STATE gilstate;
#ifdef USE_PEDANTIC_WRITE
const int is_operator= RNA_struct_is_a(ptr->type, &RNA_Operator);
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);
const short is_readonly= strstr("draw", func_id) || /*strstr("render", func_id) ||*/ !is_operator;
#endif
py_class= RNA_struct_py_type_get(ptr->type);
@@ -6102,6 +6100,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
* Although this is annoying to have to impliment a part of pythons typeobject.c:type_call().
*/
if(py_class->tp_init) {
#ifdef USE_PEDANTIC_WRITE
const int prev_write= rna_disallow_writes;
rna_disallow_writes= is_operator ? FALSE : TRUE; /* only operators can write on __init__ */
#endif
/* true in most cases even when the class its self doesn't define an __init__ function. */
args= PyTuple_New(0);
if (py_class->tp_init(py_srna, args, NULL) < 0) {
@@ -6110,11 +6113,16 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
/* err set below */
}
Py_DECREF(args);
#ifdef USE_PEDANTIC_WRITE
rna_disallow_writes= prev_write;
#endif
}
py_class_instance= py_srna;
#else
const int prev_write= rna_disallow_writes;
rna_disallow_writes= TRUE;
/* 'almost' all the time calling the class isn't needed.
* We could just do...
py_class_instance= py_srna;
@@ -6128,7 +6136,10 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
py_class_instance= PyObject_Call(py_class, args, NULL);
Py_DECREF(args);
rna_disallow_writes= prev_write;
#endif
if(py_class_instance == NULL) {
err= -1; /* so the error is not overridden below */
}
@@ -6303,7 +6314,7 @@ static void bpy_class_free(void *pyob_ptr)
// PyDict_Clear(((PyTypeObject*)self)->tp_dict);
//
// remove the rna attribute instead.
PyDict_DelItemString(((PyTypeObject *)self)->tp_dict, "bl_rna");
PyDict_DelItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna);
if(PyErr_Occurred())
PyErr_Clear();
@@ -6409,7 +6420,7 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class
const char *identifier;
PyObject *py_cls_meth;
if(PyDict_GetItemString(((PyTypeObject*)py_class)->tp_dict, "bl_rna")) {
if(PyDict_GetItem(((PyTypeObject*)py_class)->tp_dict, bpy_intern_str_bl_rna)) {
PyErr_SetString(PyExc_AttributeError, "register_class(...): already registered as a subclass");
return NULL;
}
@@ -6474,7 +6485,7 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class
return NULL;
/* call classed register method () */
py_cls_meth= PyObject_GetAttrString(py_class, "register");
py_cls_meth= PyObject_GetAttr(py_class, bpy_intern_str_register);
if(py_cls_meth == NULL) {
PyErr_Clear();
}
@@ -6532,7 +6543,7 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
StructRNA *srna;
PyObject *py_cls_meth;
/*if(PyDict_GetItemString(((PyTypeObject*)py_class)->tp_dict, "bl_rna")==NULL) {
/*if(PyDict_GetItem(((PyTypeObject*)py_class)->tp_dict, bpy_intern_str_bl_rna)==NULL) {
PWM_cursor_wait(0);
PyErr_SetString(PyExc_ValueError, "unregister_class(): not a registered as a subclass");
return NULL;
@@ -6551,7 +6562,7 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
}
/* call classed unregister method */
py_cls_meth= PyObject_GetAttrString(py_class, "unregister");
py_cls_meth= PyObject_GetAttr(py_class, bpy_intern_str_unregister);
if(py_cls_meth == NULL) {
PyErr_Clear();
}
@@ -6601,7 +6612,7 @@ static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_cla
/* call unregister */
unreg(CTX_data_main(C), srna); /* calls bpy_class_free, this decref's py_class */
PyDict_DelItemString(((PyTypeObject *)py_class)->tp_dict, "bl_rna");
PyDict_DelItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna);
if(PyErr_Occurred())
PyErr_Clear(); //return NULL;

View File

@@ -68,17 +68,24 @@ static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[]
/* check that a sequence contains dimsize[dim] items */
const int seq_size= PySequence_Size(seq);
if(seq_size == -1) {
PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not %s", error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
return 0;
PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'",
error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
return -1;
}
for (i= 0; i < seq_size; i++) {
PyObject *item;
int ok= 1;
item= PySequence_GetItem(seq, i);
if (!PySequence_Check(item)) {
if(item == NULL) {
PyErr_Format(PyExc_TypeError, "%s sequence type '%s' failed to retrieve index %d",
error_prefix, Py_TYPE(seq)->tp_name, i);
ok= 0;
}
else if (!PySequence_Check(item)) {
/* BLI_snprintf(error_str, error_str_size, "expected a sequence of %s", item_type_str); */
PyErr_Format(PyExc_TypeError, "%s expected a sequence of %s, not %s", error_prefix, item_type_str, Py_TYPE(item)->tp_name);
PyErr_Format(PyExc_TypeError, "%s expected a sequence of %s, not %s",
error_prefix, item_type_str, Py_TYPE(item)->tp_name);
ok= 0;
}
/* arr[3][4][5]
@@ -88,42 +95,50 @@ static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[]
dim=0 */
else if (PySequence_Size(item) != dimsize[dim + 1]) {
/* BLI_snprintf(error_str, error_str_size, "sequences of dimension %d should contain %d items", (int)dim + 1, (int)dimsize[dim + 1]); */
PyErr_Format(PyExc_ValueError, "%s sequences of dimension %d should contain %d items", error_prefix, (int)dim + 1, (int)dimsize[dim + 1]);
PyErr_Format(PyExc_ValueError, "%s sequences of dimension %d should contain %d items",
error_prefix, (int)dim + 1, (int)dimsize[dim + 1]);
ok= 0;
}
else if (!validate_array_type(item, dim + 1, totdim, dimsize, check_item_type, item_type_str, error_prefix)) {
else if (validate_array_type(item, dim + 1, totdim, dimsize, check_item_type, item_type_str, error_prefix) == -1) {
ok= 0;
}
Py_DECREF(item);
Py_XDECREF(item);
if (!ok)
return 0;
return -1;
}
}
else {
/* check that items are of correct type */
const int seq_size= PySequence_Size(seq);
if(seq_size == -1) {
PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not %s", error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
return 0;
PyErr_Format(PyExc_ValueError, "%s sequence expected at dimension %d, not '%s'",
error_prefix, (int)dim + 1, Py_TYPE(seq)->tp_name);
return -1;
}
for (i= 0; i < seq_size; i++) {
PyObject *item= PySequence_GetItem(seq, i);
if (!check_item_type(item)) {
if(item == NULL) {
PyErr_Format(PyExc_TypeError, "%s sequence type '%s' failed to retrieve index %d",
error_prefix, Py_TYPE(seq)->tp_name, i);
return -1;
}
else if (!check_item_type(item)) {
Py_DECREF(item);
/* BLI_snprintf(error_str, error_str_size, "sequence items should be of type %s", item_type_str); */
PyErr_Format(PyExc_TypeError, "%s expected sequence items of type %s, not %s", error_prefix, item_type_str, Py_TYPE(item)->tp_name);
return 0;
PyErr_Format(PyExc_TypeError, "%s expected sequence items of type %s, not %s",
error_prefix, item_type_str, Py_TYPE(item)->tp_name);
return -1;
}
Py_DECREF(item);
}
}
return 1;
return 0; /* ok */
}
/* Returns the number of items in a single- or multi-dimensional sequence. */
@@ -136,8 +151,21 @@ static int count_items(PyObject *seq, int dim)
int i;
for (i= 0; i < seq_size; i++) {
PyObject *item= PySequence_GetItem(seq, i);
totitem += count_items(item, dim - 1);
Py_DECREF(item);
if(item) {
const int tot= count_items(item, dim - 1);
Py_DECREF(item);
if(tot != -1) {
totitem += tot;
}
else {
totitem= -1;
break;
}
}
else {
totitem= -1;
break;
}
}
}
else {
@@ -156,18 +184,24 @@ static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA
totdim= RNA_property_array_dimension(ptr, prop, dimsize);
tot= count_items(rvalue, totdim - lvalue_dim);
if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) {
if(tot == -1) {
PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, error validating the sequence length",
error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop));
return -1;
}
else if ((RNA_property_flag(prop) & PROP_DYNAMIC) && lvalue_dim == 0) {
if (RNA_property_array_length(ptr, prop) != tot) {
#if 0
/* length is flexible */
if (!RNA_property_dynamic_array_set_length(ptr, prop, tot)) {
/* BLI_snprintf(error_str, error_str_size, "%s.%s: array length cannot be changed to %d", RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot); */
PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot);
return 0;
PyErr_Format(PyExc_ValueError, "%s %s.%s: array length cannot be changed to %d",
error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), tot);
return -1;
}
#else
*totitem= tot;
return 1;
return 0;
#endif
}
@@ -204,14 +238,15 @@ static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA
if (tot != len) {
/* BLI_snprintf(error_str, error_str_size, "sequence must have length of %d", len); */
PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, sequence must have %d items total, not %d", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), len, tot);
return 0;
PyErr_Format(PyExc_ValueError, "%s %.200s.%.200s, sequence must have %d items total, not %d",
error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), len, tot);
return -1;
}
}
*totitem= len;
return 1;
return 0;
}
static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, int *totitem, const char *error_prefix)
@@ -221,8 +256,8 @@ static int validate_array(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop,
/* validate type first because length validation may modify property array length */
if (!validate_array_type(rvalue, lvalue_dim, totdim, dimsize, check_item_type, item_type_str, error_prefix))
return 0;
if (validate_array_type(rvalue, lvalue_dim, totdim, dimsize, check_item_type, item_type_str, error_prefix) == -1)
return -1;
return validate_array_length(rvalue, ptr, prop, lvalue_dim, totitem, error_prefix);
}
@@ -250,25 +285,39 @@ static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int
int totdim= RNA_property_array_dimension(ptr, prop, NULL);
const int seq_size= PySequence_Size(seq);
assert(seq_size != -1);
/* General note for 'data' being NULL or PySequence_GetItem() failing.
*
* This should never be NULL since we validated it, _but_ some triky python
* developer could write their own sequence type which succeeds on
* validating but fails later somehow, so include checks for safety. */
for (i= 0; i < seq_size; i++) {
if(seq_size == -1) {
return NULL;
}
for (i= 0; (i < seq_size) && data; i++) {
PyObject *item= PySequence_GetItem(seq, i);
if(item) {
if (dim + 1 < totdim) {
data= copy_values(item, ptr, prop, dim + 1, data, item_size, index, convert_item, rna_set_index);
}
else {
data= copy_value_single(item, ptr, prop, data, item_size, index, convert_item, rna_set_index);
}
if (dim + 1 < totdim) {
data= copy_values(item, ptr, prop, dim + 1, data, item_size, index, convert_item, rna_set_index);
Py_DECREF(item);
/* data may be NULL, but the for loop checks */
}
else {
data= copy_value_single(item, ptr, prop, data, item_size, index, convert_item, rna_set_index);
return NULL;
}
Py_DECREF(item);
}
return data;
}
static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
static int py_to_array(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, char *param_data, ItemTypeCheckFunc check_item_type, const char *item_type_str, int item_size, ItemConvertFunc convert_item, RNA_SetArrayFunc rna_set_array, const char *error_prefix)
{
/*int totdim, dim_size[MAX_ARRAY_DIMENSION];*/
int totitem;
@@ -276,8 +325,8 @@ static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *p
/*totdim= RNA_property_array_dimension(ptr, prop, dim_size);*/ /*UNUSED*/
if (!validate_array(py, ptr, prop, 0, check_item_type, item_type_str, &totitem, error_prefix)) {
return 0;
if (validate_array(seq, ptr, prop, 0, check_item_type, item_type_str, &totitem, error_prefix) == -1) {
return -1;
}
if (totitem) {
@@ -297,16 +346,27 @@ static int py_to_array(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, char *p
data= PyMem_MALLOC(item_size * totitem);
}
copy_values(py, ptr, prop, 0, data, item_size, NULL, convert_item, NULL);
/* will only fail in very rare cases since we already validated the
* python data, the check here is mainly for completeness. */
if(copy_values(seq, ptr, prop, 0, data, item_size, NULL, convert_item, NULL) != NULL) {
if (param_data==NULL) {
/* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */
rna_set_array(ptr, prop, data);
PyMem_FREE(data);
}
}
else {
if (param_data==NULL) {
PyMem_FREE(data);
}
if (param_data==NULL) {
/* NULL can only pass through in case RNA property arraylength is 0 (impossible?) */
rna_set_array(ptr, prop, data);
PyMem_FREE(data);
PyErr_Format(PyExc_TypeError, "%s internal error parsing sequence of type '%s' after successful validation",
error_prefix, Py_TYPE(seq)->tp_name);
return -1;
}
}
return 1;
return 0;
}
static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, int arrayoffset, int index, ItemTypeCheckFunc check_item_type, const char *item_type_str, ItemConvertFunc convert_item, RNA_SetIndexFunc rna_set_index, const char *error_prefix)
@@ -335,21 +395,24 @@ static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, i
if(lvalue_dim == totdim) { /* single item, assign directly */
if(!check_item_type(py)) {
PyErr_Format(PyExc_TypeError, "%s %.200s.%.200s, expected a %s type, not %s", error_prefix, RNA_struct_identifier(ptr->type), RNA_property_identifier(prop), item_type_str, Py_TYPE(py)->tp_name);
return 0;
PyErr_Format(PyExc_TypeError, "%s %.200s.%.200s, expected a %s type, not %s",
error_prefix, RNA_struct_identifier(ptr->type),
RNA_property_identifier(prop), item_type_str,
Py_TYPE(py)->tp_name);
return -1;
}
copy_value_single(py, ptr, prop, NULL, 0, &index, convert_item, rna_set_index);
}
else {
if (!validate_array(py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix)) {
return 0;
if (validate_array(py, ptr, prop, lvalue_dim, check_item_type, item_type_str, &totitem, error_prefix) == -1) {
return -1;
}
if (totitem) {
copy_values(py, ptr, prop, lvalue_dim, NULL, 0, &index, convert_item, rna_set_index);
}
}
return 1;
return 0;
}
static void py_to_float(PyObject *py, char *data)
@@ -414,7 +477,7 @@ int pyrna_py_to_array(PointerRNA *ptr, PropertyRNA *prop, char *param_data, PyOb
break;
default:
PyErr_SetString(PyExc_TypeError, "not an array type");
ret= 0;
ret= -1;
}
return ret;
@@ -435,7 +498,7 @@ int pyrna_py_to_array_index(PointerRNA *ptr, PropertyRNA *prop, int arraydim, in
break;
default:
PyErr_SetString(PyExc_TypeError, "not an array type");
ret= 0;
ret= -1;
}
return ret;

View File

@@ -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;
}