misc python api improvements
authorCampbell Barton <ideasman42@gmail.com>
Thu, 13 Jan 2011 21:44:18 +0000 (21:44 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 13 Jan 2011 21:44:18 +0000 (21:44 +0000)
- rna array parsing was using PySequence_Size() in a loop, this can  be slow to run so only call once.
- assigning a single value to a multi-dimensional array was missing type check.
- improve exception messages for rna array type errors.
- simplify vector slice assignment by using mathutils_array_parse(...)

source/blender/python/generic/mathutils_vector.c
source/blender/python/intern/bpy_rna_array.c

index cc9f9d32819499198edcff72dfd06d30de774c59..b5ac197abee09061b54e9c48356c683750d90f92 100644 (file)
@@ -832,48 +832,28 @@ static PyObject *Vector_slice(VectorObject *self, int begin, int end)
 static int Vector_ass_slice(VectorObject *self, int begin, int end,
                                 PyObject * seq)
 {
-       int i, y, size = 0;
-       float vec[4], scalar;
-       PyObject *v;
+       int y, size = 0;
+       float vec[MAX_DIMENSIONS];
 
        if(!BaseMath_ReadCallback(self))
                return -1;
-       
+
        CLAMP(begin, 0, self->size);
-       if (end<0) end= self->size+end+1;
        CLAMP(end, 0, self->size);
        begin = MIN2(begin,end);
 
-       size = PySequence_Size(seq);
-       if(size != (end - begin)){
-               PyErr_SetString(PyExc_TypeError, "vector[begin:end] = []: size mismatch in slice assignment");
+       size = (end - begin);
+       if(mathutils_array_parse(vec, size, size, seq, "vector[begin:end] = [...]:") == -1)
                return -1;
-       }
 
-       for (i = 0; i < size; i++) {
-               v = PySequence_GetItem(seq, i);
-               if (v == NULL) { /* Failed to read sequence */
-                       PyErr_SetString(PyExc_RuntimeError, "vector[begin:end] = []: unable to read sequence");
-                       return -1;
-               }
-               
-               if((scalar=PyFloat_AsDouble(v)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
-                       Py_DECREF(v);
-                       PyErr_SetString(PyExc_TypeError, "vector[begin:end] = []: sequence argument not a number");
-                       return -1;
-               }
-
-               vec[i] = scalar;
-               Py_DECREF(v);
-       }
        /*parsed well - now set in vector*/
        for(y = 0; y < size; y++){
                self->vec[begin + y] = vec[y];
        }
-       
+
        if(!BaseMath_WriteCallback(self))
                return -1;
-       
+
        return 0;
 }
 /*------------------------NUMERIC PROTOCOLS----------------------
index f3b3615793b343dfb1d3134a1bb9a519e3c3fa58..32efa3871969b3194310f1b89f81646e7a436846 100644 (file)
@@ -56,15 +56,15 @@ static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[]
        /* not the last dimension */
        if (dim + 1 < totdim) {
                /* check that a sequence contains dimsize[dim] items */
-
-               for (i= 0; i < PySequence_Size(seq); i++) {
+               const int seq_size= PySequence_Size(seq);
+               for (i= 0; i < seq_size; i++) {
                        PyObject *item;
                        int ok= 1;
                        item= PySequence_GetItem(seq, i);
 
                        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", error_prefix, 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);
                                ok= 0;
                        }
                        /* arr[3][4][5]
@@ -89,14 +89,15 @@ static int validate_array_type(PyObject *seq, int dim, int totdim, int dimsize[]
        }
        else {
                /* check that items are of correct type */
-               for (i= 0; i < PySequence_Size(seq); i++) {
+               const int seq_size= PySequence_Size(seq);
+               for (i= 0; i < seq_size; i++) {
                        PyObject *item= PySequence_GetItem(seq, i);
 
                        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, "sequence items should be of type %s", item_type_str);
+                               PyErr_Format(PyExc_TypeError, "expected sequence items of type %s, not %s", item_type_str, Py_TYPE(item)->tp_name);
                                return 0;
                        }
 
@@ -113,8 +114,9 @@ static int count_items(PyObject *seq)
        int totitem= 0;
 
        if (PySequence_Check(seq)) {
+               const int seq_size= PySequence_Size(seq);
                int i;
-               for (i= 0; i < PySequence_Size(seq); i++) {
+               for (i= 0; i < seq_size; i++) {
                        PyObject *item= PySequence_GetItem(seq, i);
                        totitem += count_items(item);
                        Py_DECREF(item);
@@ -183,7 +185,7 @@ 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 sequence must have %d items total", error_prefix, len);
+                       PyErr_Format(PyExc_ValueError, "%s sequence must have %d items total, not %d", error_prefix, len, tot);
                        return 0;
                }
        }
@@ -227,8 +229,9 @@ static char *copy_values(PyObject *seq, PointerRNA *ptr, PropertyRNA *prop, int
 {
        unsigned int i;
        int totdim= RNA_property_array_dimension(ptr, prop, NULL);
+       const int seq_size= PySequence_Size(seq);
 
-       for (i= 0; i < PySequence_Size(seq); i++) {
+       for (i= 0; i < seq_size; i++) {
                PyObject *item= PySequence_GetItem(seq, i);
 
                if (dim + 1 < totdim) {
@@ -310,6 +313,10 @@ static int py_to_array_index(PyObject *py, PointerRNA *ptr, PropertyRNA *prop, i
        index += arrayoffset;
 
        if(lvalue_dim == totdim) { /* single item, assign directly */
+               if(!check_item_type(py)) {
+                       PyErr_Format(PyExc_TypeError, "%s expected a %s type, not %s", error_prefix, item_type_str, Py_TYPE(py)->tp_name);
+                       return 0;
+               }
                copy_value_single(py, ptr, prop, NULL, 0, &index, convert_item, rna_set_index);
        }
        else {
@@ -342,7 +349,7 @@ static void py_to_bool(PyObject *py, char *data)
 static int py_float_check(PyObject *py)
 {
        /* accept both floats and integers */
-       return PyFloat_Check(py) || PyLong_Check(py);
+       return PyNumber_Check(py);
 }
 
 static int py_int_check(PyObject *py)