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:
authorBastien Montagne <montagne29@wanadoo.fr>2013-08-27 01:11:52 +0400
committerBastien Montagne <montagne29@wanadoo.fr>2013-08-27 01:11:52 +0400
commit1679cd7f966b5441bd02e8960ece398ee1980c7f (patch)
treec9c7334bbd62463ff3bdf501e1f82e64bb6ab9f7 /source/blender/python/intern
parent03dbae07d346dcfb5cdaeeeea3585f642cd90d31 (diff)
This commit adds optional parameters for pyfunc implementations of RNA API (i.e. callbacks, e.g. draw functions of panels, uiLists, or exec/poll/etc. of operators). Thanks to Brecht for he review!
Any parameter after the first flagged with PROP_PYFUNC_OPTIONAL will be considered as optional, hence the python code does not have to define/use it. This will ease API evolutions by avoiding to break existing code when adding non-essential new parameters. Note: this will need some update to API doc generation, patch is ready, will have it reviewed by Campbell asap.
Diffstat (limited to 'source/blender/python/intern')
-rw-r--r--source/blender/python/intern/bpy_rna.c61
1 files changed, 46 insertions, 15 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 3cd030e9b08..29f2d308367 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -6875,7 +6875,7 @@ int pyrna_deferred_register_class(StructRNA *srna, PyTypeObject *py_class)
/*-------------------- Type Registration ------------------------*/
-static int rna_function_arg_count(FunctionRNA *func)
+static int rna_function_arg_count(FunctionRNA *func, int *min_count)
{
const ListBase *lb = RNA_function_defined_parameters(func);
PropertyRNA *parm;
@@ -6883,13 +6883,23 @@ static int rna_function_arg_count(FunctionRNA *func)
int flag = RNA_function_flag(func);
int is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
int count = is_staticmethod ? 0 : 1;
+ bool done_min_count = false;
for (link = lb->first; link; link = link->next) {
parm = (PropertyRNA *)link;
- if (!(RNA_property_flag(parm) & PROP_OUTPUT))
+ if (!(RNA_property_flag(parm) & PROP_OUTPUT)) {
+ if (!done_min_count && (RNA_property_flag(parm) & PROP_PYFUNC_OPTIONAL)) {
+ /* From now on, following parameters are optional in py func */
+ if (min_count)
+ *min_count = count;
+ done_min_count = true;
+ }
count++;
+ }
}
+ if (!done_min_count && min_count)
+ *min_count = count;
return count;
}
@@ -6904,7 +6914,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
PyObject *py_class = (PyObject *)py_data;
PyObject *base_class = RNA_struct_py_type_get(srna);
PyObject *item;
- int i, flag, is_staticmethod, arg_count, func_arg_count;
+ int i, flag, is_staticmethod, arg_count, func_arg_count, func_arg_min_count = 0;
const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */
if (srna_base) {
@@ -6968,7 +6978,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
}
}
- func_arg_count = rna_function_arg_count(func);
+ func_arg_count = rna_function_arg_count(func, &func_arg_min_count);
if (func_arg_count >= 0) { /* -1 if we don't care*/
arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount;
@@ -6976,14 +6986,25 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v
/* note, the number of args we check for and the number of args we give to
* @staticmethods are different (quirk of python),
* this is why rna_function_arg_count() doesn't return the value -1*/
- if (is_staticmethod)
+ if (is_staticmethod) {
func_arg_count++;
+ func_arg_min_count++;
+ }
- if (arg_count != func_arg_count) {
- PyErr_Format(PyExc_ValueError,
- "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d",
- class_type, py_class_name, RNA_function_identifier(func),
- func_arg_count, arg_count);
+ if (arg_count < func_arg_min_count || arg_count > func_arg_count) {
+ if (func_arg_min_count != func_arg_count) {
+ PyErr_Format(PyExc_ValueError,
+ "expected %.200s, %.200s class \"%.200s\" function to have between %d and %d "
+ "args, found %d",
+ class_type, py_class_name, RNA_function_identifier(func),
+ func_arg_count, func_arg_min_count, arg_count);
+ }
+ else {
+ PyErr_Format(PyExc_ValueError,
+ "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d",
+ class_type, py_class_name, RNA_function_identifier(func),
+ func_arg_count, arg_count);
+ }
return -1;
}
}
@@ -7063,7 +7084,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
PropertyRNA *parm;
ParameterIterator iter;
PointerRNA funcptr;
- int err = 0, i, ret_len = 0;
+ int err = 0, i, ret_len = 0, arg_count;
int flag = RNA_function_flag(func);
const char is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE);
const char is_classmethod = (flag & FUNC_NO_SELF) && (flag & FUNC_USE_SELF_TYPE);
@@ -7198,7 +7219,15 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
if (item) {
RNA_pointer_create(NULL, &RNA_Function, func, &funcptr);
- args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */
+ if (is_staticmethod) {
+ arg_count = ((PyCodeObject *)PyFunction_GET_CODE(((PyMethodObject *)item)->im_func))->co_argcount - 1;
+ }
+ else {
+ arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount;
+ }
+// args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */
+ args = PyTuple_New(arg_count); /* first arg is included in 'item' */
+
if (is_staticmethod) {
i = 0;
@@ -7230,9 +7259,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
continue;
}
- parmitem = pyrna_param_to_py(&funcptr, parm, iter.data);
- PyTuple_SET_ITEM(args, i, parmitem);
- i++;
+ if (i < arg_count) {
+ parmitem = pyrna_param_to_py(&funcptr, parm, iter.data);
+ PyTuple_SET_ITEM(args, i, parmitem);
+ i++;
+ }
}
#ifdef USE_PEDANTIC_WRITE