diff options
author | Campbell Barton <ideasman42@gmail.com> | 2008-12-25 13:48:36 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2008-12-25 13:48:36 +0300 |
commit | 46d505194b1a6f18d33eae15f46d9cea73f5d8f6 (patch) | |
tree | 2c39862e8603b571f89b53824740fdd6bea723d5 /source/blender/python | |
parent | 0d7027ecab5d4c667a42c1a5d16d88a9e74e8979 (diff) |
* PyOperators now parse args using the PyRNA api (wraps ID props internally),
this means it can reuse the function for converting python to RNA types - giving more useful errors.
* Incorrect enum args lists valid values in their exception message (used for PyRNA and PyOperators).
* remove bpy_idprop.c and bpy_idprop.h
PyOperators are not usable since they run outside the UI loop atm.
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/intern/bpy_idprop.c | 183 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_idprop.h | 33 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator.c | 64 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 50 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.h | 3 |
5 files changed, 90 insertions, 243 deletions
diff --git a/source/blender/python/intern/bpy_idprop.c b/source/blender/python/intern/bpy_idprop.c deleted file mode 100644 index 4b4bfa6c94a..00000000000 --- a/source/blender/python/intern/bpy_idprop.c +++ /dev/null @@ -1,183 +0,0 @@ -/** - * $Id: IDProp.c - * - * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): Joseph Eagar, Campbell Barton - * - * ***** END GPL LICENSE BLOCK ***** - */ - - #include "DNA_ID.h" - -#include "BKE_idprop.h" - -#include "bpy_idprop.h" -#include "bpy_compat.h" - -#include "MEM_guardedalloc.h" - -#define BSTR_EQ(a, b) (*(a) == *(b) && !strcmp(a, b)) - -static PyObject *EXPP_ReturnPyObjError( PyObject * type, char *error_msg ) -{ /* same as above, just to change its name smoothly */ - PyErr_SetString( type, error_msg ); - return NULL; -} - -static int EXPP_ReturnIntError( PyObject * type, char *error_msg ) -{ - PyErr_SetString( type, error_msg ); - return -1; -} - - -/*returns NULL on success, error string on failure*/ -static char *BPy_IDProperty_Map_ValidateAndCreate(char *name, IDProperty *group, PyObject *ob) -{ - IDProperty *prop = NULL; - IDPropertyTemplate val = {0}; - - if (PyFloat_Check(ob)) { - val.d = PyFloat_AsDouble(ob); - prop = IDP_New(IDP_DOUBLE, val, name); - } else if (PyLong_Check(ob)) { - val.i = (int) PyLong_AsLong(ob); - prop = IDP_New(IDP_INT, val, name); - } else if (PyUnicode_Check(ob)) { - val.str = _PyUnicode_AsString(ob); - prop = IDP_New(IDP_STRING, val, name); - } else if (PySequence_Check(ob)) { - PyObject *item; - int i; - - /*validate sequence and derive type. - we assume IDP_INT unless we hit a float - number; then we assume it's */ - val.array.type = IDP_INT; - val.array.len = PySequence_Length(ob); - for (i=0; i<val.array.len; i++) { - item = PySequence_GetItem(ob, i); - if (PyFloat_Check(item)) val.array.type = IDP_DOUBLE; - else if (!PyLong_Check(item)) return "only floats and ints are allowed in ID property arrays"; - Py_XDECREF(item); - } - - prop = IDP_New(IDP_ARRAY, val, name); - for (i=0; i<val.array.len; i++) { - item = PySequence_GetItem(ob, i); - if (val.array.type == IDP_INT) { - item = PyNumber_Int(item); - ((int*)prop->data.pointer)[i] = (int)PyLong_AsLong(item); - } else { - item = PyNumber_Float(item); - ((double*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item); - } - Py_XDECREF(item); - } - } else if (PyMapping_Check(ob)) { - PyObject *keys, *vals, *key, *pval; - int i, len; - /*yay! we get into recursive stuff now!*/ - keys = PyMapping_Keys(ob); - vals = PyMapping_Values(ob); - - /*we allocate the group first; if we hit any invalid data, - we can delete it easily enough.*/ - prop = IDP_New(IDP_GROUP, val, name); - len = PyMapping_Length(ob); - for (i=0; i<len; i++) { - key = PySequence_GetItem(keys, i); - pval = PySequence_GetItem(vals, i); - if (!PyUnicode_Check(key)) { - IDP_FreeProperty(prop); - MEM_freeN(prop); - Py_XDECREF(keys); - Py_XDECREF(vals); - Py_XDECREF(key); - Py_XDECREF(pval); - return "invalid element in subgroup dict template!"; - } - if (BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, pval)) { - IDP_FreeProperty(prop); - MEM_freeN(prop); - Py_XDECREF(keys); - Py_XDECREF(vals); - Py_XDECREF(key); - Py_XDECREF(pval); - return "invalid element in subgroup dict template!"; - } - Py_XDECREF(key); - Py_XDECREF(pval); - } - Py_XDECREF(keys); - Py_XDECREF(vals); - } else return "invalid property value"; - - IDP_ReplaceInGroup(group, prop); - return NULL; -} - - -static int BPy_IDGroup_Map_SetItem(IDProperty *prop, PyObject *key, PyObject *val) -{ - char *err; - - if (prop->type != IDP_GROUP) - return EXPP_ReturnIntError( PyExc_TypeError, - "unsubscriptable object"); - - if (!PyUnicode_Check(key)) - return EXPP_ReturnIntError( PyExc_TypeError, - "only strings are allowed as subgroup keys" ); - - if (val == NULL) { - IDProperty *pkey = IDP_GetPropertyFromGroup(prop, _PyUnicode_AsString(key)); - if (pkey) { - IDP_RemFromGroup(prop, pkey); - IDP_FreeProperty(pkey); - MEM_freeN(pkey); - return 0; - } else return EXPP_ReturnIntError( PyExc_RuntimeError, "property not found in group" ); - } - - err = BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, val); - if (err) return EXPP_ReturnIntError( PyExc_RuntimeError, err ); - - return 0; -} - - -PyObject *BPy_IDGroup_Update(IDProperty *prop, PyObject *value) -{ - PyObject *pkey, *pval; - Py_ssize_t i=0; - - if (!PyDict_Check(value)) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected an object derived from dict."); - - while (PyDict_Next(value, &i, &pkey, &pval)) { - BPy_IDGroup_Map_SetItem(prop, pkey, pval); - if (PyErr_Occurred()) return NULL; - } - - Py_RETURN_NONE; -}
\ No newline at end of file diff --git a/source/blender/python/intern/bpy_idprop.h b/source/blender/python/intern/bpy_idprop.h deleted file mode 100644 index c68265aca83..00000000000 --- a/source/blender/python/intern/bpy_idprop.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * $Id: IDProp.h - * - * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): Joseph Eagar - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include <Python.h> - -struct ID; -struct IDProperty; - -PyObject *BPy_IDGroup_Update(IDProperty *prop, PyObject *value);
\ No newline at end of file diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 0da0782c2d1..d6bae190dd2 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -24,8 +24,8 @@ */ #include "bpy_operator.h" +#include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */ #include "bpy_compat.h" -#include "bpy_idprop.h" //#include "blendef.h" #include "BLI_dynstr.h" @@ -90,26 +90,74 @@ static PyObject *pyop_base_getattro( BPy_OperatorBase * self, PyObject *pyname ) static PyObject * pyop_func_call(BPy_OperatorFunc * self, PyObject *args, PyObject *kw) { IDProperty *properties = NULL; + wmOperatorType *ot; + + int error_val = 0; + const char *arg_name= NULL; + PyObject *item; + + PointerRNA ptr; + PropertyRNA *prop, *iterprop; + CollectionPropertyIterator iter; + + + if (ot == NULL) { + PyErr_SetString( PyExc_SystemError, "Operator could not be found"); + return NULL; + } if (PyTuple_Size(args)) { PyErr_SetString( PyExc_AttributeError, "All operator args must be keywords"); return NULL; } - if (kw && PyDict_Size(kw) > 0) { - IDPropertyTemplate val; - val.i = 0; /* silence MSVC warning about uninitialized var when debugging */ + ot= WM_operatortype_find(self->name); + RNA_pointer_create(NULL, NULL, ot->srna, &properties, &ptr); + + + iterprop= RNA_struct_iterator_property(&ptr); + RNA_property_collection_begin(&ptr, iterprop, &iter); + + + for(; iter.valid; RNA_property_collection_next(&iter)) { + prop= iter.ptr.data; - properties= IDP_New(IDP_GROUP, val, "property"); - BPy_IDGroup_Update(properties, kw); + arg_name= RNA_property_identifier(&iter.ptr, prop); - if (PyErr_Occurred()) { + if (strcmp(arg_name, "rna_type")==0) continue; + + if (kw==NULL) { + PyErr_Format( PyExc_AttributeError, "no args, expected \"%s\"", arg_name ? arg_name : "<UNKNOWN>"); + error_val= 1; + break; + } + + item= PyDict_GetItemString(kw, arg_name); + + if (item == NULL) { + PyErr_Format( PyExc_AttributeError, "argument \"%s\" missing", arg_name ? arg_name : "<UNKNOWN>"); + error_val = 1; /* pyrna_py_to_prop sets the error */ + break; + } + + if (pyrna_py_to_prop(&ptr, prop, item)) { + error_val= 1; + break; + } + } + + RNA_property_collection_end(&iter); + + if (error_val) { + if (properties) { IDP_FreeProperty(properties); MEM_freeN(properties); - return NULL; } + + return NULL; } + WM_operator_name_call(self->C, self->name, WM_OP_DEFAULT, properties); if (properties) { diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 356cb40965f..0b33f11d74d 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -59,6 +59,27 @@ static long pyrna_struct_hash( BPy_StructRNA * self ) return (long)self->ptr.data; } +static char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) +{ + const EnumPropertyItem *item; + int totitem, i; + + DynStr *dynstr= BLI_dynstr_new(); + char *cstring; + + RNA_property_enum_items(ptr, prop, &item, &totitem); + + for (i=0; i<totitem; i++) { + if (i<totitem-1) + BLI_dynstr_appendf(dynstr, "'%s', ", item[i].identifier); + else + BLI_dynstr_appendf(dynstr, "'%s'", item[i].identifier); + } + + cstring = BLI_dynstr_get_cstring(dynstr); + BLI_dynstr_free(dynstr); + return cstring; +} static PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) { @@ -130,7 +151,7 @@ static PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) } -static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) +int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) { int type = RNA_property_type(ptr, prop); int len = RNA_property_array_length(ptr, prop); @@ -281,14 +302,18 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) char *param = _PyUnicode_AsString(value); if (param==NULL) { - PyErr_SetString(PyExc_TypeError, "expected a string type"); + char *enum_str= pyrna_enum_as_string(ptr, prop); + PyErr_Format(PyExc_TypeError, "expected a string enum type in (%s)", enum_str); + MEM_freeN(enum_str); return -1; } else { int val; if (RNA_property_enum_value(ptr, prop, param, &val)) { RNA_property_enum_set(ptr, prop, val); } else { - PyErr_Format(PyExc_AttributeError, "enum \"%s\" not found", param); + char *enum_str= pyrna_enum_as_string(ptr, prop); + PyErr_Format(PyExc_AttributeError, "enum \"%s\" not found in (%s)", param, enum_str); + MEM_freeN(enum_str); return -1; } } @@ -608,23 +633,10 @@ PyObject *pyrna_struct_to_docstring(BPy_StructRNA *self) } case PROP_ENUM: { - const EnumPropertyItem *item; - int totitem; - + char *enum_str= pyrna_enum_as_string(&iter.ptr, prop); BLI_dynstr_appendf(dynstr, "@ivar %s: %s%s\n", identifier, desc, readonly); - - BLI_dynstr_appendf(dynstr, "@type %s: enum in [", identifier); - - RNA_property_enum_items(&iter.ptr, prop, &item, &totitem); - - for (i=0; i<totitem; i++) { - BLI_dynstr_append(dynstr, item[i].identifier); - if (i<totitem-1) { - BLI_dynstr_append(dynstr, ", "); - } - } - - BLI_dynstr_append(dynstr, "]\n"); + BLI_dynstr_appendf(dynstr, "@type %s: enum in [%s]\n", identifier, enum_str); + MEM_freeN(enum_str); break; } case PROP_POINTER: diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 94f97a565a4..f707ebb774b 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -49,4 +49,7 @@ PyObject *BPY_rna_doc( void ); PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr ); PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop ); +/* operators also need this to set args */ +int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, PyObject *value); + #endif |