modify the python context access so invalid names will raise an exception rather then returning None.

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.
This commit is contained in:
Campbell Barton 2009-11-10 15:09:53 +00:00
parent 1f2fe7ec14
commit 7efc2c2375
7 changed files with 91 additions and 39 deletions

View 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):

View 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);

View 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)

View 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 */
}

View 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 ************************/

View 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 */

View 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 {