Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2009-07-01 17:31:36 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-07-01 17:31:36 +0400
commit1a86cd6dcda1b6bca338d096b6a4b332d0b39822 (patch)
tree87a5fca2015899cccee526b4fce9c1405647b2be
parent82055c82170885249bf922b05a5c7a3186c07c71 (diff)
slice support working in py3 for Vector and Matrix types.
Added slice to PyRNA collections and arrays (py3 only). eg. some_verts = mesh.verts[0:10] some_rna_array[4:-1] = [0,1,2,3] Collections dont support assignment, when assigning slices, resizing the array isnt support like with python lists.
-rw-r--r--source/blender/python/generic/matrix.c82
-rw-r--r--source/blender/python/generic/vector.c92
-rw-r--r--source/blender/python/intern/bpy_rna.c285
3 files changed, 380 insertions, 79 deletions
diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c
index 41411559fe0..34d29dacdd1 100644
--- a/source/blender/python/generic/matrix.c
+++ b/source/blender/python/generic/matrix.c
@@ -760,8 +760,7 @@ static PyObject *Matrix_slice(MatrixObject * self, int begin, int end)
}
/*----------------------------object[z:y]------------------------
sequence slice (set)*/
-static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
- PyObject * seq)
+static int Matrix_ass_slice(MatrixObject * self, int begin, int end, PyObject * seq)
{
int i, x, y, size, sub_size = 0;
float mat[16], f;
@@ -999,6 +998,83 @@ static PySequenceMethods Matrix_SeqMethods = {
};
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static PyObject *Matrix_subscript(MatrixObject* 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->rowSize;
+ return Matrix_item(self, i);
+ } else if (PySlice_Check(item)) {
+ Py_ssize_t start, stop, step, slicelength;
+
+ if (PySlice_GetIndicesEx((PySliceObject*)item, self->rowSize, &start, &stop, &step, &slicelength) < 0)
+ return NULL;
+
+ if (slicelength <= 0) {
+ return PyList_New(0);
+ }
+ else if (step == 1) {
+ return Matrix_slice(self, start, stop);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies");
+ return NULL;
+ }
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "vector indices must be integers, not %.200s",
+ item->ob_type->tp_name);
+ return NULL;
+ }
+}
+
+static int Matrix_ass_subscript(MatrixObject* 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->rowSize;
+ return Matrix_ass_item(self, i, value);
+ }
+ else if (PySlice_Check(item)) {
+ Py_ssize_t start, stop, step, slicelength;
+
+ if (PySlice_GetIndicesEx((PySliceObject*)item, self->rowSize, &start, &stop, &step, &slicelength) < 0)
+ return -1;
+
+ if (step == 1)
+ return Matrix_ass_slice(self, start, stop, value);
+ else {
+ PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies");
+ return -1;
+ }
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "matrix indices must be integers, not %.200s",
+ item->ob_type->tp_name);
+ return -1;
+ }
+}
+
+static PyMappingMethods Matrix_AsMapping = {
+ (lenfunc)Matrix_len,
+ (binaryfunc)Matrix_subscript,
+ (objobjargproc)Matrix_ass_subscript
+};
+#endif /* (PY_VERSION_HEX >= 0x03000000) */
+
+
+
#if (PY_VERSION_HEX >= 0x03000000)
static PyNumberMethods Matrix_NumMethods = {
(binaryfunc) Matrix_add, /*nb_add*/
@@ -1106,7 +1182,7 @@ PyTypeObject matrix_Type = {
(reprfunc) Matrix_repr, /*tp_repr*/
&Matrix_NumMethods, /*tp_as_number*/
&Matrix_SeqMethods, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
+ &Matrix_AsMapping, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c
index 0af646bd82f..5abc68c63ca 100644
--- a/source/blender/python/generic/vector.c
+++ b/source/blender/python/generic/vector.c
@@ -1051,16 +1051,100 @@ static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa
Py_RETURN_FALSE;
}
}
+
/*-----------------PROTCOL DECLARATIONS--------------------------*/
static PySequenceMethods Vector_SeqMethods = {
(inquiry) Vector_len, /* sq_length */
(binaryfunc) 0, /* sq_concat */
- (ssizeargfunc) 0, /* sq_repeat */
+ (ssizeargfunc) 0, /* sq_repeat */
(ssizeargfunc) Vector_item, /* sq_item */
- (ssizessizeargfunc) Vector_slice, /* sq_slice */
+#if (PY_VERSION_HEX < 0x03000000)
+ (ssizessizeargfunc) Vector_slice, /* sq_slice */ /* PY2 ONLY */
+#else
+ NULL,
+#endif
(ssizeobjargproc) Vector_ass_item, /* sq_ass_item */
- (ssizessizeobjargproc) Vector_ass_slice, /* sq_ass_slice */
+#if (PY_VERSION_HEX < 0x03000000)
+ (ssizessizeobjargproc) Vector_ass_slice, /* sq_ass_slice */ /* PY2 ONLY */
+#else
+ NULL,
+#endif
+};
+
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static PyObject *Vector_subscript(VectorObject* 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->size;
+ return Vector_item(self, i);
+ } else if (PySlice_Check(item)) {
+ Py_ssize_t start, stop, step, slicelength;
+
+ if (PySlice_GetIndicesEx((PySliceObject*)item, self->size, &start, &stop, &step, &slicelength) < 0)
+ return NULL;
+
+ if (slicelength <= 0) {
+ return PyList_New(0);
+ }
+ else if (step == 1) {
+ return Vector_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",
+ item->ob_type->tp_name);
+ return NULL;
+ }
+}
+
+static int Vector_ass_subscript(VectorObject* 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->size;
+ return Vector_ass_item(self, i, value);
+ }
+ else if (PySlice_Check(item)) {
+ Py_ssize_t start, stop, step, slicelength;
+
+ if (PySlice_GetIndicesEx((PySliceObject*)item, self->size, &start, &stop, &step, &slicelength) < 0)
+ return -1;
+
+ if (step == 1)
+ return Vector_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",
+ item->ob_type->tp_name);
+ return -1;
+ }
+}
+
+static PyMappingMethods Vector_AsMapping = {
+ (lenfunc)Vector_len,
+ (binaryfunc)Vector_subscript,
+ (objobjargproc)Vector_ass_subscript
};
+#endif /* (PY_VERSION_HEX >= 0x03000000) */
#if (PY_VERSION_HEX >= 0x03000000)
static PyNumberMethods Vector_NumMethods = {
@@ -1813,7 +1897,7 @@ PyTypeObject vector_Type = {
&Vector_NumMethods, /* PyNumberMethods *tp_as_number; */
&Vector_SeqMethods, /* PySequenceMethods *tp_as_sequence; */
- NULL, /* PyMappingMethods *tp_as_mapping; */
+ &Vector_AsMapping, /* PyMappingMethods *tp_as_mapping; */
/* More standard operations (here for binary compatibility) */
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index e13f02c5529..4729620bb8a 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -35,6 +35,7 @@
#include "RNA_define.h" /* for defining our own rna */
#include "MEM_guardedalloc.h"
+#include "BKE_utildefines.h"
#include "BKE_context.h"
#include "BKE_global.h" /* evil G.* */
#include "BKE_report.h"
@@ -820,108 +821,246 @@ static Py_ssize_t pyrna_prop_len( BPy_PropertyRNA * self )
return len;
}
-static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key )
+/* internal use only */
+static PyObject *prop_subscript_collection_int(BPy_PropertyRNA * self, int keynum)
{
- PyObject *ret;
PointerRNA newptr;
- int keynum = 0;
- char *keyname = NULL;
-
+
+ if(keynum < 0) keynum += RNA_property_collection_length(&self->ptr, self->prop);
+
+ if(RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr))
+ return pyrna_struct_CreatePyObject(&newptr);
+
+ PyErr_SetString(PyExc_IndexError, "out of range");
+ return NULL;
+}
+static PyObject *prop_subscript_array_int(BPy_PropertyRNA * self, int keynum)
+{
+ int len= RNA_property_array_length(self->prop);
+
+ if(keynum < 0) keynum += len;
+
+ if(keynum >= 0 && keynum < len)
+ return pyrna_prop_to_py_index(&self->ptr, self->prop, keynum);
+
+ PyErr_SetString(PyExc_IndexError, "out of range");
+ return NULL;
+}
+
+static PyObject *prop_subscript_collection_str(BPy_PropertyRNA * self, char *keyname)
+{
+ PointerRNA newptr;
+ if(RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr))
+ return pyrna_struct_CreatePyObject(&newptr);
+
+ PyErr_SetString(PyExc_KeyError, "key not found");
+ return NULL;
+}
+/* static PyObject *prop_subscript_array_str(BPy_PropertyRNA * self, char *keyname) */
+
+
+
+
+#if PY_VERSION_HEX >= 0x03000000
+static PyObject *prop_subscript_collection_slice(BPy_PropertyRNA * self, int start, int stop)
+{
+ PointerRNA newptr;
+ PyObject *list = PyList_New(stop - start);
+ int count;
+
+ start = MIN2(start,stop); /* values are clamped from */
+
+ for(count = start; count < stop; count++) {
+ if(RNA_property_collection_lookup_int(&self->ptr, self->prop, count - start, &newptr)) {
+ PyList_SetItem(list, count - start, pyrna_struct_CreatePyObject(&newptr));
+ }
+ else {
+ Py_DECREF(list);
+
+ PyErr_SetString(PyExc_RuntimeError, "error getting an rna struct from a collection");
+ return NULL;
+ }
+ }
+
+ return list;
+}
+static PyObject *prop_subscript_array_slice(BPy_PropertyRNA * self, int start, int stop)
+{
+ PyObject *list = PyList_New(stop - start);
+ int count;
+
+ start = MIN2(start,stop); /* values are clamped from PySlice_GetIndicesEx */
+
+ for(count = start; count < stop; count++)
+ PyList_SetItem(list, count - start, pyrna_prop_to_py_index(&self->ptr, self->prop, count));
+
+ return list;
+}
+#endif
+
+static PyObject *prop_subscript_collection(BPy_PropertyRNA * self, PyObject *key)
+{
if (PyUnicode_Check(key)) {
- keyname = _PyUnicode_AsString(key);
- } else if (PyLong_Check(key)) {
- keynum = PyLong_AsSsize_t(key);
- } else {
+ return prop_subscript_collection_str(self, _PyUnicode_AsString(key));
+ }
+ else if (PyLong_Check(key)) {
+ return prop_subscript_collection_int(self, PyLong_AsSsize_t(key));
+ }
+#if PY_VERSION_HEX >= 0x03000000
+ else if (PySlice_Check(key)) {
+ int len= RNA_property_collection_length(&self->ptr, self->prop);
+ Py_ssize_t start, stop, step, slicelength;
+
+ if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0)
+ return NULL;
+
+ if (slicelength <= 0) {
+ return PyList_New(0);
+ }
+ else if (step == 1) {
+ return prop_subscript_collection_slice(self, start, stop);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna");
+ return NULL;
+ }
+ }
+#endif
+ else {
PyErr_SetString(PyExc_AttributeError, "invalid key, key must be a string or an int");
return NULL;
}
-
- if (RNA_property_type(self->prop) == PROP_COLLECTION) {
- int ok;
- if (keyname) ok = RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr);
- else ok = RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum, &newptr);
-
- if (ok) {
- ret = pyrna_struct_CreatePyObject(&newptr);
- } else {
- PyErr_SetString(PyExc_AttributeError, "out of range");
- ret = NULL;
+}
+
+static PyObject *prop_subscript_array(BPy_PropertyRNA * self, PyObject *key)
+{
+ /*if (PyUnicode_Check(key)) {
+ return prop_subscript_array_str(self, _PyUnicode_AsString(key));
+ } else*/
+ if (PyLong_Check(key)) {
+ return prop_subscript_array_int(self, PyLong_AsSsize_t(key));
+ }
+#if PY_VERSION_HEX >= 0x03000000
+ else if (PySlice_Check(key)) {
+ int len= RNA_property_array_length(self->prop);
+ Py_ssize_t start, stop, step, slicelength;
+
+ if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0)
+ return NULL;
+
+ if (slicelength <= 0) {
+ return PyList_New(0);
}
-
- } else if (keyname) {
- PyErr_SetString(PyExc_AttributeError, "string keys are only supported for collections");
- ret = NULL;
- } else {
- int len = RNA_property_array_length(self->prop);
-
- if (len==0) { /* not an array*/
- PyErr_Format(PyExc_AttributeError, "not an array or collection %d", keynum);
- ret = NULL;
+ else if (step == 1) {
+ return prop_subscript_array_slice(self, start, stop);
}
-
- if (keynum >= len){
- PyErr_SetString(PyExc_AttributeError, "index out of range");
- ret = NULL;
- } else { /* not an array*/
- ret = pyrna_prop_to_py_index(&self->ptr, self->prop, keynum);
+ else {
+ PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna");
+ return NULL;
}
}
-
- return ret;
+#endif
+ else {
+ PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int");
+ return NULL;
+ }
}
+static PyObject *pyrna_prop_subscript( BPy_PropertyRNA * self, PyObject *key )
+{
+ if (RNA_property_type(self->prop) == PROP_COLLECTION) {
+ return prop_subscript_collection(self, key);
+ } else if (RNA_property_array_length(self->prop)) { /* arrays are currently fixed length, zero length means its not an array */
+ return prop_subscript_array(self, key);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "rna type is not an array or a collection");
+ return NULL;
+ }
+
+}
-static int pyrna_prop_assign_subscript( BPy_PropertyRNA * self, PyObject *key, PyObject *value )
+#if PY_VERSION_HEX >= 0x03000000
+static int prop_subscript_ass_array_slice(BPy_PropertyRNA * self, int begin, int end, PyObject *value)
{
- int ret = 0;
- int keynum = 0;
- char *keyname = NULL;
+ int count;
+
+ /* values are clamped from */
+ begin = MIN2(begin,end);
+
+ for(count = begin; count < end; count++) {
+ if(pyrna_py_to_prop_index(&self->ptr, self->prop, count - begin, value) == -1) {
+ /* TODO - this is wrong since some values have been assigned... will need to fix that */
+ return -1; /* pyrna_struct_CreatePyObject should set the error */
+ }
+ }
+
+ return 0;
+}
+#endif
+
+static int prop_subscript_ass_array_int(BPy_PropertyRNA * self, int keynum, PyObject *value)
+{
+
+ int len= RNA_property_array_length(self->prop);
+
+ if(keynum < 0) keynum += len;
+
+ if(keynum >= 0 && keynum < len)
+ return pyrna_py_to_prop_index(&self->ptr, self->prop, keynum, value);
+
+ PyErr_SetString(PyExc_IndexError, "out of range");
+ return -1;
+}
+
+static int pyrna_prop_ass_subscript( BPy_PropertyRNA * self, PyObject *key, PyObject *value )
+{
+ /* char *keyname = NULL; */ /* not supported yet */
if (!RNA_property_editable(&self->ptr, self->prop)) {
PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%s\" from \"%s\" is read-only", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) );
return -1;
}
- if (PyUnicode_Check(key)) {
- keyname = _PyUnicode_AsString(key);
- } else if (PyLong_Check(key)) {
- keynum = PyLong_AsSsize_t(key);
- } else {
- PyErr_SetString(PyExc_AttributeError, "PropertyRNA - invalid key, key must be a string or an int");
+ /* maybe one day we can support this... */
+ if (RNA_property_type(self->prop) == PROP_COLLECTION) {
+ PyErr_Format( PyExc_AttributeError, "PropertyRNA - attribute \"%s\" from \"%s\" is a collection, assignment not supported", RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type) );
return -1;
}
-
- if (RNA_property_type(self->prop) == PROP_COLLECTION) {
- PyErr_SetString(PyExc_AttributeError, "PropertyRNA - assignment is not supported for collections (yet)");
- ret = -1;
- } else if (keyname) {
- PyErr_SetString(PyExc_AttributeError, "PropertyRNA - string keys are only supported for collections");
- ret = -1;
- } else {
- int len = RNA_property_array_length(self->prop);
-
- if (len==0) { /* not an array*/
- PyErr_Format(PyExc_AttributeError, "PropertyRNA - not an array or collection %d", keynum);
- ret = -1;
+
+ if (PyLong_Check(key)) {
+ return prop_subscript_ass_array_int(self, PyLong_AsSsize_t(key), value);
+ }
+#if PY_VERSION_HEX >= 0x03000000
+ else if (PySlice_Check(key)) {
+ int len= RNA_property_array_length(self->prop);
+ Py_ssize_t start, stop, step, slicelength;
+
+ if (PySlice_GetIndicesEx((PySliceObject*)key, len, &start, &stop, &step, &slicelength) < 0)
+ return -1;
+
+ if (slicelength <= 0) {
+ return 0;
}
-
- if (keynum >= len){
- PyErr_SetString(PyExc_AttributeError, "PropertyRNA - index out of range");
- ret = -1;
- } else {
- ret = pyrna_py_to_prop_index(&self->ptr, self->prop, keynum, value);
+ else if (step == 1) {
+ return prop_subscript_ass_array_slice(self, start, stop, value);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna");
+ return -1;
}
}
-
- return ret;
+#endif
+ else {
+ PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int");
+ return -1;
+ }
}
-
static PyMappingMethods pyrna_prop_as_mapping = {
( lenfunc ) pyrna_prop_len, /* mp_length */
( binaryfunc ) pyrna_prop_subscript, /* mp_subscript */
- ( objobjargproc ) pyrna_prop_assign_subscript, /* mp_ass_subscript */
+ ( objobjargproc ) pyrna_prop_ass_subscript, /* mp_ass_subscript */
};
static int pyrna_prop_contains(BPy_PropertyRNA * self, PyObject *value)
@@ -1252,8 +1391,10 @@ static int foreach_parse_args(
/*values to assign */
char **attr, PyObject **seq, int *tot, int *size, RawPropertyType *raw_type, int *attr_tot, int *attr_signed)
{
+#if 0
int array_tot;
int target_tot;
+#endif
*size= *raw_type= *attr_tot= *attr_signed= 0;
@@ -1340,7 +1481,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set)
Py_buffer buf;
PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT);
- /* check if the buffer matches, TODO - signed/unsigned types */
+ /* check if the buffer matches */
buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format);