bpy rna
authorCampbell Barton <ideasman42@gmail.com>
Fri, 17 Jul 2009 02:31:28 +0000 (02:31 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 17 Jul 2009 02:31:28 +0000 (02:31 +0000)
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.

release/ui/buttons_physics_fluid.py
release/ui/buttons_physics_softbody.py
source/blender/editors/space_console/space_console.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/RNA_types.h
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_internal_types.h
source/blender/makesrna/intern/rna_ui.c
source/blender/python/intern/bpy_rna.c

index 482dd231f14bd1ed305b51fb7a9f8cbf7468be7f..cab5b0c632a555bbe9b01e5fe8873744ea2567f5 100644 (file)
@@ -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
index 774f7f67979ef042d996bf5b8ad8601ecfb46353..35cee713a8791054f170b71bf0255e6bfb56ffed 100644 (file)
@@ -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")
index f5bccbce3f50a23d9b9d1a17d4d0158b538f2ba9..4585eef2579db96ff210488ade50594d779d5edf 100644 (file)
@@ -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;
index a04a09d4d117b487a2e17e24c2770ce6638d713d..9ad71f4e1d75b691d5f1d7c62bbd00c773cef988 100644 (file)
@@ -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);
index dc2a2a1a1dedc25ef62955f0e6c849a51b243bcb..bf4fa97b6fe331ce0a1838467316962d1fec0712 100644 (file)
@@ -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);
index 838592562b3dd9a23fdc08486321a477b4122ec3..b55df31640f7fdbc2aa6ce225c0beb54ef70c0d1 100644 (file)
@@ -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(&params, ptr, cprop->add);
+                       RNA_function_call(NULL, NULL, ptr, cprop->add, &params);
+                       RNA_parameter_list_free(&params);
                }
        }
 #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, &params);
+                       RNA_parameter_list_free(&params);
                }
        }
 #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;
 }
index b63e347e165867f829f525e6ced546ecccf1c722..12bd876ce52491fd26c5ba91d88a89f4575b504d 100644 (file)
@@ -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;
index b10ca6c5e83c603abccb1fb9d0f68c7db69c6317..217f1ea00a8fec0f9488c20cdc376b431f5a8fac 100644 (file)
@@ -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)
index 9ce9ec8e838b09adbfa00b8afbe0792bcc864873..34269db7f9493f834ef144f5b2a6a95886ee3417 100644 (file)
@@ -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;
        }