diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-07-17 06:31:28 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-07-17 06:31:28 +0400 |
commit | 70f6255433fcb1f5551199ef7a285a9ab80a3318 (patch) | |
tree | 1471a4451ee14d5b29ed37e2dc86300b01180698 | |
parent | c6c853d88a9c5ff12b7a56e4bdaca1757f160997 (diff) |
bpy rna
Calling rna functions with invalid keywords, too many keywords and too many args would fail silently
- now raise an error with invalid keywords and a list of valid ones, raise an error when too many args are given.
- calling rna functions would alloc a ParameterList each time, changed to use a stack variable (2 pointers and an int).
- store the number of parameters ParameterList
- python exception types were wrong in many cases, (using attribute error rather then type error)
- fixes to small errors in python UI scripts.
-rw-r--r-- | release/ui/buttons_physics_fluid.py | 30 | ||||
-rw-r--r-- | release/ui/buttons_physics_softbody.py | 4 | ||||
-rw-r--r-- | source/blender/editors/space_console/space_console.c | 2 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_access.h | 3 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_types.h | 15 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_access.c | 40 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_internal_types.h | 8 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_ui.c | 64 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 145 |
9 files changed, 206 insertions, 105 deletions
diff --git a/release/ui/buttons_physics_fluid.py b/release/ui/buttons_physics_fluid.py index 482dd231f14..cab5b0c632a 100644 --- a/release/ui/buttons_physics_fluid.py +++ b/release/ui/buttons_physics_fluid.py @@ -30,13 +30,19 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel): row = split.row(align=True) row.itemR(md, "render", text="") row.itemR(md, "realtime", text="") + + fluid = md.settings + else: # add modifier split.item_enumO("OBJECT_OT_modifier_add", "type", "FLUID_SIMULATION", text="Add") split.itemL() - - if md: - fluid = md.settings + + fluid = None + + + if fluid: + col = layout.column(align=True) row = col.row() @@ -177,7 +183,11 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel): def poll(self, context): md = context.fluid if md: - return (md.settings.type == 'DOMAIN') + settings = md.settings + if settings: + return (settings.type == 'DOMAIN') + + return False def draw(self, context): layout = self.layout @@ -217,7 +227,11 @@ class PHYSICS_PT_domain_boundary(PhysicButtonsPanel): def poll(self, context): md = context.fluid if md: - return (md.settings.type == 'DOMAIN') + settings = md.settings + if settings: + return (settings.type == 'DOMAIN') + + return False def draw(self, context): layout = self.layout @@ -244,7 +258,11 @@ class PHYSICS_PT_domain_particles(PhysicButtonsPanel): def poll(self, context): md = context.fluid if md: - return (md.settings.type == 'DOMAIN') + settings = md.settings + if settings: + return (settings.type == 'DOMAIN') + + return False def draw(self, context): layout = self.layout diff --git a/release/ui/buttons_physics_softbody.py b/release/ui/buttons_physics_softbody.py index 774f7f67979..35cee713a87 100644 --- a/release/ui/buttons_physics_softbody.py +++ b/release/ui/buttons_physics_softbody.py @@ -136,8 +136,8 @@ class PHYSICS_PT_softbody_edge(PhysicButtonsPanel): col.itemR(softbody, "new_aero", text="Aero") subcol = col.column() - subcol.active = softbody.new_aero - subcol.itemR(softbody, "aero", text="Factor", enabled=softbody.new_aero) + subcol.enabled = softbody.new_aero + subcol.itemR(softbody, "aero", text="Factor") col.itemL(text="Collision:") col.itemR(softbody, "edge_collision", text="Edge") diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index f5bccbce3f5..4585eef2579 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -60,7 +60,7 @@ #include "console_intern.h" // own include -static void console_update_rect(bContext *C, ARegion *ar) +static void console_update_rect(const bContext *C, ARegion *ar) { SpaceConsole *sc= CTX_wm_space_console(C); View2D *v2d= &ar->v2d; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index a04a09d4d11..9ad71f4e1d7 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -758,8 +758,9 @@ const struct ListBase *RNA_function_defined_parameters(FunctionRNA *func); /* Utility */ -ParameterList *RNA_parameter_list_create(PointerRNA *ptr, FunctionRNA *func); +ParameterList *RNA_parameter_list_create(ParameterList *parms, PointerRNA *ptr, FunctionRNA *func); void RNA_parameter_list_free(ParameterList *parms); +int RNA_parameter_list_size(ParameterList *parms); void RNA_parameter_list_begin(ParameterList *parms, ParameterIterator *iter); void RNA_parameter_list_next(ParameterIterator *iter); diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index dc2a2a1a1de..bf4fa97b6fe 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -163,10 +163,19 @@ typedef struct PropertyRNA PropertyRNA; /* Parameter List */ -typedef struct ParameterList ParameterList; +typedef struct ParameterList { + /* storage for parameters */ + void *data; + + /* store the parameter count */ + int tot; + + /* function passed at creation time */ + struct FunctionRNA *func; +} ParameterList; typedef struct ParameterIterator { - ParameterList *parms; + struct ParameterList *parms; PointerRNA funcptr; void *data; int size, offset; @@ -209,7 +218,7 @@ typedef enum StructFlag { } StructFlag; typedef int (*StructValidateFunc)(struct PointerRNA *ptr, void *data, int *have_function); -typedef int (*StructCallbackFunc)(struct PointerRNA *ptr, struct FunctionRNA *func, struct ParameterList *list); +typedef int (*StructCallbackFunc)(struct PointerRNA *ptr, struct FunctionRNA *func, ParameterList *list); typedef void (*StructFreeFunc)(void *data); typedef struct StructRNA *(*StructRegisterFunc)(const struct bContext *C, struct ReportList *reports, void *data, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 838592562b3..b55df31640f 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1404,9 +1404,10 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA #if 0 else if(cprop->add){ if(!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */ - ParameterList *params= RNA_parameter_list_create(ptr, cprop->add); - RNA_function_call(NULL, NULL, ptr, cprop->add, params); - RNA_parameter_list_free(params); + ParameterList params; + RNA_parameter_list_create(¶ms, ptr, cprop->add); + RNA_function_call(NULL, NULL, ptr, cprop->add, ¶ms); + RNA_parameter_list_free(¶ms); } } #endif @@ -1453,9 +1454,10 @@ void RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) #if 0 else if(cprop->remove){ if(!(cprop->remove->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */ - ParameterList *params= RNA_parameter_list_create(ptr, cprop->remove); - RNA_function_call(NULL, NULL, ptr, cprop->remove, params); - RNA_parameter_list_free(params); + ParameterList params; + RNA_parameter_list_create(&ptr, cprop->remove); + RNA_function_call(NULL, NULL, ptr, cprop->remove, ¶ms); + RNA_parameter_list_free(¶ms); } } #endif @@ -2787,20 +2789,17 @@ const struct ListBase *RNA_function_defined_parameters(FunctionRNA *func) /* Utility */ -ParameterList *RNA_parameter_list_create(PointerRNA *ptr, FunctionRNA *func) +ParameterList *RNA_parameter_list_create(ParameterList *parms, PointerRNA *ptr, FunctionRNA *func) { - ParameterList *parms; PropertyRNA *parm; - int tot; - - parms= MEM_callocN(sizeof(ParameterList), "ParameterList"); + int tot= 0; - parm= func->cont.properties.first; - for(tot= 0; parm; parm= parm->next) + for(parm= func->cont.properties.first; parm; parm= parm->next) tot+= rna_parameter_size(parm); parms->data= MEM_callocN(tot, "RNA_parameter_list_create"); parms->func= func; + parms->tot= tot; return parms; } @@ -2822,8 +2821,11 @@ void RNA_parameter_list_free(ParameterList *parms) parms->data= NULL; parms->func= NULL; +} - MEM_freeN(parms); +int RNA_parameter_list_size(ParameterList *parms) +{ + return parms->tot; } void RNA_parameter_list_begin(ParameterList *parms, ParameterIterator *iter) @@ -3141,7 +3143,7 @@ static int rna_function_parameter_parse(PointerRNA *ptr, PropertyRNA *prop, Prop int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *ptr, FunctionRNA *func, const char *format, va_list args) { PointerRNA funcptr; - ParameterList *parms; + ParameterList parms; ParameterIterator iter; PropertyRNA *pret, *parm; PropertyType type; @@ -3157,8 +3159,8 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt pret= RNA_function_return(func); flen= strlen(format); - parms= RNA_parameter_list_create(ptr, func); - RNA_parameter_list_begin(parms, &iter); + RNA_parameter_list_create(&parms, ptr, func); + RNA_parameter_list_begin(&parms, &iter); for(i= 0, ofs= 0; iter.valid; RNA_parameter_list_next(&iter), i++) { parm= iter.parm; @@ -3240,7 +3242,7 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt } if (err==0) - err= RNA_function_call(C, reports, ptr, func, parms); + err= RNA_function_call(C, reports, ptr, func, &parms); /* XXX throw error when more parameters than those needed are passed or leave silent? */ if (err==0 && pret && ofs<flen && format[ofs++]=='R') { @@ -3302,7 +3304,7 @@ int RNA_function_call_direct_va(bContext *C, ReportList *reports, PointerRNA *pt } RNA_parameter_list_end(&iter); - RNA_parameter_list_free(parms); + RNA_parameter_list_free(&parms); return err; } diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index b63e347e165..12bd876ce52 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -88,14 +88,6 @@ typedef struct ContainerRNA { ListBase properties; } ContainerRNA; -struct ParameterList { - /* storage for parameters */ - void *data; - - /* function passed at creation time */ - FunctionRNA *func; -}; - struct FunctionRNA { /* structs are containers of properties */ ContainerRNA cont; diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index b10ca6c5e83..217f1ea00a8 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -76,7 +76,7 @@ static ARegionType *region_type_find(ReportList *reports, int space_type, int re static int panel_poll(const bContext *C, PanelType *pt) { PointerRNA ptr; - ParameterList *list; + ParameterList list; FunctionRNA *func; void *ret; int visible; @@ -84,14 +84,14 @@ static int panel_poll(const bContext *C, PanelType *pt) RNA_pointer_create(NULL, pt->py_srna, NULL, &ptr); /* dummy */ func= RNA_struct_find_function(&ptr, "poll"); - list= RNA_parameter_list_create(&ptr, func); - RNA_parameter_set_lookup(list, "context", &C); - pt->py_call(&ptr, func, list); + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "context", &C); + pt->py_call(&ptr, func, &list); - RNA_parameter_get_lookup(list, "visible", &ret); + RNA_parameter_get_lookup(&list, "visible", &ret); visible= *(int*)ret; - RNA_parameter_list_free(list); + RNA_parameter_list_free(&list); return visible; } @@ -99,33 +99,33 @@ static int panel_poll(const bContext *C, PanelType *pt) static void panel_draw(const bContext *C, Panel *pnl) { PointerRNA ptr; - ParameterList *list; + ParameterList list; FunctionRNA *func; RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->py_srna, pnl, &ptr); func= RNA_struct_find_function(&ptr, "draw"); - list= RNA_parameter_list_create(&ptr, func); - RNA_parameter_set_lookup(list, "context", &C); - pnl->type->py_call(&ptr, func, list); + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "context", &C); + pnl->type->py_call(&ptr, func, &list); - RNA_parameter_list_free(list); + RNA_parameter_list_free(&list); } static void panel_draw_header(const bContext *C, Panel *pnl) { PointerRNA ptr; - ParameterList *list; + ParameterList list; FunctionRNA *func; RNA_pointer_create(&CTX_wm_screen(C)->id, pnl->type->py_srna, pnl, &ptr); func= RNA_struct_find_function(&ptr, "draw_header"); - list= RNA_parameter_list_create(&ptr, func); - RNA_parameter_set_lookup(list, "context", &C); - pnl->type->py_call(&ptr, func, list); + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "context", &C); + pnl->type->py_call(&ptr, func, &list); - RNA_parameter_list_free(list); + RNA_parameter_list_free(&list); } static void rna_Panel_unregister(const bContext *C, StructRNA *type) @@ -210,17 +210,17 @@ static StructRNA* rna_Panel_refine(struct PointerRNA *ptr) static void header_draw(const bContext *C, Header *hdr) { PointerRNA htr; - ParameterList *list; + ParameterList list; FunctionRNA *func; RNA_pointer_create(&CTX_wm_screen(C)->id, hdr->type->py_srna, hdr, &htr); func= RNA_struct_find_function(&htr, "draw"); - list= RNA_parameter_list_create(&htr, func); - RNA_parameter_set_lookup(list, "context", &C); - hdr->type->py_call(&htr, func, list); + RNA_parameter_list_create(&list, &htr, func); + RNA_parameter_set_lookup(&list, "context", &C); + hdr->type->py_call(&htr, func, &list); - RNA_parameter_list_free(list); + RNA_parameter_list_free(&list); } static void rna_Header_unregister(const bContext *C, StructRNA *type) @@ -301,7 +301,7 @@ static StructRNA* rna_Header_refine(struct PointerRNA *htr) static int menu_poll(const bContext *C, MenuType *pt) { PointerRNA ptr; - ParameterList *list; + ParameterList list; FunctionRNA *func; void *ret; int visible; @@ -309,14 +309,14 @@ static int menu_poll(const bContext *C, MenuType *pt) RNA_pointer_create(NULL, pt->py_srna, NULL, &ptr); /* dummy */ func= RNA_struct_find_function(&ptr, "poll"); - list= RNA_parameter_list_create(&ptr, func); - RNA_parameter_set_lookup(list, "context", &C); - pt->py_call(&ptr, func, list); + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "context", &C); + pt->py_call(&ptr, func, &list); - RNA_parameter_get_lookup(list, "visible", &ret); + RNA_parameter_get_lookup(&list, "visible", &ret); visible= *(int*)ret; - RNA_parameter_list_free(list); + RNA_parameter_list_free(&list); return visible; } @@ -324,17 +324,17 @@ static int menu_poll(const bContext *C, MenuType *pt) static void menu_draw(const bContext *C, Menu *hdr) { PointerRNA mtr; - ParameterList *list; + ParameterList list; FunctionRNA *func; RNA_pointer_create(&CTX_wm_screen(C)->id, hdr->type->py_srna, hdr, &mtr); func= RNA_struct_find_function(&mtr, "draw"); - list= RNA_parameter_list_create(&mtr, func); - RNA_parameter_set_lookup(list, "context", &C); - hdr->type->py_call(&mtr, func, list); + RNA_parameter_list_create(&list, &mtr, func); + RNA_parameter_set_lookup(&list, "context", &C); + hdr->type->py_call(&mtr, func, &list); - RNA_parameter_list_free(list); + RNA_parameter_list_free(&list); } static void rna_Menu_unregister(const bContext *C, StructRNA *type) diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 9ce9ec8e838..34269db7f94 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -367,7 +367,7 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) ret = pyrna_prop_CreatePyObject(ptr, prop); break; default: - PyErr_Format(PyExc_AttributeError, "RNA Error: unknown type \"%d\" (pyrna_prop_to_py)", type); + PyErr_Format(PyExc_TypeError, "RNA Error: unknown type \"%d\" (pyrna_prop_to_py)", type); ret = NULL; break; } @@ -392,7 +392,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi if (strcmp(arg_name, "rna_type")==0) continue; if (kw==NULL) { - PyErr_Format( PyExc_AttributeError, "%.200s: no keywords, expected \"%.200s\"", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); + PyErr_Format( PyExc_TypeError, "%.200s: no keywords, expected \"%.200s\"", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); error_val= -1; break; } @@ -400,7 +400,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi item= PyDict_GetItemString(kw, arg_name); if (item == NULL) { - PyErr_Format( PyExc_AttributeError, "%.200s: keyword \"%.200s\" missing", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); + PyErr_Format( PyExc_TypeError, "%.200s: keyword \"%.200s\" missing", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); error_val = -1; /* pyrna_py_to_prop sets the error */ break; } @@ -424,7 +424,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi arg_name= NULL; } - PyErr_Format( PyExc_AttributeError, "%.200s: keyword \"%.200s\" unrecognized", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); + PyErr_Format( PyExc_TypeError, "%.200s: keyword \"%.200s\" unrecognized", error_prefix, arg_name ? arg_name : "<UNKNOWN>"); error_val = -1; } @@ -482,7 +482,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v /* done getting the length */ if (py_len != len) { - PyErr_Format(PyExc_AttributeError, "python sequence length %d did not match the RNA array length %d.", py_len, len); + PyErr_Format(PyExc_TypeError, "python sequence length %d did not match the RNA array length %d.", py_len, len); return -1; } @@ -647,7 +647,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v else RNA_property_enum_set(ptr, prop, val); } else { char *enum_str= pyrna_enum_as_string(ptr, prop); - PyErr_Format(PyExc_AttributeError, "enum \"%.200s\" not found in (%.200s)", param, enum_str); + PyErr_Format(PyExc_TypeError, "enum \"%.200s\" not found in (%.200s)", param, enum_str); MEM_freeN(enum_str); return -1; } @@ -1807,7 +1807,7 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble( ((float*)data)[a] )); break; default: - PyErr_Format(PyExc_AttributeError, "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", type); + PyErr_Format(PyExc_TypeError, "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", type); ret = NULL; break; } @@ -1889,7 +1889,7 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) break; } default: - PyErr_Format(PyExc_AttributeError, "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", type); + PyErr_Format(PyExc_TypeError, "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", type); ret = NULL; break; } @@ -1904,25 +1904,31 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw) FunctionRNA *self_func= PyCObject_AsVoidPtr(PyTuple_GET_ITEM(self, 1)); PointerRNA funcptr; - ParameterList *parms; + ParameterList parms; ParameterIterator iter; PropertyRNA *pret, *parm; PyObject *ret, *item; - int i, tlen, flag, err= 0; - const char *tid, *fid, *pid; + int i, args_len, parms_len, flag, err= 0, kw_tot= 0; + const char *parm_id; void *retdata= NULL; /* setup */ RNA_pointer_create(NULL, &RNA_Function, self_func, &funcptr); pret= RNA_function_return(self_func); - tlen= PyTuple_GET_SIZE(args); + args_len= PyTuple_GET_SIZE(args); - parms= RNA_parameter_list_create(self_ptr, self_func); - RNA_parameter_list_begin(parms, &iter); + RNA_parameter_list_create(&parms, self_ptr, self_func); + RNA_parameter_list_begin(&parms, &iter); + parms_len = RNA_parameter_list_size(&parms); + + if(args_len + (kw ? PyDict_Size(kw):0) > parms_len) { + PyErr_Format(PyExc_TypeError, "%.200s.%.200s(): takes at most %d arguments, got %d", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), parms_len, args_len); + err= -1; + } /* parse function parameters */ - for (i= 0; iter.valid; RNA_parameter_list_next(&iter)) { + for (i= 0; iter.valid && err==0; RNA_parameter_list_next(&iter)) { parm= iter.parm; if (parm==pret) { @@ -1930,27 +1936,27 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw) continue; } - pid= RNA_property_identifier(parm); + parm_id= RNA_property_identifier(parm); flag= RNA_property_flag(parm); item= NULL; - if ((i < tlen) && (flag & PROP_REQUIRED)) { + if ((i < args_len) && (flag & PROP_REQUIRED)) { item= PyTuple_GET_ITEM(args, i); i++; } - else if (kw != NULL) - item= PyDict_GetItemString(kw, pid); /* borrow ref */ + else if (kw != NULL) { + item= PyDict_GetItemString(kw, parm_id); /* borrow ref */ + if(item) + kw_tot++; /* make sure invalid keywords are not given */ + } if (item==NULL) { if(flag & PROP_REQUIRED) { - tid= RNA_struct_identifier(self_ptr->type); - fid= RNA_function_identifier(self_func); - - PyErr_Format(PyExc_AttributeError, "%.200s.%.200s(): required parameter \"%.200s\" not specified", tid, fid, pid); + PyErr_Format(PyExc_TypeError, "%.200s.%.200s(): required parameter \"%.200s\" not specified", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), parm_id); err= -1; break; } - else + else /* PyDict_GetItemString wont raise an error */ continue; } @@ -1960,6 +1966,73 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw) break; } + + /* Check if we gave args that dont exist in the function + * printing the error is slow but it should only happen when developing. + * the if below is quick, checking if it passed less keyword args then we gave */ + if(kw && (PyDict_Size(kw) > kw_tot)) { + PyObject *key, *value; + Py_ssize_t pos = 0; + + DynStr *bad_args= BLI_dynstr_new(); + DynStr *good_args= BLI_dynstr_new(); + + char *arg_name, *bad_args_str, *good_args_str; + int found= 0, first=1; + + while (PyDict_Next(kw, &pos, &key, &value)) { + + arg_name= _PyUnicode_AsString(key); + found= 0; + + if(arg_name==NULL) { /* unlikely the argname is not a string but ignore if it is*/ + PyErr_Clear(); + } + else { + /* Search for arg_name */ + RNA_parameter_list_begin(&parms, &iter); + for(; iter.valid; RNA_parameter_list_next(&iter)) { + parm= iter.parm; + if (strcmp(arg_name, RNA_property_identifier(parm))==0) { + found= 1; + break; + } + } + + RNA_parameter_list_end(&iter); + + if(!found) { + BLI_dynstr_appendf(bad_args, first ? "%s" : ", %s", arg_name); + first= 0; + } + } + } + + /* list good args */ + first= 1; + + RNA_parameter_list_begin(&parms, &iter); + for(; iter.valid; RNA_parameter_list_next(&iter)) { + parm= iter.parm; + BLI_dynstr_appendf(good_args, first ? "%s" : ", %s", RNA_property_identifier(parm)); + first= 0; + } + RNA_parameter_list_end(&iter); + + + bad_args_str= BLI_dynstr_get_cstring(bad_args); + good_args_str= BLI_dynstr_get_cstring(good_args); + + PyErr_Format(PyExc_TypeError, "%.200s.%.200s(): was called with invalid keyword arguments(s) (%s), expected (%s)", RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), bad_args_str, good_args_str); + + BLI_dynstr_free(bad_args); + BLI_dynstr_free(good_args); + MEM_freeN(bad_args_str); + MEM_freeN(good_args_str); + + err= -1; + } + ret= NULL; if (err==0) { /* call function */ @@ -1967,20 +2040,26 @@ static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw) bContext *C= BPy_GetContext(); BKE_reports_init(&reports, RPT_STORE); - RNA_function_call(C, &reports, self_ptr, self_func, parms); + RNA_function_call(C, &reports, self_ptr, self_func, &parms); err= (BPy_reports_to_error(&reports))? -1: 0; BKE_reports_clear(&reports); /* return value */ - if(err==0) - if(pret) + if(err==0) { + if(pret) { ret= pyrna_param_to_py(&funcptr, pret, retdata); + + /* possible there is an error in conversion */ + if(ret==NULL) + err= -1; + } + } } /* cleanup */ RNA_parameter_list_end(&iter); - RNA_parameter_list_free(parms); + RNA_parameter_list_free(&parms); if (ret) return ret; @@ -2387,7 +2466,7 @@ static PyObject *pyrna_basetype_getattro( BPy_BaseTypeRNA * self, PyObject *pyna return ret; } else { /* Override the error */ - PyErr_Format(PyExc_AttributeError, "bpy.types.%.200s not a valid RNA_Struct", _PyUnicode_AsString(pyname)); + PyErr_Format(PyExc_AttributeError, "bpy.types.%.200s RNA_Struct does not exist", _PyUnicode_AsString(pyname)); return NULL; } } @@ -2629,7 +2708,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun if (base_class) { if (!PyObject_IsSubclass(py_class, base_class)) { PyObject *name= PyObject_GetAttrString(base_class, "__name__"); - PyErr_Format( PyExc_AttributeError, "expected %.200s subclass of class \"%.200s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>"); + PyErr_Format( PyExc_TypeError, "expected %.200s subclass of class \"%.200s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>"); Py_XDECREF(name); return -1; } @@ -2667,7 +2746,7 @@ static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_fun fitem= item; /* py 3.x */ if (PyFunction_Check(fitem)==0) { - PyErr_Format( PyExc_AttributeError, "expected %.200s class \"%.200s\" attribute to be a function", class_type, RNA_function_identifier(func)); + PyErr_Format( PyExc_TypeError, "expected %.200s class \"%.200s\" attribute to be a function", class_type, RNA_function_identifier(func)); return -1; } @@ -2795,12 +2874,12 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par } else { Py_DECREF(py_class_instance); - PyErr_Format(PyExc_AttributeError, "could not find function %.200s in %.200s to execute callback.", RNA_function_identifier(func), RNA_struct_identifier(ptr->type)); + PyErr_Format(PyExc_TypeError, "could not find function %.200s in %.200s to execute callback.", RNA_function_identifier(func), RNA_struct_identifier(ptr->type)); err= -1; } } else { - PyErr_Format(PyExc_AttributeError, "could not create instance of %.200s to call callback function %.200s.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func)); + PyErr_Format(PyExc_RuntimeError, "could not create instance of %.200s to call callback function %.200s.", RNA_struct_identifier(ptr->type), RNA_function_identifier(func)); err= -1; } |