merge from trunk #37722
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
57
source/blender/python/intern/bpy_intern_string.c
Executable file
57
source/blender/python/intern/bpy_intern_string.c
Executable 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__);
|
||||
}
|
||||
37
source/blender/python/intern/bpy_intern_string.h
Executable file
37
source/blender/python/intern/bpy_intern_string.h
Executable 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__;
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user