diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-11-17 12:47:34 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-11-17 12:47:34 +0400 |
commit | 92ed90d2fac4b62d242987542a58adb75e80966a (patch) | |
tree | eef477c543b2c89afd6e64158c39be6652b31935 /source/blender | |
parent | 096f7c06b111df6e4ee5370f27921681a56b53b6 (diff) |
pyapi feature from 2.4x
allow collection subscript to contain the library or None.
eg:
bpy.data.objects["Mesh", "/subsurf_test.blend"]
bpy.data.scenes["Scene", None]
# also works with get()
bpy.data.armatures.get(("some_armature", "//some_lib.blend"), None)
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 107 |
1 files changed, 103 insertions, 4 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index f1916355971..3bde38d1445 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -64,6 +64,7 @@ #include "MEM_guardedalloc.h" +#include "BKE_main.h" #include "BKE_idcode.h" #include "BKE_context.h" #include "BKE_global.h" /* evil G.* */ @@ -2096,6 +2097,84 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons } /* static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) */ +/* special case: bpy.data.objects["some_id_name", "//some_lib_name.blend"] + * also for: bpy.data.objects.get(("some_id_name", "//some_lib_name.blend"), fallback) */ +static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *self, PyObject *key, const char *err_prefix, const short err_not_found) +{ + char *keyname; + + /* first validate the args, all we know is that they are a tuple */ + if (PyTuple_GET_SIZE(key) != 2) { + PyErr_Format(PyExc_KeyError, + "%s: tuple key must be a pair, not size %d", + err_prefix, PyTuple_GET_SIZE(key)); + return NULL; + } + else if (self->ptr.type != &RNA_BlendData) { + PyErr_Format(PyExc_KeyError, + "%s: is only valid for bpy.data collections, not %.200s", + err_prefix, RNA_struct_identifier(self->ptr.type)); + return NULL; + } + else if ((keyname= _PyUnicode_AsString(PyTuple_GET_ITEM(key, 0))) == NULL) { + PyErr_Format(PyExc_KeyError, + "%s: id must be a string, not %.200s", + err_prefix, Py_TYPE(PyTuple_GET_ITEM(key, 0))->tp_name); + return NULL; + } + else { + PyObject *keylib= PyTuple_GET_ITEM(key, 1); + Library *lib; + PyObject *ret= NULL; + + if (keylib == Py_None) { + lib= NULL; + } + else if (PyUnicode_Check(keylib)) { + Main *bmain= self->ptr.data; + const char *keylib_str= _PyUnicode_AsString(keylib); + lib= BLI_findstring(&bmain->library, keylib_str, offsetof(Library, name)); + if (lib == NULL) { + if (err_not_found) { + PyErr_Format(PyExc_KeyError, + "%s: lib name '%.240s' " + "does not reference a valid library", + err_prefix, keylib_str); + } + + return NULL; + } + } + else { + PyErr_Format(PyExc_KeyError, + "%s: lib must be a sting or None, not %.200s", + err_prefix, Py_TYPE(keylib)->tp_name); + return NULL; + } + + /* lib is either a valid poniter or NULL, + * either way can do direct comparison with id.lib */ + + RNA_PROP_BEGIN(&self->ptr, itemptr, self->prop) { + ID *id= itemptr.data; /* always an ID */ + if (id->lib == lib && (strncmp(keyname, id->name+2, sizeof(id->name)-2) == 0)) { + ret= pyrna_struct_CreatePyObject(&itemptr); + break; + } + } + RNA_PROP_END; + + /* we may want to fail silently as with collection.get() */ + if ((ret == NULL) && err_not_found) { + /* only runs for getitem access so use fixed string */ + PyErr_SetString(PyExc_KeyError, + "bpy_prop_collection[key, lib]: not found"); + } + + return ret; + } +} + static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py_ssize_t start, Py_ssize_t stop) { CollectionPropertyIterator rna_macro_iter; @@ -2266,6 +2345,10 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject } } } + else if (PyTuple_Check(key)) { + /* special case, for ID datablocks we */ + return pyrna_prop_collection_subscript_str_lib_pair(self, key, "bpy_prop_collection[id, lib]", TRUE); + } else { PyErr_Format(PyExc_TypeError, "bpy_prop_collection[key]: invalid key, " @@ -3915,6 +3998,7 @@ static PyObject *pyrna_struct_as_pointer(BPy_StructRNA *self) return PyLong_FromVoidPtr(self->ptr.data); } +/* TODO, get (string, lib) pair */ PyDoc_STRVAR(pyrna_prop_collection_get_doc, ".. method:: get(key, default=None)\n" "\n" @@ -3931,16 +4015,31 @@ static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args { PointerRNA newptr; - const char *key; + PyObject *key_ob; PyObject* def= Py_None; PYRNA_PROP_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) + if (!PyArg_ParseTuple(args, "O|O:get", &key_ob, &def)) return NULL; - if (RNA_property_collection_lookup_string(&self->ptr, self->prop, key, &newptr)) - return pyrna_struct_CreatePyObject(&newptr); + if (PyUnicode_Check(key_ob)) { + const char *key= _PyUnicode_AsString(key_ob); + + if (RNA_property_collection_lookup_string(&self->ptr, self->prop, key, &newptr)) + return pyrna_struct_CreatePyObject(&newptr); + } + else if (PyTuple_Check(key_ob)) { + PyObject *ret= pyrna_prop_collection_subscript_str_lib_pair(self, key_ob, "bpy_prop_collection.get((id, lib))", FALSE); + if (ret) { + return ret; + } + } + else { + PyErr_Format(PyExc_KeyError, + "bpy_prop_collection.get(key, ...): key must be a string or tuple, not %.200s", + Py_TYPE(key_ob)->tp_name); + } return Py_INCREF(def), def; } |