modify the python context access so invalid names will raise an exception rather...
authorCampbell Barton <ideasman42@gmail.com>
Tue, 10 Nov 2009 15:09:53 +0000 (15:09 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 10 Nov 2009 15:09:53 +0000 (15:09 +0000)
this way the UI scripts are less likely to fail silently and wont let typos work ok.

also allow subclassing of the context, added a copy function,
 bpy.context.copy(), returns the context as a python dict to be modified and used in python.

This also showed up an invalid brush member in the screen context.

release/scripts/modules/bpy_types.py
source/blender/blenkernel/BKE_context.h
source/blender/blenkernel/intern/context.c
source/blender/editors/screen/screen_context.c
source/blender/editors/space_buttons/buttons_context.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/python/intern/bpy_rna.c

index d2bed9f7faae579659f08f161d07e91aab9d6115..23862c5c840f6bceec9e08d8aeee088e9477b43c 100644 (file)
@@ -22,6 +22,17 @@ StructRNA = bpy.types.Struct.__bases__[0]
 # StructRNA = bpy.types.Struct
 
 
+class Context(StructRNA):
+    
+    def copy(self):
+        new_context = {}
+        for item in dir(self):
+            if item not in StructRNA.__dict__ and item != "id_data":
+                new_context[item] = getattr(self, item)
+            
+        return new_context
+
+
 class Object(bpy.types.ID):
 
     def _get_children(self):
index feba39ee11db2de1ef327d6f8c4c0a336a701c8d..7f64538b10d09802c0073eefecfd4058fb0e51c2 100644 (file)
@@ -174,7 +174,7 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member);
 PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type);
 ListBase CTX_data_collection_get(const bContext *C, const char *member);
 ListBase CTX_data_dir_get(const bContext *C);
-void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb);
+int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb);
 
 void CTX_data_id_pointer_set(bContextDataResult *result, struct ID *id);
 void CTX_data_pointer_set(bContextDataResult *result, struct ID *id, StructRNA *type, void *data);
index 7f2872c0797fc5b8294893687c897f0fdc2d0db6..1cd0e6cd677ff95b5d867cad30819e9028263fdd 100644 (file)
@@ -408,6 +408,7 @@ struct bContextDataResult {
 static int ctx_data_get(bContext *C, const char *member, bContextDataResult *result)
 {
        int done= 0, recursion= C->data.recursion;
+       int ret= 0;
 
        memset(result, 0, sizeof(bContextDataResult));
 
@@ -417,7 +418,14 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res
 
        /* we check recursion to ensure that we do not get infinite
         * loops requesting data from ourselfs in a context callback */
-       if(!done && recursion < 1 && C->wm.store) {
+
+       /* Ok, this looks evil...
+        * if(ret) done= -(-ret | -done);
+        *
+        * Values in order of importance
+        * (0, -1, 1) - Where 1 is highest priority
+        * */
+       if(done!=1 && recursion < 1 && C->wm.store) {
                bContextStoreEntry *entry;
 
                C->data.recursion= 1;
@@ -429,21 +437,28 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res
                        }
                }
        }
-       if(!done && recursion < 2 && C->wm.region) {
+       if(done!=1 && recursion < 2 && C->wm.region) {
                C->data.recursion= 2;
-               if(C->wm.region->type && C->wm.region->type->context)
-                       done= C->wm.region->type->context(C, member, result);
+               if(C->wm.region->type && C->wm.region->type->context) {
+                       ret = C->wm.region->type->context(C, member, result);
+                       if(ret) done= -(-ret | -done);
+
+               }
        }
-       if(!done && recursion < 3 && C->wm.area) {
+       if(done!=1 && recursion < 3 && C->wm.area) {
                C->data.recursion= 3;
-               if(C->wm.area->type && C->wm.area->type->context)
-                       done= C->wm.area->type->context(C, member, result);
+               if(C->wm.area->type && C->wm.area->type->context) {
+                       ret = C->wm.area->type->context(C, member, result);
+                       if(ret) done= -(-ret | -done);
+               }
        }
-       if(!done && recursion < 4 && C->wm.screen) {
+       if(done!=1 && recursion < 4 && C->wm.screen) {
                bContextDataCallback cb= C->wm.screen->context;
                C->data.recursion= 4;
-               if(cb)
-                       done= cb(C, member, result);
+               if(cb) {
+                       ret = cb(C, member, result);
+                       if(ret) done= -(-ret | -done);
+               }
        }
 
        C->data.recursion= recursion;
@@ -455,7 +470,7 @@ static void *ctx_data_pointer_get(const bContext *C, const char *member)
 {
        bContextDataResult result;
 
-       if(C && ctx_data_get((bContext*)C, member, &result))
+       if(C && ctx_data_get((bContext*)C, member, &result)==1)
                return result.ptr.data;
 
        return NULL;
@@ -465,7 +480,7 @@ static int ctx_data_pointer_verify(const bContext *C, const char *member, void *
 {
        bContextDataResult result;
 
-       if(ctx_data_get((bContext*)C, member, &result)) {
+       if(ctx_data_get((bContext*)C, member, &result)==1) {
                *pointer= result.ptr.data;
                return 1;
        }
@@ -479,7 +494,7 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa
 {
        bContextDataResult result;
 
-       if(ctx_data_get((bContext*)C, member, &result)) {
+       if(ctx_data_get((bContext*)C, member, &result)==1) {
                *list= result.list;
                return 1;
        }
@@ -494,7 +509,7 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
 {
        bContextDataResult result;
 
-       if(ctx_data_get((bContext*)C, member, &result))
+       if(ctx_data_get((bContext*)C, member, &result)==1)
                return result.ptr;
        else
                return PointerRNA_NULL;
@@ -514,7 +529,7 @@ ListBase CTX_data_collection_get(const bContext *C, const char *member)
 {
        bContextDataResult result;
 
-       if(ctx_data_get((bContext*)C, member, &result)) {
+       if(ctx_data_get((bContext*)C, member, &result)==1) {
                return result.list;
        }
        else {
@@ -524,11 +539,13 @@ ListBase CTX_data_collection_get(const bContext *C, const char *member)
        }
 }
 
-void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb)
+/* 1:found,  -1:found but not set,  0:not found */
+int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb)
 {
        bContextDataResult result;
+       int ret= ctx_data_get((bContext*)C, member, &result);
 
-       if(ctx_data_get((bContext*)C, member, &result)) {
+       if(ret==1) {
                *r_ptr= result.ptr;
                *r_lb= result.list;
        }
@@ -536,6 +553,8 @@ void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, List
                memset(r_ptr, 0, sizeof(*r_ptr));
                memset(r_lb, 0, sizeof(*r_lb));
        }
+
+       return ret;
 }
 
 static void data_dir_add(ListBase *lb, const char *member)
index 31827e1b9c00cc9e527d1bd109ed471617b00765..1a1def70717d6561dfd05af7741e402ea59baed2 100644 (file)
@@ -67,7 +67,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
                        "visible_pchans", "selected_pchans", "active_bone", "active_pchan",
                        "active_base", "active_object", "edit_object",
                        "sculpt_object", "vertex_paint_object", "weight_paint_object",
-                       "texture_paint_object", "brush", "particle_edit_object", NULL};
+                       "texture_paint_object", "particle_edit_object", NULL};
 
                CTX_data_dir_set(result, dir);
                return 1;
@@ -304,7 +304,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
 
                return 1;
        }
+       else {
+               return 0; /* not found */
+       }
 
-       return 0;
+       return -1; /* found but not available */
 }
 
index 71d5b59f2535ada50957506f523625d56fcc014b..0e2769a35577debbccf1631fb034803909b9c7a5 100644 (file)
@@ -707,8 +707,11 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
                set_pointer_type(path, result, &RNA_Brush);
                return 1;
        }
+       else {
+               return 0; /* not found */
+       }
 
-       return 0;
+       return -1; /* found but not available */
 }
 
 /************************* Drawing the Path ************************/
index 4a9042aa31c90d1324a8d27ab93e52aab35b2f60..5bde6e029e4e60e4ead0d8aa43964b15bc021cc1 100644 (file)
@@ -747,7 +747,11 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
                
                return 1;
        }
-       return 0;
+       else {
+               return 0; /* not found */
+       }
+
+       return -1; /* found but not available */
 }
 
 /* only called once, from space/spacetypes.c */
index bcc12eb4502743741a21e5d9c0cd6dcc6deeb7eb..c06931feedb7156ef4e65db7ec93db4b1060409f 100644 (file)
@@ -1376,27 +1376,38 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
        else if (self->ptr.type == &RNA_Context) {
                PointerRNA newptr;
                ListBase newlb;
+               int done;
 
-               CTX_data_get(self->ptr.data, name, &newptr, &newlb);
+               done= CTX_data_get(self->ptr.data, name, &newptr, &newlb);
 
-        if (newptr.data) {
-            ret = pyrna_struct_CreatePyObject(&newptr);
-               }
-               else if (newlb.first) {
-                       CollectionPointerLink *link;
-                       PyObject *linkptr;
+               if(done==1) { /* found */
+                       if (newptr.data) {
+                               ret = pyrna_struct_CreatePyObject(&newptr);
+                       }
+                       else if (newlb.first) {
+                               CollectionPointerLink *link;
+                               PyObject *linkptr;
 
-                       ret = PyList_New(0);
+                               ret = PyList_New(0);
 
-                       for(link=newlb.first; link; link=link->next) {
-                               linkptr= pyrna_struct_CreatePyObject(&link->ptr);
-                               PyList_Append(ret, linkptr);
-                               Py_DECREF(linkptr);
+                               for(link=newlb.first; link; link=link->next) {
+                                       linkptr= pyrna_struct_CreatePyObject(&link->ptr);
+                                       PyList_Append(ret, linkptr);
+                                       Py_DECREF(linkptr);
+                               }
+                       }
+                       else {
+                               ret = Py_None;
+                               Py_INCREF(ret);
                        }
                }
-        else {
-            ret = Py_None;
-            Py_INCREF(ret);
+               else if (done==-1) { /* found but not set */
+                       ret = Py_None;
+                       Py_INCREF(ret);
+               }
+        else { /* not found in the context */
+               /* lookup the subclass. raise an error if its not found */
+               ret = PyObject_GenericGetAttr((PyObject *)self, pyname);
         }
 
                BLI_freelistN(&newlb);
@@ -1405,10 +1416,11 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname )
                if(self->ptr.id.data) {
                        PointerRNA id_ptr;
                        RNA_id_pointer_create((ID *)self->ptr.id.data, &id_ptr);
-                       return pyrna_struct_CreatePyObject(&id_ptr);
+                       ret = pyrna_struct_CreatePyObject(&id_ptr);
                }
                else {
-                       Py_RETURN_NONE;
+                       ret = Py_None;
+                       Py_INCREF(ret);
                }
        }
        else {