diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-06-05 16:48:58 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-06-05 16:48:58 +0400 |
commit | 52d8e64b857530c85efb6e1c38b4b4fd40d9c345 (patch) | |
tree | 41083ff76cc35ffd34cbd13fce5c163f754033f2 /source | |
parent | 13376a903b6167f26c04e14bad344374469fef25 (diff) |
PyRNA
- Support for python to convert a PyObject into a collection (uses a list of dicts - quite verbose :/)
- Operators can now take collection args when called from python.
- Support for printing operators that use collections (macro recording).
- Added RNA_pointer_as_string which prints all pointer prop values as a python dict.
Example that can run in the in test.py (F7 key)
bpy.ops.VIEW3D_OT_select_lasso(path=[{"loc":(0, 0), "time":0}, {"loc":(1000, 0), "time":0}, {"loc":(1000, 1000), "time":0}], type='SELECT')
for some reason lasso locations always print as 0,0. Need to look into why this is.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/makesrna/RNA_access.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_access.c | 63 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator.c | 69 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator.h | 3 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_operator_wrap.c | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 96 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.h | 1 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_ui.c | 4 |
8 files changed, 162 insertions, 77 deletions
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 70490259832..4df5aa67104 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -536,6 +536,7 @@ int RNA_property_is_set(PointerRNA *ptr, const char *name); /* python compatible string representation of this property, (must be freed!) */ char *RNA_property_as_string(PointerRNA *ptr, PropertyRNA *prop); +char *RNA_pointer_as_string(PointerRNA *ptr); /* Function */ diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index cf52c5fb1ec..91b46e8e3d7 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -2185,6 +2185,47 @@ int RNA_property_is_set(PointerRNA *ptr, const char *name) /* string representation of a property, python * compatible but can be used for display too*/ +char *RNA_pointer_as_string(PointerRNA *ptr) +{ + DynStr *dynstr= BLI_dynstr_new(); + char *cstring; + + PropertyRNA *prop, *iterprop; + CollectionPropertyIterator iter; + const char *propname; + int first_time = 1; + + BLI_dynstr_append(dynstr, "{"); + + iterprop= RNA_struct_iterator_property(ptr->type); + RNA_property_collection_begin(ptr, iterprop, &iter); + + for(; iter.valid; RNA_property_collection_next(&iter)) { + prop= iter.ptr.data; + propname = RNA_property_identifier(prop); + + if(strcmp(propname, "rna_type")==0) + continue; + + if(first_time==0) + BLI_dynstr_append(dynstr, ", "); + first_time= 0; + + cstring = RNA_property_as_string(&iter.ptr, prop); + BLI_dynstr_appendf(dynstr, "\"%s\":%s", propname, cstring); + MEM_freeN(cstring); + first_time= 0; + } + + RNA_property_collection_end(&iter); + BLI_dynstr_append(dynstr, "}"); + + + cstring = BLI_dynstr_get_cstring(dynstr); + BLI_dynstr_free(dynstr); + return cstring; +} + char *RNA_property_as_string(PointerRNA *ptr, PropertyRNA *prop) { int type = RNA_property_type(prop); @@ -2262,8 +2303,28 @@ char *RNA_property_as_string(PointerRNA *ptr, PropertyRNA *prop) break; } case PROP_COLLECTION: - BLI_dynstr_append(dynstr, "'<COLLECTION>'"); /* TODO */ + { + int first_time = 1; + CollectionPropertyIterator collect_iter; + BLI_dynstr_append(dynstr, "["); + + for(RNA_property_collection_begin(ptr, prop, &collect_iter); collect_iter.valid; RNA_property_collection_next(&collect_iter)) { + PointerRNA itemptr= collect_iter.ptr; + + if(first_time==0) + BLI_dynstr_append(dynstr, ", "); + first_time= 0; + + /* now get every prop of the collection */ + cstring= RNA_pointer_as_string(&itemptr); + BLI_dynstr_append(dynstr, cstring); + MEM_freeN(cstring); + } + + RNA_property_collection_end(&collect_iter); + BLI_dynstr_append(dynstr, "]"); break; + } default: BLI_dynstr_append(dynstr, "'<UNKNOWN TYPE>'"); /* TODO */ break; diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index b03540fb765..004cf2fb7c7 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -41,73 +41,6 @@ extern ListBase global_ops; /* evil, temp use */ - - -/* This function is only used by operators right now - * Its used for taking keyword args and filling in property values */ -int PYOP_props_from_dict(PointerRNA *ptr, PyObject *kw) -{ - int error_val = 0; - int totkw; - const char *arg_name= NULL; - PyObject *item; - - PropertyRNA *prop, *iterprop; - CollectionPropertyIterator iter; - - iterprop= RNA_struct_iterator_property(ptr->type); - RNA_property_collection_begin(ptr, iterprop, &iter); - - totkw = kw ? PyDict_Size(kw):0; - - for(; iter.valid; RNA_property_collection_next(&iter)) { - prop= iter.ptr.data; - - arg_name= RNA_property_identifier(prop); - - 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, NULL, item)) { - error_val= -1; - break; - } - - totkw--; - } - - RNA_property_collection_end(&iter); - - if (error_val==0 && totkw > 0) { /* some keywords were given that were not used :/ */ - PyObject *key, *value; - Py_ssize_t pos = 0; - - while (PyDict_Next(kw, &pos, &key, &value)) { - arg_name= _PyUnicode_AsString(key); - if (RNA_struct_find_property(ptr, arg_name) == NULL) break; - arg_name= NULL; - } - - PyErr_Format( PyExc_AttributeError, "argument \"%s\" unrecognized", arg_name ? arg_name : "<UNKNOWN>"); - error_val = -1; - } - - return error_val; -} - static PyObject *pyop_base_dir(PyObject *self); static PyObject *pyop_base_rna(PyObject *self, PyObject *pyname); static struct PyMethodDef pyop_base_methods[] = { @@ -148,7 +81,7 @@ static PyObject *pyop_base_call( PyObject * self, PyObject * args, PyObject * k WM_operator_properties_create(&ptr, opname); - error_val= PYOP_props_from_dict(&ptr, kw); + error_val= pyrna_pydict_to_props(&ptr, kw, "Converting py args to operator properties: "); if (error_val==0) { ReportList reports; diff --git a/source/blender/python/intern/bpy_operator.h b/source/blender/python/intern/bpy_operator.h index c4741f936bf..46ea144fd4d 100644 --- a/source/blender/python/intern/bpy_operator.h +++ b/source/blender/python/intern/bpy_operator.h @@ -42,7 +42,4 @@ typedef struct { PyObject *BPY_operator_module(void); -/* fill in properties from a python dict */ -int PYOP_props_from_dict(PointerRNA *ptr, PyObject *kw); - #endif diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 43d62b3005f..bf92db832af 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -272,7 +272,7 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve * thrown away anyway * * If we ever want to do this and use the props again, - * it can be done with - PYOP_props_from_dict(op->ptr, kw) + * it can be done with - pyrna_pydict_to_props(op->ptr, kw, "") */ Py_DECREF(ret); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index c1778faa1cd..d9a0d9408c7 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -204,6 +204,71 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) return ret; } +/* This function is only used by operators right now + * Its used for taking keyword args and filling in property values */ +int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefix) +{ + int error_val = 0; + int totkw; + const char *arg_name= NULL; + PyObject *item; + + PropertyRNA *prop, *iterprop; + CollectionPropertyIterator iter; + + iterprop= RNA_struct_iterator_property(ptr->type); + RNA_property_collection_begin(ptr, iterprop, &iter); + + totkw = kw ? PyDict_Size(kw):0; + + for(; iter.valid; RNA_property_collection_next(&iter)) { + prop= iter.ptr.data; + + arg_name= RNA_property_identifier(prop); + + if (strcmp(arg_name, "rna_type")==0) continue; + + if (kw==NULL) { + PyErr_Format( PyExc_AttributeError, "%s: no keywords, expected \"%s\"", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); + error_val= -1; + break; + } + + item= PyDict_GetItemString(kw, arg_name); + + if (item == NULL) { + PyErr_Format( PyExc_AttributeError, "%s: keyword \"%s\" missing", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); + error_val = -1; /* pyrna_py_to_prop sets the error */ + break; + } + + if (pyrna_py_to_prop(ptr, prop, NULL, item)) { + error_val= -1; + break; + } + + totkw--; + } + + RNA_property_collection_end(&iter); + + if (error_val==0 && totkw > 0) { /* some keywords were given that were not used :/ */ + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(kw, &pos, &key, &value)) { + arg_name= _PyUnicode_AsString(key); + if (RNA_struct_find_property(ptr, arg_name) == NULL) break; + arg_name= NULL; + } + + PyErr_Format( PyExc_AttributeError, "%s: keyword \"%s\" unrecognized", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); + error_val = -1; + } + + return error_val; +} + static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw); PyObject *pyrna_func_to_py(PointerRNA *ptr, FunctionRNA *func) @@ -447,9 +512,36 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v break; } case PROP_COLLECTION: - PyErr_SetString(PyExc_AttributeError, "cant convert collections yet"); - return -1; + { + int seq_len, i; + PyObject *item; + PointerRNA itemptr; + + /* convert a sequence of dict's into a collection */ + if(!PySequence_Check(value)) { + PyErr_SetString(PyExc_TypeError, "expected a sequence of dicts for an RNA collection"); + return -1; + } + + seq_len = PySequence_Length(value); + for(i=0; i<seq_len; i++) { + item= PySequence_GetItem(value, i); + if(item==NULL || PyDict_Check(item)==0) { + PyErr_SetString(PyExc_TypeError, "expected a sequence of dicts for an RNA collection"); + Py_XDECREF(item); + return -1; + } + + RNA_property_collection_add(ptr, prop, &itemptr); + if(pyrna_pydict_to_props(&itemptr, item, "Converting a python list to an RNA collection")==-1) { + Py_DECREF(item); + return -1; + } + Py_DECREF(item); + } + break; + } default: PyErr_SetString(PyExc_AttributeError, "unknown property type (pyrna_py_to_prop)"); return -1; diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index a97d450fb2f..a2a3015912b 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -69,6 +69,7 @@ PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop ); /* operators also need this to set args */ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value); +int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefix); PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop); /* functions for setting up new props - experemental */ diff --git a/source/blender/python/intern/bpy_ui.c b/source/blender/python/intern/bpy_ui.c index bbfb04719d8..c15315ca350 100644 --- a/source/blender/python/intern/bpy_ui.c +++ b/source/blender/python/intern/bpy_ui.c @@ -78,7 +78,7 @@ static PyObject *Method_defButO( PyObject * self, PyObject * args ) /* Optional python doctionary used to set python properties, just like how keyword args are used */ if (py_keywords && PyDict_Size(py_keywords)) { - if (PYOP_props_from_dict(uiButGetOperatorPtrRNA(but), py_keywords) == -1) + if (pyrna_pydict_to_props(uiButGetOperatorPtrRNA(but), py_keywords, "") == -1) return NULL; } @@ -296,7 +296,7 @@ static PyObject *Method_registerKey( PyObject * self, PyObject * args ) /* Optional python doctionary used to set python properties, just like how keyword args are used */ if (py_keywords && PyDict_Size(py_keywords)) { - if (PYOP_props_from_dict(km->ptr, py_keywords) == -1) + if (pyrna_pydict_to_props(km->ptr, py_keywords, "Registering keybinding") == -1) return NULL; } |