diff options
Diffstat (limited to 'source/blender/python/intern/bpy_rna.c')
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 14186 |
1 files changed, 7183 insertions, 7003 deletions
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 71d46de1be8..cf45d6ca2d9 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -83,73 +83,71 @@ BPy_StructRNA *bpy_context_module = NULL; /* for fast access */ static PyObject *pyrna_struct_Subtype(PointerRNA *ptr); static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self); -#define BPY_DOC_ID_PROP_TYPE_NOTE \ -" .. note::\n" \ -"\n" \ -" Only :class:`bpy.types.ID`, :class:`bpy.types.Bone` and\n" \ -" :class:`bpy.types.PoseBone` classes support custom properties.\n" - +#define BPY_DOC_ID_PROP_TYPE_NOTE \ + " .. note::\n" \ + "\n" \ + " Only :class:`bpy.types.ID`, :class:`bpy.types.Bone` and\n" \ + " :class:`bpy.types.PoseBone` classes support custom properties.\n" int pyrna_struct_validity_check(BPy_StructRNA *pysrna) { - if (pysrna->ptr.type) { - return 0; - } - PyErr_Format(PyExc_ReferenceError, - "StructRNA of type %.200s has been removed", - Py_TYPE(pysrna)->tp_name); - return -1; + if (pysrna->ptr.type) { + return 0; + } + PyErr_Format( + PyExc_ReferenceError, "StructRNA of type %.200s has been removed", Py_TYPE(pysrna)->tp_name); + return -1; } int pyrna_prop_validity_check(BPy_PropertyRNA *self) { - if (self->ptr.type) { - return 0; - } - PyErr_Format(PyExc_ReferenceError, - "PropertyRNA of type %.200s.%.200s has been removed", - Py_TYPE(self)->tp_name, RNA_property_identifier(self->prop)); - return -1; + if (self->ptr.type) { + return 0; + } + PyErr_Format(PyExc_ReferenceError, + "PropertyRNA of type %.200s.%.200s has been removed", + Py_TYPE(self)->tp_name, + RNA_property_identifier(self->prop)); + return -1; } void pyrna_invalidate(BPy_DummyPointerRNA *self) { - RNA_POINTER_INVALIDATE(&self->ptr); + RNA_POINTER_INVALIDATE(&self->ptr); } #ifdef USE_PYRNA_INVALIDATE_GC -#define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g) + 1)) +# define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g) + 1)) /* only for sizeof() */ struct gc_generation { - PyGC_Head head; - int threshold; - int count; + PyGC_Head head; + int threshold; + int count; } gc_generation; static void id_release_gc(struct ID *id) { - unsigned int j; - // unsigned int i = 0; - for (j = 0; j < 3; j++) { - /* hack below to get the 2 other lists from _PyGC_generation0 that are normally not exposed */ - PyGC_Head *gen = (PyGC_Head *)(((char *)_PyGC_generation0) + (sizeof(gc_generation) * j)); - PyGC_Head *g = gen->gc.gc_next; - while ((g = g->gc.gc_next) != gen) { - PyObject *ob = FROM_GC(g); - if (PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) || - PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) - { - BPy_DummyPointerRNA *ob_ptr = (BPy_DummyPointerRNA *)ob; - if (ob_ptr->ptr.id.data == id) { - pyrna_invalidate(ob_ptr); - // printf("freeing: %p %s, %.200s\n", (void *)ob, id->name, Py_TYPE(ob)->tp_name); - // i++; - } - } - } - } - // printf("id_release_gc freed '%s': %d\n", id->name, i); + unsigned int j; + // unsigned int i = 0; + for (j = 0; j < 3; j++) { + /* hack below to get the 2 other lists from _PyGC_generation0 that are normally not exposed */ + PyGC_Head *gen = (PyGC_Head *)(((char *)_PyGC_generation0) + (sizeof(gc_generation) * j)); + PyGC_Head *g = gen->gc.gc_next; + while ((g = g->gc.gc_next) != gen) { + PyObject *ob = FROM_GC(g); + if (PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) || + PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) { + BPy_DummyPointerRNA *ob_ptr = (BPy_DummyPointerRNA *)ob; + if (ob_ptr->ptr.id.data == id) { + pyrna_invalidate(ob_ptr); + // printf("freeing: %p %s, %.200s\n", (void *)ob, id->name, Py_TYPE(ob)->tp_name); + // i++; + } + } + } + } + // printf("id_release_gc freed '%s': %d\n", id->name, i); } #endif @@ -158,128 +156,128 @@ static void id_release_gc(struct ID *id) struct GHash *id_weakref_pool = NULL; static PyObject *id_free_weakref_cb(PyObject *weakinfo_pair, PyObject *weakref); -static PyMethodDef id_free_weakref_cb_def = {"id_free_weakref_cb", (PyCFunction)id_free_weakref_cb, METH_O, NULL}; +static PyMethodDef id_free_weakref_cb_def = { + "id_free_weakref_cb", (PyCFunction)id_free_weakref_cb, METH_O, NULL}; /* adds a reference to the list, remember to decref */ static GHash *id_weakref_pool_get(ID *id) { - GHash *weakinfo_hash = NULL; + GHash *weakinfo_hash = NULL; - if (id_weakref_pool) { - weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id); - } - else { - /* first time, allocate pool */ - id_weakref_pool = BLI_ghash_ptr_new("rna_global_pool"); - weakinfo_hash = NULL; - } + if (id_weakref_pool) { + weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id); + } + else { + /* first time, allocate pool */ + id_weakref_pool = BLI_ghash_ptr_new("rna_global_pool"); + weakinfo_hash = NULL; + } - if (weakinfo_hash == NULL) { - /* we're using a ghash as a set, could use libHX's HXMAP_SINGULAR but would be an extra dep. */ - weakinfo_hash = BLI_ghash_ptr_new("rna_id"); - BLI_ghash_insert(id_weakref_pool, id, weakinfo_hash); - } + if (weakinfo_hash == NULL) { + /* we're using a ghash as a set, could use libHX's HXMAP_SINGULAR but would be an extra dep. */ + weakinfo_hash = BLI_ghash_ptr_new("rna_id"); + BLI_ghash_insert(id_weakref_pool, id, weakinfo_hash); + } - return weakinfo_hash; + return weakinfo_hash; } /* called from pyrna_struct_CreatePyObject() and pyrna_prop_CreatePyObject() */ static void id_weakref_pool_add(ID *id, BPy_DummyPointerRNA *pyrna) { - PyObject *weakref; - PyObject *weakref_capsule; - PyObject *weakref_cb_py; - - /* create a new function instance and insert the list as 'self' so we can remove ourself from it */ - GHash *weakinfo_hash = id_weakref_pool_get(id); /* new or existing */ + PyObject *weakref; + PyObject *weakref_capsule; + PyObject *weakref_cb_py; - weakref_capsule = PyCapsule_New(weakinfo_hash, NULL, NULL); - weakref_cb_py = PyCFunction_New(&id_free_weakref_cb_def, weakref_capsule); - Py_DECREF(weakref_capsule); + /* create a new function instance and insert the list as 'self' so we can remove ourself from it */ + GHash *weakinfo_hash = id_weakref_pool_get(id); /* new or existing */ - /* add weakref to weakinfo_hash list */ - weakref = PyWeakref_NewRef((PyObject *)pyrna, weakref_cb_py); + weakref_capsule = PyCapsule_New(weakinfo_hash, NULL, NULL); + weakref_cb_py = PyCFunction_New(&id_free_weakref_cb_def, weakref_capsule); + Py_DECREF(weakref_capsule); - Py_DECREF(weakref_cb_py); /* function owned by the weakref now */ + /* add weakref to weakinfo_hash list */ + weakref = PyWeakref_NewRef((PyObject *)pyrna, weakref_cb_py); - /* important to add at the end, since first removal looks at the end */ - BLI_ghash_insert(weakinfo_hash, weakref, id); /* using a hash table as a set, all 'id's are the same */ - /* weakinfo_hash owns the weakref */ + Py_DECREF(weakref_cb_py); /* function owned by the weakref now */ + /* important to add at the end, since first removal looks at the end */ + BLI_ghash_insert( + weakinfo_hash, weakref, id); /* using a hash table as a set, all 'id's are the same */ + /* weakinfo_hash owns the weakref */ } /* workaround to get the last id without a lookup */ static ID *_id_tmp_ptr; static void value_id_set(void *id) { - _id_tmp_ptr = (ID *)id; + _id_tmp_ptr = (ID *)id; } static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash); static PyObject *id_free_weakref_cb(PyObject *weakinfo_capsule, PyObject *weakref) { - /* important to search backwards */ - GHash *weakinfo_hash = PyCapsule_GetPointer(weakinfo_capsule, NULL); + /* important to search backwards */ + GHash *weakinfo_hash = PyCapsule_GetPointer(weakinfo_capsule, NULL); + if (BLI_ghash_len(weakinfo_hash) > 1) { + BLI_ghash_remove(weakinfo_hash, weakref, NULL, NULL); + } + else { /* get the last id and free it */ + BLI_ghash_remove(weakinfo_hash, weakref, NULL, value_id_set); + id_release_weakref_list(_id_tmp_ptr, weakinfo_hash); + } - if (BLI_ghash_len(weakinfo_hash) > 1) { - BLI_ghash_remove(weakinfo_hash, weakref, NULL, NULL); - } - else { /* get the last id and free it */ - BLI_ghash_remove(weakinfo_hash, weakref, NULL, value_id_set); - id_release_weakref_list(_id_tmp_ptr, weakinfo_hash); - } + Py_DECREF(weakref); - Py_DECREF(weakref); - - Py_RETURN_NONE; + Py_RETURN_NONE; } static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash) { - GHashIterator weakinfo_hash_iter; + GHashIterator weakinfo_hash_iter; - BLI_ghashIterator_init(&weakinfo_hash_iter, weakinfo_hash); + BLI_ghashIterator_init(&weakinfo_hash_iter, weakinfo_hash); -#ifdef DEBUG_RNA_WEAKREF - fprintf(stdout, "id_release_weakref: '%s', %d items\n", id->name, BLI_ghash_len(weakinfo_hash)); -#endif +# ifdef DEBUG_RNA_WEAKREF + fprintf(stdout, "id_release_weakref: '%s', %d items\n", id->name, BLI_ghash_len(weakinfo_hash)); +# endif - while (!BLI_ghashIterator_done(&weakinfo_hash_iter)) { - PyObject *weakref = (PyObject *)BLI_ghashIterator_getKey(&weakinfo_hash_iter); - PyObject *item = PyWeakref_GET_OBJECT(weakref); - if (item != Py_None) { + while (!BLI_ghashIterator_done(&weakinfo_hash_iter)) { + PyObject *weakref = (PyObject *)BLI_ghashIterator_getKey(&weakinfo_hash_iter); + PyObject *item = PyWeakref_GET_OBJECT(weakref); + if (item != Py_None) { -#ifdef DEBUG_RNA_WEAKREF - PyC_ObSpit("id_release_weakref item ", item); -#endif +# ifdef DEBUG_RNA_WEAKREF + PyC_ObSpit("id_release_weakref item ", item); +# endif - pyrna_invalidate((BPy_DummyPointerRNA *)item); - } + pyrna_invalidate((BPy_DummyPointerRNA *)item); + } - Py_DECREF(weakref); + Py_DECREF(weakref); - BLI_ghashIterator_step(&weakinfo_hash_iter); - } + BLI_ghashIterator_step(&weakinfo_hash_iter); + } - BLI_ghash_remove(id_weakref_pool, (void *)id, NULL, NULL); - BLI_ghash_free(weakinfo_hash, NULL, NULL); + BLI_ghash_remove(id_weakref_pool, (void *)id, NULL, NULL); + BLI_ghash_free(weakinfo_hash, NULL, NULL); - if (BLI_ghash_len(id_weakref_pool) == 0) { - BLI_ghash_free(id_weakref_pool, NULL, NULL); - id_weakref_pool = NULL; -#ifdef DEBUG_RNA_WEAKREF - printf("id_release_weakref freeing pool\n"); -#endif - } + if (BLI_ghash_len(id_weakref_pool) == 0) { + BLI_ghash_free(id_weakref_pool, NULL, NULL); + id_weakref_pool = NULL; +# ifdef DEBUG_RNA_WEAKREF + printf("id_release_weakref freeing pool\n"); +# endif + } } static void id_release_weakref(struct ID *id) { - GHash *weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id); - if (weakinfo_hash) { - id_release_weakref_list(id, weakinfo_hash); - } + GHash *weakinfo_hash = BLI_ghash_lookup(id_weakref_pool, (void *)id); + if (weakinfo_hash) { + id_release_weakref_list(id, weakinfo_hash); + } } #endif /* USE_PYRNA_INVALIDATE_WEAKREF */ @@ -287,20 +285,20 @@ static void id_release_weakref(struct ID *id) void BPY_id_release(struct ID *id) { #ifdef USE_PYRNA_INVALIDATE_GC - id_release_gc(id); + id_release_gc(id); #endif #ifdef USE_PYRNA_INVALIDATE_WEAKREF - if (id_weakref_pool) { - PyGILState_STATE gilstate = PyGILState_Ensure(); + if (id_weakref_pool) { + PyGILState_STATE gilstate = PyGILState_Ensure(); - id_release_weakref(id); + id_release_weakref(id); - PyGILState_Release(gilstate); - } + PyGILState_Release(gilstate); + } #endif /* USE_PYRNA_INVALIDATE_WEAKREF */ - (void)id; + (void)id; } #ifdef USE_PEDANTIC_WRITE @@ -308,480 +306,487 @@ static bool rna_disallow_writes = false; static bool rna_id_write_error(PointerRNA *ptr, PyObject *key) { - ID *id = ptr->id.data; - if (id) { - const short idcode = GS(id->name); - if (!ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { /* may need more added here */ - const char *idtype = BKE_idcode_to_name(idcode); - const char *pyname; - if (key && PyUnicode_Check(key)) { - pyname = _PyUnicode_AsString(key); - } - else { - pyname = "<UNKNOWN>"; - } - - /* make a nice string error */ - BLI_assert(idtype != NULL); - PyErr_Format(PyExc_AttributeError, - "Writing to ID classes in this context is not allowed: " - "%.200s, %.200s datablock, error setting %.200s.%.200s", - id->name + 2, idtype, RNA_struct_identifier(ptr->type), pyname); - - return true; - } - } - return false; -} -#endif /* USE_PEDANTIC_WRITE */ - + ID *id = ptr->id.data; + if (id) { + const short idcode = GS(id->name); + if (!ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { /* may need more added here */ + const char *idtype = BKE_idcode_to_name(idcode); + const char *pyname; + if (key && PyUnicode_Check(key)) { + pyname = _PyUnicode_AsString(key); + } + else { + pyname = "<UNKNOWN>"; + } + + /* make a nice string error */ + BLI_assert(idtype != NULL); + PyErr_Format(PyExc_AttributeError, + "Writing to ID classes in this context is not allowed: " + "%.200s, %.200s datablock, error setting %.200s.%.200s", + id->name + 2, + idtype, + RNA_struct_identifier(ptr->type), + pyname); + + return true; + } + } + return false; +} +#endif /* USE_PEDANTIC_WRITE */ #ifdef USE_PEDANTIC_WRITE bool pyrna_write_check(void) { - return !rna_disallow_writes; + return !rna_disallow_writes; } void pyrna_write_set(bool val) { - rna_disallow_writes = !val; + rna_disallow_writes = !val; } #else /* USE_PEDANTIC_WRITE */ bool pyrna_write_check(void) { - return true; + return true; } void pyrna_write_set(bool UNUSED(val)) { - /* nothing */ + /* nothing */ } -#endif /* USE_PEDANTIC_WRITE */ +#endif /* USE_PEDANTIC_WRITE */ static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self); static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self); -static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix); +static int pyrna_py_to_prop( + PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix); static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item); #ifdef USE_MATHUTILS -#include "../mathutils/mathutils.h" /* so we can have mathutils callbacks */ - -static PyObject *pyrna_prop_array_subscript_slice( - BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, - Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length); -static short pyrna_rotation_euler_order_get( - PointerRNA *ptr, const short order_fallback, - PropertyRNA **r_prop_eul_order); +# include "../mathutils/mathutils.h" /* so we can have mathutils callbacks */ + +static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, + PointerRNA *ptr, + PropertyRNA *prop, + Py_ssize_t start, + Py_ssize_t stop, + Py_ssize_t length); +static short pyrna_rotation_euler_order_get(PointerRNA *ptr, + const short order_fallback, + PropertyRNA **r_prop_eul_order); /* bpyrna vector/euler/quat callbacks */ static unsigned char mathutils_rna_array_cb_index = -1; /* index for our callbacks */ /* subtype not used much yet */ -#define MATHUTILS_CB_SUBTYPE_EUL 0 -#define MATHUTILS_CB_SUBTYPE_VEC 1 -#define MATHUTILS_CB_SUBTYPE_QUAT 2 -#define MATHUTILS_CB_SUBTYPE_COLOR 3 +# define MATHUTILS_CB_SUBTYPE_EUL 0 +# define MATHUTILS_CB_SUBTYPE_VEC 1 +# define MATHUTILS_CB_SUBTYPE_QUAT 2 +# define MATHUTILS_CB_SUBTYPE_COLOR 3 static int mathutils_rna_generic_check(BaseMathObject *bmo) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - return self->prop ? 0 : -1; + return self->prop ? 0 : -1; } static int mathutils_rna_vector_get(BaseMathObject *bmo, int subtype) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - if (self->prop == NULL) { - return -1; - } + if (self->prop == NULL) { + return -1; + } - RNA_property_float_get_array(&self->ptr, self->prop, bmo->data); + RNA_property_float_get_array(&self->ptr, self->prop, bmo->data); - /* Euler order exception */ - if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { - EulerObject *eul = (EulerObject *)bmo; - PropertyRNA *prop_eul_order = NULL; - eul->order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); - } + /* Euler order exception */ + if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { + EulerObject *eul = (EulerObject *)bmo; + PropertyRNA *prop_eul_order = NULL; + eul->order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); + } - return 0; + return 0; } static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - float min, max; - - PYRNA_PROP_CHECK_INT(self); - - if (self->prop == NULL) { - return -1; - } - -#ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ - - if (!RNA_property_editable_flag(&self->ptr, self->prop)) { - PyErr_Format(PyExc_AttributeError, - "bpy_prop \"%.200s.%.200s\" is read-only", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop)); - return -1; - } - - RNA_property_float_range(&self->ptr, self->prop, &min, &max); - - if (min != -FLT_MAX || max != FLT_MAX) { - int i, len = RNA_property_array_length(&self->ptr, self->prop); - for (i = 0; i < len; i++) { - CLAMP(bmo->data[i], min, max); - } - } - - RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); - if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); - } - - /* Euler order exception */ - if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { - EulerObject *eul = (EulerObject *)bmo; - PropertyRNA *prop_eul_order = NULL; - short order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); - if (order != eul->order) { - RNA_property_enum_set(&self->ptr, prop_eul_order, eul->order); - if (RNA_property_update_check(prop_eul_order)) { - RNA_property_update(BPy_GetContext(), &self->ptr, prop_eul_order); - } - } - } - return 0; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + float min, max; + + PYRNA_PROP_CHECK_INT(self); + + if (self->prop == NULL) { + return -1; + } + +# ifdef USE_PEDANTIC_WRITE + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return -1; + } +# endif /* USE_PEDANTIC_WRITE */ + + if (!RNA_property_editable_flag(&self->ptr, self->prop)) { + PyErr_Format(PyExc_AttributeError, + "bpy_prop \"%.200s.%.200s\" is read-only", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); + return -1; + } + + RNA_property_float_range(&self->ptr, self->prop, &min, &max); + + if (min != -FLT_MAX || max != FLT_MAX) { + int i, len = RNA_property_array_length(&self->ptr, self->prop); + for (i = 0; i < len; i++) { + CLAMP(bmo->data[i], min, max); + } + } + + RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); + if (RNA_property_update_check(self->prop)) { + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + } + + /* Euler order exception */ + if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { + EulerObject *eul = (EulerObject *)bmo; + PropertyRNA *prop_eul_order = NULL; + short order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); + if (order != eul->order) { + RNA_property_enum_set(&self->ptr, prop_eul_order, eul->order); + if (RNA_property_update_check(prop_eul_order)) { + RNA_property_update(BPy_GetContext(), &self->ptr, prop_eul_order); + } + } + } + return 0; } static int mathutils_rna_vector_get_index(BaseMathObject *bmo, int UNUSED(subtype), int index) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - if (self->prop == NULL) { - return -1; - } + if (self->prop == NULL) { + return -1; + } - bmo->data[index] = RNA_property_float_get_index(&self->ptr, self->prop, index); - return 0; + bmo->data[index] = RNA_property_float_get_index(&self->ptr, self->prop, index); + return 0; } static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int UNUSED(subtype), int index) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - if (self->prop == NULL) { - return -1; - } + if (self->prop == NULL) { + return -1; + } -#ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ +# ifdef USE_PEDANTIC_WRITE + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return -1; + } +# endif /* USE_PEDANTIC_WRITE */ - if (!RNA_property_editable_flag(&self->ptr, self->prop)) { - PyErr_Format(PyExc_AttributeError, - "bpy_prop \"%.200s.%.200s\" is read-only", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop)); - return -1; - } + if (!RNA_property_editable_flag(&self->ptr, self->prop)) { + PyErr_Format(PyExc_AttributeError, + "bpy_prop \"%.200s.%.200s\" is read-only", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); + return -1; + } - RNA_property_float_clamp(&self->ptr, self->prop, &bmo->data[index]); - RNA_property_float_set_index(&self->ptr, self->prop, index, bmo->data[index]); + RNA_property_float_clamp(&self->ptr, self->prop, &bmo->data[index]); + RNA_property_float_set_index(&self->ptr, self->prop, index, bmo->data[index]); - if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); - } + if (RNA_property_update_check(self->prop)) { + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + } - return 0; + return 0; } static Mathutils_Callback mathutils_rna_array_cb = { - (BaseMathCheckFunc) mathutils_rna_generic_check, - (BaseMathGetFunc) mathutils_rna_vector_get, - (BaseMathSetFunc) mathutils_rna_vector_set, - (BaseMathGetIndexFunc) mathutils_rna_vector_get_index, - (BaseMathSetIndexFunc) mathutils_rna_vector_set_index, + (BaseMathCheckFunc)mathutils_rna_generic_check, + (BaseMathGetFunc)mathutils_rna_vector_get, + (BaseMathSetFunc)mathutils_rna_vector_set, + (BaseMathGetIndexFunc)mathutils_rna_vector_get_index, + (BaseMathSetIndexFunc)mathutils_rna_vector_set_index, }; - /* bpyrna matrix callbacks */ static unsigned char mathutils_rna_matrix_cb_index = -1; /* index for our callbacks */ static int mathutils_rna_matrix_get(BaseMathObject *bmo, int UNUSED(subtype)) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - if (self->prop == NULL) { - return -1; - } + if (self->prop == NULL) { + return -1; + } - RNA_property_float_get_array(&self->ptr, self->prop, bmo->data); - return 0; + RNA_property_float_get_array(&self->ptr, self->prop, bmo->data); + return 0; } static int mathutils_rna_matrix_set(BaseMathObject *bmo, int UNUSED(subtype)) { - BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; + BPy_PropertyRNA *self = (BPy_PropertyRNA *)bmo->cb_user; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - if (self->prop == NULL) { - return -1; - } + if (self->prop == NULL) { + return -1; + } -#ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ +# ifdef USE_PEDANTIC_WRITE + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return -1; + } +# endif /* USE_PEDANTIC_WRITE */ - if (!RNA_property_editable_flag(&self->ptr, self->prop)) { - PyErr_Format(PyExc_AttributeError, - "bpy_prop \"%.200s.%.200s\" is read-only", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop)); - return -1; - } + if (!RNA_property_editable_flag(&self->ptr, self->prop)) { + PyErr_Format(PyExc_AttributeError, + "bpy_prop \"%.200s.%.200s\" is read-only", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); + return -1; + } - /* can ignore clamping here */ - RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); + /* can ignore clamping here */ + RNA_property_float_set_array(&self->ptr, self->prop, bmo->data); - if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); - } - return 0; + if (RNA_property_update_check(self->prop)) { + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + } + return 0; } static Mathutils_Callback mathutils_rna_matrix_cb = { - mathutils_rna_generic_check, - mathutils_rna_matrix_get, - mathutils_rna_matrix_set, - NULL, - NULL, + mathutils_rna_generic_check, + mathutils_rna_matrix_get, + mathutils_rna_matrix_set, + NULL, + NULL, }; -static short pyrna_rotation_euler_order_get( - PointerRNA *ptr, const short order_fallback, - PropertyRNA **r_prop_eul_order) +static short pyrna_rotation_euler_order_get(PointerRNA *ptr, + const short order_fallback, + PropertyRNA **r_prop_eul_order) { - /* attempt to get order */ - if (*r_prop_eul_order == NULL) { - *r_prop_eul_order = RNA_struct_find_property(ptr, "rotation_mode"); - } + /* attempt to get order */ + if (*r_prop_eul_order == NULL) { + *r_prop_eul_order = RNA_struct_find_property(ptr, "rotation_mode"); + } - if (*r_prop_eul_order) { - short order = RNA_property_enum_get(ptr, *r_prop_eul_order); - /* could be quat or axisangle */ - if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) { - return order; - } - } + if (*r_prop_eul_order) { + short order = RNA_property_enum_get(ptr, *r_prop_eul_order); + /* could be quat or axisangle */ + if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) { + return order; + } + } - return order_fallback; + return order_fallback; } -#endif /* USE_MATHUTILS */ +#endif /* USE_MATHUTILS */ /* note that PROP_NONE is included as a vector subtype. this is because its handy to * have x/y access to fcurve keyframes and other fixed size float arrays of length 2-4. */ -#define PROP_ALL_VECTOR_SUBTYPES \ - PROP_COORDS: \ - case PROP_TRANSLATION: \ - case PROP_DIRECTION: \ - case PROP_VELOCITY: \ - case PROP_ACCELERATION: \ - case PROP_XYZ: \ - case PROP_XYZ_LENGTH \ - +#define PROP_ALL_VECTOR_SUBTYPES \ + PROP_COORDS: \ + case PROP_TRANSLATION: \ + case PROP_DIRECTION: \ + case PROP_VELOCITY: \ + case PROP_ACCELERATION: \ + case PROP_XYZ: \ + case PROP_XYZ_LENGTH PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) { - PyObject *ret = NULL; + PyObject *ret = NULL; #ifdef USE_MATHUTILS - int subtype, totdim; - int len; - const int flag = RNA_property_flag(prop); - const int type = RNA_property_type(prop); - const bool is_thick = (flag & PROP_THICK_WRAP) != 0; - - /* disallow dynamic sized arrays to be wrapped since the size could change - * to a size mathutils does not support */ - if (flag & PROP_DYNAMIC) { - return NULL; - } - - len = RNA_property_array_length(ptr, prop); - if (type == PROP_FLOAT) { - /* pass */ - } - else if (type == PROP_INT) { - if (is_thick) { - goto thick_wrap_slice; - } - else { - return NULL; - } - } - else { - return NULL; - } - - subtype = RNA_property_subtype(prop); - totdim = RNA_property_array_dimension(ptr, prop, NULL); - - if (totdim == 1 || (totdim == 2 && subtype == PROP_MATRIX)) { - if (!is_thick) { - /* owned by the mathutils PyObject */ - ret = pyrna_prop_CreatePyObject(ptr, prop); - } - - switch (subtype) { - case PROP_ALL_VECTOR_SUBTYPES: - if (len >= 2 && len <= 4) { - if (is_thick) { - ret = Vector_CreatePyObject(NULL, len, NULL); - RNA_property_float_get_array(ptr, prop, ((VectorObject *)ret)->vec); - } - else { - PyObject *vec_cb = Vector_CreatePyObject_cb( - ret, len, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_VEC); - Py_DECREF(ret); /* the vector owns now */ - ret = vec_cb; /* return the vector instead */ - } - } - break; - case PROP_MATRIX: - if (len == 16) { - if (is_thick) { - ret = Matrix_CreatePyObject(NULL, 4, 4, NULL); - RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix); - } - else { - PyObject *mat_cb = Matrix_CreatePyObject_cb( - ret, 4, 4, mathutils_rna_matrix_cb_index, 0); - Py_DECREF(ret); /* the matrix owns now */ - ret = mat_cb; /* return the matrix instead */ - } - } - else if (len == 9) { - if (is_thick) { - ret = Matrix_CreatePyObject(NULL, 3, 3, NULL); - RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix); - } - else { - PyObject *mat_cb = Matrix_CreatePyObject_cb( - ret, 3, 3, mathutils_rna_matrix_cb_index, 0); - Py_DECREF(ret); /* the matrix owns now */ - ret = mat_cb; /* return the matrix instead */ - } - } - break; - case PROP_EULER: - case PROP_QUATERNION: - if (len == 3) { /* euler */ - if (is_thick) { - /* attempt to get order, only needed for thick types since wrapped with update via callbacks */ - PropertyRNA *prop_eul_order = NULL; - short order = pyrna_rotation_euler_order_get(ptr, EULER_ORDER_XYZ, &prop_eul_order); - - ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA */ - RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul); - } - else { - /* order will be updated from callback on use */ - // TODO, get order from RNA - PyObject *eul_cb = Euler_CreatePyObject_cb( - ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); - Py_DECREF(ret); /* the euler owns now */ - ret = eul_cb; /* return the euler instead */ - } - } - else if (len == 4) { - if (is_thick) { - ret = Quaternion_CreatePyObject(NULL, NULL); - RNA_property_float_get_array(ptr, prop, ((QuaternionObject *)ret)->quat); - } - else { - PyObject *quat_cb = Quaternion_CreatePyObject_cb( - ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_QUAT); - Py_DECREF(ret); /* the quat owns now */ - ret = quat_cb; /* return the quat instead */ - } - } - break; - case PROP_COLOR: - case PROP_COLOR_GAMMA: - if (len == 3) { /* color */ - if (is_thick) { - ret = Color_CreatePyObject(NULL, NULL); - RNA_property_float_get_array(ptr, prop, ((ColorObject *)ret)->col); - } - else { - PyObject *col_cb = Color_CreatePyObject_cb( - ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_COLOR); - Py_DECREF(ret); /* the color owns now */ - ret = col_cb; /* return the color instead */ - } - } - break; - default: - break; - } - } - - if (ret == NULL) { - if (is_thick) { - /* this is an array we cant reference (since its not thin wrappable) - * and cannot be coerced into a mathutils type, so return as a list */ -thick_wrap_slice: - ret = pyrna_prop_array_subscript_slice(NULL, ptr, prop, 0, len, len); - } - else { - ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the mathutils PyObject */ - } - } + int subtype, totdim; + int len; + const int flag = RNA_property_flag(prop); + const int type = RNA_property_type(prop); + const bool is_thick = (flag & PROP_THICK_WRAP) != 0; + + /* disallow dynamic sized arrays to be wrapped since the size could change + * to a size mathutils does not support */ + if (flag & PROP_DYNAMIC) { + return NULL; + } + + len = RNA_property_array_length(ptr, prop); + if (type == PROP_FLOAT) { + /* pass */ + } + else if (type == PROP_INT) { + if (is_thick) { + goto thick_wrap_slice; + } + else { + return NULL; + } + } + else { + return NULL; + } + + subtype = RNA_property_subtype(prop); + totdim = RNA_property_array_dimension(ptr, prop, NULL); + + if (totdim == 1 || (totdim == 2 && subtype == PROP_MATRIX)) { + if (!is_thick) { + /* owned by the mathutils PyObject */ + ret = pyrna_prop_CreatePyObject(ptr, prop); + } + + switch (subtype) { + case PROP_ALL_VECTOR_SUBTYPES: + if (len >= 2 && len <= 4) { + if (is_thick) { + ret = Vector_CreatePyObject(NULL, len, NULL); + RNA_property_float_get_array(ptr, prop, ((VectorObject *)ret)->vec); + } + else { + PyObject *vec_cb = Vector_CreatePyObject_cb( + ret, len, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_VEC); + Py_DECREF(ret); /* the vector owns now */ + ret = vec_cb; /* return the vector instead */ + } + } + break; + case PROP_MATRIX: + if (len == 16) { + if (is_thick) { + ret = Matrix_CreatePyObject(NULL, 4, 4, NULL); + RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix); + } + else { + PyObject *mat_cb = Matrix_CreatePyObject_cb( + ret, 4, 4, mathutils_rna_matrix_cb_index, 0); + Py_DECREF(ret); /* the matrix owns now */ + ret = mat_cb; /* return the matrix instead */ + } + } + else if (len == 9) { + if (is_thick) { + ret = Matrix_CreatePyObject(NULL, 3, 3, NULL); + RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix); + } + else { + PyObject *mat_cb = Matrix_CreatePyObject_cb( + ret, 3, 3, mathutils_rna_matrix_cb_index, 0); + Py_DECREF(ret); /* the matrix owns now */ + ret = mat_cb; /* return the matrix instead */ + } + } + break; + case PROP_EULER: + case PROP_QUATERNION: + if (len == 3) { /* euler */ + if (is_thick) { + /* attempt to get order, only needed for thick types since wrapped with update via callbacks */ + PropertyRNA *prop_eul_order = NULL; + short order = pyrna_rotation_euler_order_get(ptr, EULER_ORDER_XYZ, &prop_eul_order); + + ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA */ + RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul); + } + else { + /* order will be updated from callback on use */ + // TODO, get order from RNA + PyObject *eul_cb = Euler_CreatePyObject_cb( + ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); + Py_DECREF(ret); /* the euler owns now */ + ret = eul_cb; /* return the euler instead */ + } + } + else if (len == 4) { + if (is_thick) { + ret = Quaternion_CreatePyObject(NULL, NULL); + RNA_property_float_get_array(ptr, prop, ((QuaternionObject *)ret)->quat); + } + else { + PyObject *quat_cb = Quaternion_CreatePyObject_cb( + ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_QUAT); + Py_DECREF(ret); /* the quat owns now */ + ret = quat_cb; /* return the quat instead */ + } + } + break; + case PROP_COLOR: + case PROP_COLOR_GAMMA: + if (len == 3) { /* color */ + if (is_thick) { + ret = Color_CreatePyObject(NULL, NULL); + RNA_property_float_get_array(ptr, prop, ((ColorObject *)ret)->col); + } + else { + PyObject *col_cb = Color_CreatePyObject_cb( + ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_COLOR); + Py_DECREF(ret); /* the color owns now */ + ret = col_cb; /* return the color instead */ + } + } + break; + default: + break; + } + } + + if (ret == NULL) { + if (is_thick) { + /* this is an array we cant reference (since its not thin wrappable) + * and cannot be coerced into a mathutils type, so return as a list */ + thick_wrap_slice: + ret = pyrna_prop_array_subscript_slice(NULL, ptr, prop, 0, len, len); + } + else { + ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the mathutils PyObject */ + } + } #else /* USE_MATHUTILS */ - (void)ptr; - (void)prop; -#endif /* USE_MATHUTILS */ + (void)ptr; + (void)prop; +#endif /* USE_MATHUTILS */ - return ret; + return ret; } /* same as RNA_enum_value_from_id but raises an exception */ -int pyrna_enum_value_from_id( - const EnumPropertyItem *item, const char *identifier, int *r_value, - const char *error_prefix) +int pyrna_enum_value_from_id(const EnumPropertyItem *item, + const char *identifier, + int *r_value, + const char *error_prefix) { - if (RNA_enum_value_from_id(item, identifier, r_value) == 0) { - const char *enum_str = BPy_enum_as_string(item); - PyErr_Format(PyExc_ValueError, - "%s: '%.200s' not found in (%s)", - error_prefix, identifier, enum_str); - MEM_freeN((void *)enum_str); - return -1; - } + if (RNA_enum_value_from_id(item, identifier, r_value) == 0) { + const char *enum_str = BPy_enum_as_string(item); + PyErr_Format( + PyExc_ValueError, "%s: '%.200s' not found in (%s)", error_prefix, identifier, enum_str); + MEM_freeN((void *)enum_str); + return -1; + } - return 0; + return 0; } /* note on __cmp__: @@ -797,325 +802,315 @@ int pyrna_enum_value_from_id( static int pyrna_struct_compare(BPy_StructRNA *a, BPy_StructRNA *b) { - return (((a->ptr.data == b->ptr.data) && - (a->ptr.type == b->ptr.type)) ? 0 : -1); + return (((a->ptr.data == b->ptr.data) && (a->ptr.type == b->ptr.type)) ? 0 : -1); } static int pyrna_prop_compare(BPy_PropertyRNA *a, BPy_PropertyRNA *b) { - return (((a->prop == b->prop) && - (a->ptr.data == b->ptr.data) && - (a->ptr.type == b->ptr.type)) ? 0 : -1); + return (((a->prop == b->prop) && (a->ptr.data == b->ptr.data) && (a->ptr.type == b->ptr.type)) ? + 0 : + -1); } static PyObject *pyrna_struct_richcmp(PyObject *a, PyObject *b, int op) { - PyObject *res; - int ok = -1; /* zero is true */ + PyObject *res; + int ok = -1; /* zero is true */ - if (BPy_StructRNA_Check(a) && BPy_StructRNA_Check(b)) { - ok = pyrna_struct_compare((BPy_StructRNA *)a, (BPy_StructRNA *)b); - } + if (BPy_StructRNA_Check(a) && BPy_StructRNA_Check(b)) { + ok = pyrna_struct_compare((BPy_StructRNA *)a, (BPy_StructRNA *)b); + } - switch (op) { - case Py_NE: - ok = !ok; - ATTR_FALLTHROUGH; - case Py_EQ: - res = ok ? Py_False : Py_True; - break; + switch (op) { + case Py_NE: + ok = !ok; + ATTR_FALLTHROUGH; + case Py_EQ: + res = ok ? Py_False : Py_True; + break; - case Py_LT: - case Py_LE: - case Py_GT: - case Py_GE: - res = Py_NotImplemented; - break; - default: - PyErr_BadArgument(); - return NULL; - } + case Py_LT: + case Py_LE: + case Py_GT: + case Py_GE: + res = Py_NotImplemented; + break; + default: + PyErr_BadArgument(); + return NULL; + } - return Py_INCREF_RET(res); + return Py_INCREF_RET(res); } static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op) { - PyObject *res; - int ok = -1; /* zero is true */ + PyObject *res; + int ok = -1; /* zero is true */ - if (BPy_PropertyRNA_Check(a) && BPy_PropertyRNA_Check(b)) { - ok = pyrna_prop_compare((BPy_PropertyRNA *)a, (BPy_PropertyRNA *)b); - } + if (BPy_PropertyRNA_Check(a) && BPy_PropertyRNA_Check(b)) { + ok = pyrna_prop_compare((BPy_PropertyRNA *)a, (BPy_PropertyRNA *)b); + } - switch (op) { - case Py_NE: - ok = !ok; - ATTR_FALLTHROUGH; - case Py_EQ: - res = ok ? Py_False : Py_True; - break; + switch (op) { + case Py_NE: + ok = !ok; + ATTR_FALLTHROUGH; + case Py_EQ: + res = ok ? Py_False : Py_True; + break; - case Py_LT: - case Py_LE: - case Py_GT: - case Py_GE: - res = Py_NotImplemented; - break; - default: - PyErr_BadArgument(); - return NULL; - } + case Py_LT: + case Py_LE: + case Py_GT: + case Py_GE: + res = Py_NotImplemented; + break; + default: + PyErr_BadArgument(); + return NULL; + } - return Py_INCREF_RET(res); + return Py_INCREF_RET(res); } /*----------------------repr--------------------------------------------*/ static PyObject *pyrna_struct_str(BPy_StructRNA *self) { - PyObject *ret; - const char *name; + PyObject *ret; + const char *name; - if (!PYRNA_STRUCT_IS_VALID(self)) { - return PyUnicode_FromFormat("<bpy_struct, %.200s invalid>", - Py_TYPE(self)->tp_name); - } + if (!PYRNA_STRUCT_IS_VALID(self)) { + return PyUnicode_FromFormat("<bpy_struct, %.200s invalid>", Py_TYPE(self)->tp_name); + } - /* print name if available */ - name = RNA_struct_name_get_alloc(&self->ptr, NULL, 0, NULL); - if (name) { - ret = PyUnicode_FromFormat("<bpy_struct, %.200s(\"%.200s\")>", - RNA_struct_identifier(self->ptr.type), - name); - MEM_freeN((void *)name); - return ret; - } + /* print name if available */ + name = RNA_struct_name_get_alloc(&self->ptr, NULL, 0, NULL); + if (name) { + ret = PyUnicode_FromFormat( + "<bpy_struct, %.200s(\"%.200s\")>", RNA_struct_identifier(self->ptr.type), name); + MEM_freeN((void *)name); + return ret; + } - return PyUnicode_FromFormat("<bpy_struct, %.200s at %p>", - RNA_struct_identifier(self->ptr.type), - self->ptr.data); + return PyUnicode_FromFormat( + "<bpy_struct, %.200s at %p>", RNA_struct_identifier(self->ptr.type), self->ptr.data); } static PyObject *pyrna_struct_repr(BPy_StructRNA *self) { - ID *id = self->ptr.id.data; - PyObject *tmp_str; - PyObject *ret; - - if (id == NULL || !PYRNA_STRUCT_IS_VALID(self)) { - /* fallback */ - return pyrna_struct_str(self); - } - - tmp_str = PyUnicode_FromString(id->name + 2); - - if (RNA_struct_is_ID(self->ptr.type)) { - ret = PyUnicode_FromFormat("bpy.data.%s[%R]", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str); - } - else { - const char *path; - path = RNA_path_from_ID_to_struct(&self->ptr); - if (path) { - if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */ - ret = PyUnicode_FromFormat("bpy.data...%s", - path); - } - else { - ret = PyUnicode_FromFormat("bpy.data.%s[%R].%s", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str, - path); - } - - MEM_freeN((void *)path); - } - else { /* cant find, print something sane */ - ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str, - RNA_struct_identifier(self->ptr.type)); - } - } - - Py_DECREF(tmp_str); - - return ret; + ID *id = self->ptr.id.data; + PyObject *tmp_str; + PyObject *ret; + + if (id == NULL || !PYRNA_STRUCT_IS_VALID(self)) { + /* fallback */ + return pyrna_struct_str(self); + } + + tmp_str = PyUnicode_FromString(id->name + 2); + + if (RNA_struct_is_ID(self->ptr.type)) { + ret = PyUnicode_FromFormat( + "bpy.data.%s[%R]", BKE_idcode_to_name_plural(GS(id->name)), tmp_str); + } + else { + const char *path; + path = RNA_path_from_ID_to_struct(&self->ptr); + if (path) { + if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */ + ret = PyUnicode_FromFormat("bpy.data...%s", path); + } + else { + ret = PyUnicode_FromFormat( + "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(id->name)), tmp_str, path); + } + + MEM_freeN((void *)path); + } + else { /* cant find, print something sane */ + ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str, + RNA_struct_identifier(self->ptr.type)); + } + } + + Py_DECREF(tmp_str); + + return ret; } static PyObject *pyrna_prop_str(BPy_PropertyRNA *self) { - PyObject *ret; - PointerRNA ptr; - const char *name; - const char *type_id = NULL; - char type_fmt[64] = ""; - int type; - - PYRNA_PROP_CHECK_OBJ(self); - - type = RNA_property_type(self->prop); - - if (RNA_enum_id_from_value(rna_enum_property_type_items, type, &type_id) == 0) { - PyErr_SetString(PyExc_RuntimeError, "could not use property type, internal error"); /* should never happen */ - return NULL; - } - else { - /* this should never fail */ - int len = -1; - char *c = type_fmt; - - while ((*c++ = tolower(*type_id++))) {} - - if (type == PROP_COLLECTION) { - len = pyrna_prop_collection_length(self); - } - else if (RNA_property_array_check(self->prop)) { - len = pyrna_prop_array_length((BPy_PropertyArrayRNA *)self); - } - - if (len != -1) { - sprintf(--c, "[%d]", len); - } - } - - /* if a pointer, try to print name of pointer target too */ - if (type == PROP_POINTER) { - ptr = RNA_property_pointer_get(&self->ptr, self->prop); - name = RNA_struct_name_get_alloc(&ptr, NULL, 0, NULL); - - if (name) { - ret = PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s(\"%.200s\")>", - type_fmt, - RNA_struct_identifier(self->ptr.type), - RNA_property_identifier(self->prop), - name); - MEM_freeN((void *)name); - return ret; - } - } - if (type == PROP_COLLECTION) { - PointerRNA r_ptr; - if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - return PyUnicode_FromFormat("<bpy_%.200s, %.200s>", - type_fmt, - RNA_struct_identifier(r_ptr.type)); - } - } - - return PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s>", - type_fmt, - RNA_struct_identifier(self->ptr.type), - RNA_property_identifier(self->prop)); -} - -static PyObject *pyrna_prop_repr_ex( - BPy_PropertyRNA *self, - const int index_dim, const int index) -{ - ID *id = self->ptr.id.data; - PyObject *tmp_str; - PyObject *ret; - const char *path; - - PYRNA_PROP_CHECK_OBJ(self); - - if (id == NULL) { - /* fallback */ - return pyrna_prop_str(self); - } - - tmp_str = PyUnicode_FromString(id->name + 2); - - path = RNA_path_from_ID_to_property_index(&self->ptr, self->prop, index_dim, index); - - if (path) { - const char *data_delim = (path[0] == '[') ? "" : "."; - if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */ - ret = PyUnicode_FromFormat("bpy.data...%s", - path); - } - else { - ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str, - data_delim, path); - } - - MEM_freeN((void *)path); - } - else { /* cant find, print something sane */ - ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s", - BKE_idcode_to_name_plural(GS(id->name)), - tmp_str, - RNA_property_identifier(self->prop)); - } - - Py_DECREF(tmp_str); - - return ret; + PyObject *ret; + PointerRNA ptr; + const char *name; + const char *type_id = NULL; + char type_fmt[64] = ""; + int type; + + PYRNA_PROP_CHECK_OBJ(self); + + type = RNA_property_type(self->prop); + + if (RNA_enum_id_from_value(rna_enum_property_type_items, type, &type_id) == 0) { + PyErr_SetString(PyExc_RuntimeError, + "could not use property type, internal error"); /* should never happen */ + return NULL; + } + else { + /* this should never fail */ + int len = -1; + char *c = type_fmt; + + while ((*c++ = tolower(*type_id++))) { + } + + if (type == PROP_COLLECTION) { + len = pyrna_prop_collection_length(self); + } + else if (RNA_property_array_check(self->prop)) { + len = pyrna_prop_array_length((BPy_PropertyArrayRNA *)self); + } + + if (len != -1) { + sprintf(--c, "[%d]", len); + } + } + + /* if a pointer, try to print name of pointer target too */ + if (type == PROP_POINTER) { + ptr = RNA_property_pointer_get(&self->ptr, self->prop); + name = RNA_struct_name_get_alloc(&ptr, NULL, 0, NULL); + + if (name) { + ret = PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s(\"%.200s\")>", + type_fmt, + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop), + name); + MEM_freeN((void *)name); + return ret; + } + } + if (type == PROP_COLLECTION) { + PointerRNA r_ptr; + if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + return PyUnicode_FromFormat( + "<bpy_%.200s, %.200s>", type_fmt, RNA_struct_identifier(r_ptr.type)); + } + } + + return PyUnicode_FromFormat("<bpy_%.200s, %.200s.%.200s>", + type_fmt, + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); +} + +static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, const int index) +{ + ID *id = self->ptr.id.data; + PyObject *tmp_str; + PyObject *ret; + const char *path; + + PYRNA_PROP_CHECK_OBJ(self); + + if (id == NULL) { + /* fallback */ + return pyrna_prop_str(self); + } + + tmp_str = PyUnicode_FromString(id->name + 2); + + path = RNA_path_from_ID_to_property_index(&self->ptr, self->prop, index_dim, index); + + if (path) { + const char *data_delim = (path[0] == '[') ? "" : "."; + if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */ + ret = PyUnicode_FromFormat("bpy.data...%s", path); + } + else { + ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str, + data_delim, + path); + } + + MEM_freeN((void *)path); + } + else { /* cant find, print something sane */ + ret = PyUnicode_FromFormat("bpy.data.%s[%R]...%s", + BKE_idcode_to_name_plural(GS(id->name)), + tmp_str, + RNA_property_identifier(self->prop)); + } + + Py_DECREF(tmp_str); + + return ret; } static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self) { - return pyrna_prop_repr_ex(self, 0, -1); + return pyrna_prop_repr_ex(self, 0, -1); } static PyObject *pyrna_prop_array_repr(BPy_PropertyArrayRNA *self) { - return pyrna_prop_repr_ex((BPy_PropertyRNA *)self, self->arraydim, self->arrayoffset); + return pyrna_prop_repr_ex((BPy_PropertyRNA *)self, self->arraydim, self->arrayoffset); } static PyObject *pyrna_func_repr(BPy_FunctionRNA *self) { - return PyUnicode_FromFormat("<%.200s %.200s.%.200s()>", - Py_TYPE(self)->tp_name, - RNA_struct_identifier(self->ptr.type), - RNA_function_identifier(self->func)); + return PyUnicode_FromFormat("<%.200s %.200s.%.200s()>", + Py_TYPE(self)->tp_name, + RNA_struct_identifier(self->ptr.type), + RNA_function_identifier(self->func)); } - static Py_hash_t pyrna_struct_hash(BPy_StructRNA *self) { - return _Py_HashPointer(self->ptr.data); + return _Py_HashPointer(self->ptr.data); } /* from python's meth_hash v3.1.2 */ static long pyrna_prop_hash(BPy_PropertyRNA *self) { - long x, y; - if (self->ptr.data == NULL) { - x = 0; - } - else { - x = _Py_HashPointer(self->ptr.data); - if (x == -1) { - return -1; - } - } - y = _Py_HashPointer((void *)(self->prop)); - if (y == -1) { - return -1; - } - x ^= y; - if (x == -1) { - x = -2; - } - return x; + long x, y; + if (self->ptr.data == NULL) { + x = 0; + } + else { + x = _Py_HashPointer(self->ptr.data); + if (x == -1) { + return -1; + } + } + y = _Py_HashPointer((void *)(self->prop)); + if (y == -1) { + return -1; + } + x ^= y; + if (x == -1) { + x = -2; + } + return x; } #ifdef USE_PYRNA_STRUCT_REFERENCE static int pyrna_struct_traverse(BPy_StructRNA *self, visitproc visit, void *arg) { - Py_VISIT(self->reference); - return 0; + Py_VISIT(self->reference); + return 0; } static int pyrna_struct_clear(BPy_StructRNA *self) { - Py_CLEAR(self->reference); - return 0; + Py_CLEAR(self->reference); + return 0; } #endif /* !USE_PYRNA_STRUCT_REFERENCE */ @@ -1123,44 +1118,44 @@ static int pyrna_struct_clear(BPy_StructRNA *self) static void pyrna_struct_dealloc(BPy_StructRNA *self) { #ifdef PYRNA_FREE_SUPPORT - if (self->freeptr && self->ptr.data) { - IDP_FreeProperty(self->ptr.data); - MEM_freeN(self->ptr.data); - self->ptr.data = NULL; - } + if (self->freeptr && self->ptr.data) { + IDP_FreeProperty(self->ptr.data); + MEM_freeN(self->ptr.data); + self->ptr.data = NULL; + } #endif /* PYRNA_FREE_SUPPORT */ #ifdef USE_WEAKREFS - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *)self); - } + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject *)self); + } #endif #ifdef USE_PYRNA_STRUCT_REFERENCE - if (self->reference) { - PyObject_GC_UnTrack(self); - pyrna_struct_clear(self); - } + if (self->reference) { + PyObject_GC_UnTrack(self); + pyrna_struct_clear(self); + } #endif /* !USE_PYRNA_STRUCT_REFERENCE */ - /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ - Py_TYPE(self)->tp_free(self); + /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ + Py_TYPE(self)->tp_free(self); } #ifdef USE_PYRNA_STRUCT_REFERENCE static void pyrna_struct_reference_set(BPy_StructRNA *self, PyObject *reference) { - if (self->reference) { -// PyObject_GC_UnTrack(self); /* INITIALIZED TRACKED ? */ - pyrna_struct_clear(self); - } - /* reference is now NULL */ + if (self->reference) { + // PyObject_GC_UnTrack(self); /* INITIALIZED TRACKED ? */ + pyrna_struct_clear(self); + } + /* reference is now NULL */ - if (reference) { - self->reference = reference; - Py_INCREF(reference); -// PyObject_GC_Track(self); /* INITIALIZED TRACKED ? */ - } + if (reference) { + self->reference = reference; + Py_INCREF(reference); + // PyObject_GC_Track(self); /* INITIALIZED TRACKED ? */ + } } #endif /* !USE_PYRNA_STRUCT_REFERENCE */ @@ -1168,71 +1163,72 @@ static void pyrna_struct_reference_set(BPy_StructRNA *self, PyObject *reference) static void pyrna_prop_dealloc(BPy_PropertyRNA *self) { #ifdef USE_WEAKREFS - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *)self); - } + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject *)self); + } #endif - /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ - Py_TYPE(self)->tp_free(self); + /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ + Py_TYPE(self)->tp_free(self); } static void pyrna_prop_array_dealloc(BPy_PropertyRNA *self) { #ifdef USE_WEAKREFS - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *)self); - } + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject *)self); + } #endif - /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ - Py_TYPE(self)->tp_free(self); + /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ + Py_TYPE(self)->tp_free(self); } static const char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) { - const EnumPropertyItem *item; - const char *result; - bool free = false; + const EnumPropertyItem *item; + const char *result; + bool free = false; - RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); - if (item) { - result = BPy_enum_as_string(item); - } - else { - result = ""; - } + RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); + if (item) { + result = BPy_enum_as_string(item); + } + else { + result = ""; + } - if (free) { - MEM_freeN((void *)item); - } + if (free) { + MEM_freeN((void *)item); + } - return result; + return result; } - static int pyrna_string_to_enum( - PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *r_value, - const char *error_prefix) -{ - const char *param = _PyUnicode_AsString(item); - - if (param == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s expected a string enum, not %.200s", - error_prefix, Py_TYPE(item)->tp_name); - return -1; - } - else { - if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, r_value)) { - const char *enum_str = pyrna_enum_as_string(ptr, prop); - PyErr_Format(PyExc_TypeError, - "%.200s enum \"%.200s\" not found in (%s)", - error_prefix, param, enum_str); - MEM_freeN((void *)enum_str); - return -1; - } - } - - return 0; + PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *r_value, const char *error_prefix) +{ + const char *param = _PyUnicode_AsString(item); + + if (param == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s expected a string enum, not %.200s", + error_prefix, + Py_TYPE(item)->tp_name); + return -1; + } + else { + if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, r_value)) { + const char *enum_str = pyrna_enum_as_string(ptr, prop); + PyErr_Format(PyExc_TypeError, + "%.200s enum \"%.200s\" not found in (%s)", + error_prefix, + param, + enum_str); + MEM_freeN((void *)enum_str); + return -1; + } + } + + return 0; } /** @@ -1243,1112 +1239,1150 @@ static int pyrna_string_to_enum( * \param type_convert_sign: Maps signed to unsigned range, * needed when we want to use the full range of a signed short/char. */ -BLI_bitmap *pyrna_set_to_enum_bitmap( - const EnumPropertyItem *items, PyObject *value, - int type_size, bool type_convert_sign, - int bitmap_size, - const char *error_prefix) -{ - /* set looping */ - Py_ssize_t pos = 0; - Py_ssize_t hash = 0; - PyObject *key; - - BLI_bitmap *bitmap = BLI_BITMAP_NEW(bitmap_size, __func__); - - while (_PySet_NextEntry(value, &pos, &key, &hash)) { - const char *param = _PyUnicode_AsString(key); - if (param == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s expected a string, not %.200s", - error_prefix, Py_TYPE(key)->tp_name); - goto error; - } - - int ret; - if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) { - goto error; - } - - int index = ret; - - if (type_convert_sign) { - if (type_size == 2) { - union { signed short as_signed; unsigned short as_unsigned; } ret_convert; - ret_convert.as_signed = (signed short)ret; - index = (int)ret_convert.as_unsigned; - } - else if (type_size == 1) { - union { signed char as_signed; unsigned char as_unsigned; } ret_convert; - ret_convert.as_signed = (signed char)ret; - index = (int)ret_convert.as_unsigned; - } - else { - BLI_assert(0); - } - } - BLI_assert(index < bitmap_size); - BLI_BITMAP_ENABLE(bitmap, index); - } - - return bitmap; +BLI_bitmap *pyrna_set_to_enum_bitmap(const EnumPropertyItem *items, + PyObject *value, + int type_size, + bool type_convert_sign, + int bitmap_size, + const char *error_prefix) +{ + /* set looping */ + Py_ssize_t pos = 0; + Py_ssize_t hash = 0; + PyObject *key; + + BLI_bitmap *bitmap = BLI_BITMAP_NEW(bitmap_size, __func__); + + while (_PySet_NextEntry(value, &pos, &key, &hash)) { + const char *param = _PyUnicode_AsString(key); + if (param == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s expected a string, not %.200s", + error_prefix, + Py_TYPE(key)->tp_name); + goto error; + } + + int ret; + if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) { + goto error; + } + + int index = ret; + + if (type_convert_sign) { + if (type_size == 2) { + union { + signed short as_signed; + unsigned short as_unsigned; + } ret_convert; + ret_convert.as_signed = (signed short)ret; + index = (int)ret_convert.as_unsigned; + } + else if (type_size == 1) { + union { + signed char as_signed; + unsigned char as_unsigned; + } ret_convert; + ret_convert.as_signed = (signed char)ret; + index = (int)ret_convert.as_unsigned; + } + else { + BLI_assert(0); + } + } + BLI_assert(index < bitmap_size); + BLI_BITMAP_ENABLE(bitmap, index); + } + + return bitmap; error: - MEM_freeN(bitmap); - return NULL; + MEM_freeN(bitmap); + return NULL; } /* 'value' _must_ be a set type, error check before calling */ -int pyrna_set_to_enum_bitfield( - const EnumPropertyItem *items, PyObject *value, int *r_value, - const char *error_prefix) +int pyrna_set_to_enum_bitfield(const EnumPropertyItem *items, + PyObject *value, + int *r_value, + const char *error_prefix) { - /* set of enum items, concatenate all values with OR */ - int ret, flag = 0; + /* set of enum items, concatenate all values with OR */ + int ret, flag = 0; - /* set looping */ - Py_ssize_t pos = 0; - Py_ssize_t hash = 0; - PyObject *key; + /* set looping */ + Py_ssize_t pos = 0; + Py_ssize_t hash = 0; + PyObject *key; - *r_value = 0; + *r_value = 0; - while (_PySet_NextEntry(value, &pos, &key, &hash)) { - const char *param = _PyUnicode_AsString(key); + while (_PySet_NextEntry(value, &pos, &key, &hash)) { + const char *param = _PyUnicode_AsString(key); - if (param == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s expected a string, not %.200s", - error_prefix, Py_TYPE(key)->tp_name); - return -1; - } + if (param == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s expected a string, not %.200s", + error_prefix, + Py_TYPE(key)->tp_name); + return -1; + } - if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) { - return -1; - } + if (pyrna_enum_value_from_id(items, param, &ret, error_prefix) == -1) { + return -1; + } - flag |= ret; - } + flag |= ret; + } - *r_value = flag; - return 0; + *r_value = flag; + return 0; } static int pyrna_prop_to_enum_bitfield( - PointerRNA *ptr, PropertyRNA *prop, PyObject *value, int *r_value, - const char *error_prefix) -{ - const EnumPropertyItem *item; - int ret; - bool free = false; - - *r_value = 0; - - if (!PyAnySet_Check(value)) { - PyErr_Format(PyExc_TypeError, - "%.200s, %.200s.%.200s expected a set, not a %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - return -1; - } - - RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); - - if (item) { - ret = pyrna_set_to_enum_bitfield(item, value, r_value, error_prefix); - } - else { - if (PySet_GET_SIZE(value)) { - PyErr_Format(PyExc_TypeError, - "%.200s: empty enum \"%.200s\" could not have any values assigned", - error_prefix, RNA_property_identifier(prop)); - ret = -1; - } - else { - ret = 0; - } - } - - if (free) { - MEM_freeN((void *)item); - } - - return ret; + PointerRNA *ptr, PropertyRNA *prop, PyObject *value, int *r_value, const char *error_prefix) +{ + const EnumPropertyItem *item; + int ret; + bool free = false; + + *r_value = 0; + + if (!PyAnySet_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s, %.200s.%.200s expected a set, not a %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + return -1; + } + + RNA_property_enum_items(BPy_GetContext(), ptr, prop, &item, NULL, &free); + + if (item) { + ret = pyrna_set_to_enum_bitfield(item, value, r_value, error_prefix); + } + else { + if (PySet_GET_SIZE(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: empty enum \"%.200s\" could not have any values assigned", + error_prefix, + RNA_property_identifier(prop)); + ret = -1; + } + else { + ret = 0; + } + } + + if (free) { + MEM_freeN((void *)item); + } + + return ret; } PyObject *pyrna_enum_bitfield_to_py(const EnumPropertyItem *items, int value) { - PyObject *ret = PySet_New(NULL); - const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1]; + PyObject *ret = PySet_New(NULL); + const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1]; - if (RNA_enum_bitflag_identifiers(items, value, identifier)) { - PyObject *item; - int index; - for (index = 0; identifier[index]; index++) { - item = PyUnicode_FromString(identifier[index]); - PySet_Add(ret, item); - Py_DECREF(item); - } - } + if (RNA_enum_bitflag_identifiers(items, value, identifier)) { + PyObject *item; + int index; + for (index = 0; identifier[index]; index++) { + item = PyUnicode_FromString(identifier[index]); + PySet_Add(ret, item); + Py_DECREF(item); + } + } - return ret; + return ret; } static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val) { - PyObject *item, *ret = NULL; - - if (RNA_property_flag(prop) & PROP_ENUM_FLAG) { - const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1]; - - ret = PySet_New(NULL); - - if (RNA_property_enum_bitflag_identifiers(BPy_GetContext(), ptr, prop, val, identifier)) { - int index; - - for (index = 0; identifier[index]; index++) { - item = PyUnicode_FromString(identifier[index]); - PySet_Add(ret, item); - Py_DECREF(item); - } - - } - } - else { - const char *identifier; - if (RNA_property_enum_identifier(BPy_GetContext(), ptr, prop, val, &identifier)) { - ret = PyUnicode_FromString(identifier); - } - else { - /* Static, no need to free. */ - const EnumPropertyItem *enum_item; - bool free_dummy; - RNA_property_enum_items_ex(NULL, ptr, prop, true, &enum_item, NULL, &free_dummy); - BLI_assert(!free_dummy); - - /* Do not print warning in case of DummyRNA_NULL_items, this one will never match any value... */ - if (enum_item != DummyRNA_NULL_items) { - const char *ptr_name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL); - - /* prefer not fail silently in case of api errors, maybe disable it later */ - CLOG_WARN(BPY_LOG_RNA, - "current value '%d' " - "matches no enum in '%s', '%s', '%s'", - val, RNA_struct_identifier(ptr->type), - ptr_name, RNA_property_identifier(prop)); - -#if 0 /* gives python decoding errors while generating docs :( */ - char error_str[256]; - BLI_snprintf(error_str, sizeof(error_str), - "RNA Warning: Current value \"%d\" " - "matches no enum in '%s', '%s', '%s'", - val, RNA_struct_identifier(ptr->type), - ptr_name, RNA_property_identifier(prop)); - - PyErr_Warn(PyExc_RuntimeWarning, error_str); + PyObject *item, *ret = NULL; + + if (RNA_property_flag(prop) & PROP_ENUM_FLAG) { + const char *identifier[RNA_ENUM_BITFLAG_SIZE + 1]; + + ret = PySet_New(NULL); + + if (RNA_property_enum_bitflag_identifiers(BPy_GetContext(), ptr, prop, val, identifier)) { + int index; + + for (index = 0; identifier[index]; index++) { + item = PyUnicode_FromString(identifier[index]); + PySet_Add(ret, item); + Py_DECREF(item); + } + } + } + else { + const char *identifier; + if (RNA_property_enum_identifier(BPy_GetContext(), ptr, prop, val, &identifier)) { + ret = PyUnicode_FromString(identifier); + } + else { + /* Static, no need to free. */ + const EnumPropertyItem *enum_item; + bool free_dummy; + RNA_property_enum_items_ex(NULL, ptr, prop, true, &enum_item, NULL, &free_dummy); + BLI_assert(!free_dummy); + + /* Do not print warning in case of DummyRNA_NULL_items, this one will never match any value... */ + if (enum_item != DummyRNA_NULL_items) { + const char *ptr_name = RNA_struct_name_get_alloc(ptr, NULL, 0, NULL); + + /* prefer not fail silently in case of api errors, maybe disable it later */ + CLOG_WARN(BPY_LOG_RNA, + "current value '%d' " + "matches no enum in '%s', '%s', '%s'", + val, + RNA_struct_identifier(ptr->type), + ptr_name, + RNA_property_identifier(prop)); + +#if 0 /* gives python decoding errors while generating docs :( */ + char error_str[256]; + BLI_snprintf(error_str, sizeof(error_str), + "RNA Warning: Current value \"%d\" " + "matches no enum in '%s', '%s', '%s'", + val, RNA_struct_identifier(ptr->type), + ptr_name, RNA_property_identifier(prop)); + + PyErr_Warn(PyExc_RuntimeWarning, error_str); #endif - if (ptr_name) { - MEM_freeN((void *)ptr_name); - } - } + if (ptr_name) { + MEM_freeN((void *)ptr_name); + } + } - ret = PyUnicode_FromString(""); + ret = PyUnicode_FromString(""); #if 0 - PyErr_Format(PyExc_AttributeError, - "RNA Error: Current value \"%d\" matches no enum", val); - ret = NULL; + PyErr_Format(PyExc_AttributeError, + "RNA Error: Current value \"%d\" matches no enum", val); + ret = NULL; #endif - } - } + } + } - return ret; + return ret; } PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) { - PyObject *ret; - const int type = RNA_property_type(prop); - - if (RNA_property_array_check(prop)) { - return pyrna_py_from_array(ptr, prop); - } - - /* see if we can coerce into a python type - PropertyType */ - switch (type) { - case PROP_BOOLEAN: - ret = PyBool_FromLong(RNA_property_boolean_get(ptr, prop)); - break; - case PROP_INT: - ret = PyLong_FromLong(RNA_property_int_get(ptr, prop)); - break; - case PROP_FLOAT: - ret = PyFloat_FromDouble(RNA_property_float_get(ptr, prop)); - break; - case PROP_STRING: - { - const int subtype = RNA_property_subtype(prop); - const char *buf; - int buf_len; - char buf_fixed[32]; - - buf = RNA_property_string_get_alloc(ptr, prop, buf_fixed, sizeof(buf_fixed), &buf_len); + PyObject *ret; + const int type = RNA_property_type(prop); + + if (RNA_property_array_check(prop)) { + return pyrna_py_from_array(ptr, prop); + } + + /* see if we can coerce into a python type - PropertyType */ + switch (type) { + case PROP_BOOLEAN: + ret = PyBool_FromLong(RNA_property_boolean_get(ptr, prop)); + break; + case PROP_INT: + ret = PyLong_FromLong(RNA_property_int_get(ptr, prop)); + break; + case PROP_FLOAT: + ret = PyFloat_FromDouble(RNA_property_float_get(ptr, prop)); + break; + case PROP_STRING: { + const int subtype = RNA_property_subtype(prop); + const char *buf; + int buf_len; + char buf_fixed[32]; + + buf = RNA_property_string_get_alloc(ptr, prop, buf_fixed, sizeof(buf_fixed), &buf_len); #ifdef USE_STRING_COERCE - /* only file paths get special treatment, they may contain non utf-8 chars */ - if (subtype == PROP_BYTESTRING) { - ret = PyBytes_FromStringAndSize(buf, buf_len); - } - else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - ret = PyC_UnicodeFromByteAndSize(buf, buf_len); - } - else { - ret = PyUnicode_FromStringAndSize(buf, buf_len); - } + /* only file paths get special treatment, they may contain non utf-8 chars */ + if (subtype == PROP_BYTESTRING) { + ret = PyBytes_FromStringAndSize(buf, buf_len); + } + else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { + ret = PyC_UnicodeFromByteAndSize(buf, buf_len); + } + else { + ret = PyUnicode_FromStringAndSize(buf, buf_len); + } #else /* USE_STRING_COERCE */ - if (subtype == PROP_BYTESTRING) { - ret = PyBytes_FromStringAndSize(buf, buf_len); - } - else { - ret = PyUnicode_FromStringAndSize(buf, buf_len); - } -#endif /* USE_STRING_COERCE */ - if (buf_fixed != buf) { - MEM_freeN((void *)buf); - } - break; - } - case PROP_ENUM: - { - ret = pyrna_enum_to_py(ptr, prop, RNA_property_enum_get(ptr, prop)); - break; - } - case PROP_POINTER: - { - PointerRNA newptr; - newptr = RNA_property_pointer_get(ptr, prop); - if (newptr.data) { - ret = pyrna_struct_CreatePyObject(&newptr); - } - else { - ret = Py_None; - Py_INCREF(ret); - } - break; - } - case PROP_COLLECTION: - ret = pyrna_prop_CreatePyObject(ptr, prop); - break; - default: - PyErr_Format(PyExc_TypeError, - "bpy_struct internal error: unknown type '%d' (pyrna_prop_to_py)", type); - ret = NULL; - break; - } - - return ret; + if (subtype == PROP_BYTESTRING) { + ret = PyBytes_FromStringAndSize(buf, buf_len); + } + else { + ret = PyUnicode_FromStringAndSize(buf, buf_len); + } +#endif /* USE_STRING_COERCE */ + if (buf_fixed != buf) { + MEM_freeN((void *)buf); + } + break; + } + case PROP_ENUM: { + ret = pyrna_enum_to_py(ptr, prop, RNA_property_enum_get(ptr, prop)); + break; + } + case PROP_POINTER: { + PointerRNA newptr; + newptr = RNA_property_pointer_get(ptr, prop); + if (newptr.data) { + ret = pyrna_struct_CreatePyObject(&newptr); + } + else { + ret = Py_None; + Py_INCREF(ret); + } + break; + } + case PROP_COLLECTION: + ret = pyrna_prop_CreatePyObject(ptr, prop); + break; + default: + PyErr_Format(PyExc_TypeError, + "bpy_struct internal error: unknown type '%d' (pyrna_prop_to_py)", + type); + ret = NULL; + break; + } + + return ret; } /** * This function is used by operators and converting dicts into collections. * Its takes keyword args and fills them with property values */ -int pyrna_pydict_to_props( - PointerRNA *ptr, PyObject *kw, const bool all_args, - const char *error_prefix) -{ - int error_val = 0; - int totkw; - const char *arg_name = NULL; - PyObject *item; - - totkw = kw ? PyDict_Size(kw) : 0; - - RNA_STRUCT_BEGIN (ptr, prop) - { - arg_name = RNA_property_identifier(prop); - - if (STREQ(arg_name, "rna_type")) { - continue; - } - - if (kw == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s: no keywords, expected \"%.200s\"", - error_prefix, arg_name ? arg_name : "<UNKNOWN>"); - error_val = -1; - break; - } - - item = PyDict_GetItemString(kw, arg_name); /* wont set an error */ - - if (item == NULL) { - if (all_args) { - 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; - } - } - else { - if (pyrna_py_to_prop(ptr, prop, NULL, item, error_prefix)) { - error_val = -1; - break; - } - totkw--; - } - } - RNA_STRUCT_END; - - if (error_val == 0 && totkw > 0) { /* some keywords were given that were not used :/ */ - PyObject *key, *value; - Py_ssize_t pos = 0; - - while (PyDict_Next(kw, &pos, &key, &value)) { - arg_name = _PyUnicode_AsString(key); - if (RNA_struct_find_property(ptr, arg_name) == NULL) { - break; - } - arg_name = NULL; - } - - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" unrecognized", - error_prefix, arg_name ? arg_name : "<UNKNOWN>"); - error_val = -1; - } - - return error_val; +int pyrna_pydict_to_props(PointerRNA *ptr, + PyObject *kw, + const bool all_args, + const char *error_prefix) +{ + int error_val = 0; + int totkw; + const char *arg_name = NULL; + PyObject *item; + + totkw = kw ? PyDict_Size(kw) : 0; + + RNA_STRUCT_BEGIN (ptr, prop) { + arg_name = RNA_property_identifier(prop); + + if (STREQ(arg_name, "rna_type")) { + continue; + } + + if (kw == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s: no keywords, expected \"%.200s\"", + error_prefix, + arg_name ? arg_name : "<UNKNOWN>"); + error_val = -1; + break; + } + + item = PyDict_GetItemString(kw, arg_name); /* wont set an error */ + + if (item == NULL) { + if (all_args) { + 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; + } + } + else { + if (pyrna_py_to_prop(ptr, prop, NULL, item, error_prefix)) { + error_val = -1; + break; + } + totkw--; + } + } + RNA_STRUCT_END; + + if (error_val == 0 && totkw > 0) { /* some keywords were given that were not used :/ */ + PyObject *key, *value; + Py_ssize_t pos = 0; + + while (PyDict_Next(kw, &pos, &key, &value)) { + arg_name = _PyUnicode_AsString(key); + if (RNA_struct_find_property(ptr, arg_name) == NULL) { + break; + } + arg_name = NULL; + } + + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" unrecognized", + error_prefix, + arg_name ? arg_name : "<UNKNOWN>"); + error_val = -1; + } + + return error_val; } - static PyObject *pyrna_func_to_py(const PointerRNA *ptr, FunctionRNA *func) { - BPy_FunctionRNA *pyfunc = (BPy_FunctionRNA *) PyObject_NEW(BPy_FunctionRNA, &pyrna_func_Type); - pyfunc->ptr = *ptr; - pyfunc->func = func; - return (PyObject *)pyfunc; + BPy_FunctionRNA *pyfunc = (BPy_FunctionRNA *)PyObject_NEW(BPy_FunctionRNA, &pyrna_func_Type); + pyfunc->ptr = *ptr; + pyfunc->func = func; + return (PyObject *)pyfunc; } - static int pyrna_py_to_prop( - PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, - const char *error_prefix) -{ - /* XXX hard limits should be checked here */ - const int type = RNA_property_type(prop); - - - if (RNA_property_array_check(prop)) { - /* done getting the length */ - if (pyrna_py_to_array(ptr, prop, data, value, error_prefix) == -1) { - return -1; - } - } - else { - /* Normal Property (not an array) */ - - /* see if we can coerce into a python type - PropertyType */ - switch (type) { - case PROP_BOOLEAN: - { - int param; - /* prefer not to have an exception here - * however so many poll functions return None or a valid Object. - * its a hassle to convert these into a bool before returning, */ - if (RNA_parameter_flag(prop) & PARM_OUTPUT) { - param = PyObject_IsTrue(value); - } - else { - param = PyC_Long_AsI32(value); - - if (UNLIKELY(param & ~1)) { /* only accept 0/1 */ - param = -1; /* error out below */ - } - } - - if (param == -1) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected True/False or 0/1, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - return -1; - } - else { - if (data) { - *((bool *)data) = param; - } - else { - RNA_property_boolean_set(ptr, prop, param); - } - } - break; - } - case PROP_INT: - { - int overflow; - long param = PyLong_AsLongAndOverflow(value, &overflow); - if (overflow || (param > INT_MAX) || (param < INT_MIN)) { - PyErr_Format(PyExc_ValueError, - "%.200s %.200s.%.200s value not in 'int' range " - "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - return -1; - } - else if (param == -1 && PyErr_Occurred()) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected an int type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - return -1; - } - else { - int param_i = (int)param; - if (data) { - RNA_property_int_clamp(ptr, prop, ¶m_i); - *((int *)data) = param_i; - } - else { - RNA_property_int_set(ptr, prop, param_i); - } - } - break; - } - case PROP_FLOAT: - { - float param = PyFloat_AsDouble(value); - if (PyErr_Occurred()) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a float type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - return -1; - } - else { - if (data) { - RNA_property_float_clamp(ptr, prop, (float *)¶m); - *((float *)data) = param; - } - else { - RNA_property_float_set(ptr, prop, param); - } - } - break; - } - case PROP_STRING: - { - const int subtype = RNA_property_subtype(prop); - const char *param; - - if (value == Py_None) { - if ((RNA_property_flag(prop) & PROP_NEVER_NULL) == 0) { - if (data) { - *((char **)data) = (char *)NULL; - } - else { - RNA_property_string_set(ptr, prop, NULL); - } - } - else { - PyC_Err_Format_Prefix( - PyExc_TypeError, - "%.200s %.200s.%.200s doesn't support None from string types", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - return -1; - } - } - else if (subtype == PROP_BYTESTRING) { - - /* Byte String */ - - param = PyBytes_AsString(value); - - if (param == NULL) { - if (PyBytes_Check(value)) { - /* there was an error assigning a string type, - * rather than setting a new error, prefix the existing one - */ - PyC_Err_Format_Prefix(PyExc_TypeError, - "%.200s %.200s.%.200s error assigning bytes", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a bytes type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - } - - return -1; - } - else { - if (data) { - *((char **)data) = (char *)param; - } - else { - RNA_property_string_set_bytes(ptr, prop, param, PyBytes_Size(value)); - } - } - } - else { - /* Unicode String */ + PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix) +{ + /* XXX hard limits should be checked here */ + const int type = RNA_property_type(prop); + + if (RNA_property_array_check(prop)) { + /* done getting the length */ + if (pyrna_py_to_array(ptr, prop, data, value, error_prefix) == -1) { + return -1; + } + } + else { + /* Normal Property (not an array) */ + + /* see if we can coerce into a python type - PropertyType */ + switch (type) { + case PROP_BOOLEAN: { + int param; + /* prefer not to have an exception here + * however so many poll functions return None or a valid Object. + * its a hassle to convert these into a bool before returning, */ + if (RNA_parameter_flag(prop) & PARM_OUTPUT) { + param = PyObject_IsTrue(value); + } + else { + param = PyC_Long_AsI32(value); + + if (UNLIKELY(param & ~1)) { /* only accept 0/1 */ + param = -1; /* error out below */ + } + } + + if (param == -1) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected True/False or 0/1, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + return -1; + } + else { + if (data) { + *((bool *)data) = param; + } + else { + RNA_property_boolean_set(ptr, prop, param); + } + } + break; + } + case PROP_INT: { + int overflow; + long param = PyLong_AsLongAndOverflow(value, &overflow); + if (overflow || (param > INT_MAX) || (param < INT_MIN)) { + PyErr_Format(PyExc_ValueError, + "%.200s %.200s.%.200s value not in 'int' range " + "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + return -1; + } + else if (param == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected an int type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + return -1; + } + else { + int param_i = (int)param; + if (data) { + RNA_property_int_clamp(ptr, prop, ¶m_i); + *((int *)data) = param_i; + } + else { + RNA_property_int_set(ptr, prop, param_i); + } + } + break; + } + case PROP_FLOAT: { + float param = PyFloat_AsDouble(value); + if (PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a float type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + return -1; + } + else { + if (data) { + RNA_property_float_clamp(ptr, prop, (float *)¶m); + *((float *)data) = param; + } + else { + RNA_property_float_set(ptr, prop, param); + } + } + break; + } + case PROP_STRING: { + const int subtype = RNA_property_subtype(prop); + const char *param; + + if (value == Py_None) { + if ((RNA_property_flag(prop) & PROP_NEVER_NULL) == 0) { + if (data) { + *((char **)data) = (char *)NULL; + } + else { + RNA_property_string_set(ptr, prop, NULL); + } + } + else { + PyC_Err_Format_Prefix(PyExc_TypeError, + "%.200s %.200s.%.200s doesn't support None from string types", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + return -1; + } + } + else if (subtype == PROP_BYTESTRING) { + + /* Byte String */ + + param = PyBytes_AsString(value); + + if (param == NULL) { + if (PyBytes_Check(value)) { + /* there was an error assigning a string type, + * rather than setting a new error, prefix the existing one + */ + PyC_Err_Format_Prefix(PyExc_TypeError, + "%.200s %.200s.%.200s error assigning bytes", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a bytes type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + } + + return -1; + } + else { + if (data) { + *((char **)data) = (char *)param; + } + else { + RNA_property_string_set_bytes(ptr, prop, param, PyBytes_Size(value)); + } + } + } + else { + /* Unicode String */ #ifdef USE_STRING_COERCE - PyObject *value_coerce = NULL; - if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - /* TODO, get size */ - param = PyC_UnicodeAsByte(value, &value_coerce); - } - else { - param = _PyUnicode_AsString(value); - } + PyObject *value_coerce = NULL; + if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { + /* TODO, get size */ + param = PyC_UnicodeAsByte(value, &value_coerce); + } + else { + param = _PyUnicode_AsString(value); + } #else /* USE_STRING_COERCE */ - param = _PyUnicode_AsString(value); -#endif /* USE_STRING_COERCE */ - - if (param == NULL) { - if (PyUnicode_Check(value)) { - /* there was an error assigning a string type, - * rather than setting a new error, prefix the existing one - */ - PyC_Err_Format_Prefix(PyExc_TypeError, - "%.200s %.200s.%.200s error assigning string", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a string type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - } - - return -1; - } - else { - /* same as bytes */ - /* XXX, this is suspect but needed for function calls, need to see if theres a better way */ - if (data) { - *((char **)data) = (char *)param; - } - else { - RNA_property_string_set(ptr, prop, param); - } - } + param = _PyUnicode_AsString(value); +#endif /* USE_STRING_COERCE */ + + if (param == NULL) { + if (PyUnicode_Check(value)) { + /* there was an error assigning a string type, + * rather than setting a new error, prefix the existing one + */ + PyC_Err_Format_Prefix(PyExc_TypeError, + "%.200s %.200s.%.200s error assigning string", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a string type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + } + + return -1; + } + else { + /* same as bytes */ + /* XXX, this is suspect but needed for function calls, need to see if theres a better way */ + if (data) { + *((char **)data) = (char *)param; + } + else { + RNA_property_string_set(ptr, prop, param); + } + } #ifdef USE_STRING_COERCE - Py_XDECREF(value_coerce); -#endif /* USE_STRING_COERCE */ - } - break; - } - case PROP_ENUM: - { - int val = 0; - - /* type checkins is done by each function */ - if (RNA_property_flag(prop) & PROP_ENUM_FLAG) { - /* set of enum items, concatenate all values with OR */ - if (pyrna_prop_to_enum_bitfield(ptr, prop, value, &val, error_prefix) == -1) { - return -1; - } - } - else { - /* simple enum string */ - if (pyrna_string_to_enum(value, ptr, prop, &val, error_prefix) == -1) { - return -1; - } - } - - if (data) { - *((int *)data) = val; - } - else { - RNA_property_enum_set(ptr, prop, val); - } - - break; - } - case PROP_POINTER: - { - PyObject *value_new = NULL; - - StructRNA *ptr_type = RNA_property_pointer_type(ptr, prop); - int flag = RNA_property_flag(prop); - int flag_parameter = RNA_parameter_flag(prop); - - /* this is really nasty!, so we can fake the operator having direct properties eg: - * layout.prop(self, "filepath") - * ... which in fact should be - * layout.prop(self.properties, "filepath") - * - * we need to do this trick. - * if the prop is not an operator type and the pyobject is an operator, - * use its properties in place of its self. - * - * this is so bad that its almost a good reason to do away with fake 'self.properties -> self' - * class mixing if this causes problems in the future it should be removed. - */ - if ((ptr_type == &RNA_AnyType) && - (BPy_StructRNA_Check(value))) - { - const StructRNA *base_type = - RNA_struct_base_child_of(((const BPy_StructRNA *)value)->ptr.type, NULL); - if (ELEM(base_type, &RNA_Operator, &RNA_Gizmo)) { - value = PyObject_GetAttr(value, bpy_intern_str_properties); - value_new = value; - } - } - - /* if property is an OperatorProperties/GizmoProperties pointer and value is a map, - * forward back to pyrna_pydict_to_props */ - if (PyDict_Check(value)) { - const StructRNA *base_type = RNA_struct_base_child_of(ptr_type, NULL); - if (base_type == &RNA_OperatorProperties) { - PointerRNA opptr = RNA_property_pointer_get(ptr, prop); - return pyrna_pydict_to_props(&opptr, value, false, error_prefix); - } - else if (base_type == &RNA_GizmoProperties) { - PointerRNA opptr = RNA_property_pointer_get(ptr, prop); - return pyrna_pydict_to_props(&opptr, value, false, error_prefix); - } - } - - /* another exception, allow to pass a collection as an RNA property */ - if (Py_TYPE(value) == &pyrna_prop_collection_Type) { /* ok to ignore idprop collections */ - PointerRNA c_ptr; - BPy_PropertyRNA *value_prop = (BPy_PropertyRNA *)value; - if (RNA_property_collection_type_get(&value_prop->ptr, value_prop->prop, &c_ptr)) { - value = pyrna_struct_CreatePyObject(&c_ptr); - value_new = value; - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s collection has no type, " - "cant be used as a %.200s type", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), RNA_struct_identifier(ptr_type)); - return -1; - } - } - - if (!BPy_StructRNA_Check(value) && value != Py_None) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a %.200s type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), RNA_struct_identifier(ptr_type), - Py_TYPE(value)->tp_name); - Py_XDECREF(value_new); return -1; - } - else if ((flag & PROP_NEVER_NULL) && value == Py_None) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s does not support a 'None' assignment %.200s type", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), RNA_struct_identifier(ptr_type)); - Py_XDECREF(value_new); return -1; - } - else if ((value != Py_None) && - ((flag & PROP_ID_SELF_CHECK) && ptr->id.data == ((BPy_StructRNA *)value)->ptr.id.data)) - { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s ID type does not support assignment to its self", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - Py_XDECREF(value_new); return -1; - } - else { - BPy_StructRNA *param = (BPy_StructRNA *)value; - bool raise_error = false; - if (data) { - - if (flag_parameter & PARM_RNAPTR) { - if (flag & PROP_THICK_WRAP) { - if (value == Py_None) { - memset(data, 0, sizeof(PointerRNA)); - } - else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { - *((PointerRNA *)data) = param->ptr; - } - else { - raise_error = true; - } - } - else { - /* for function calls, we sometimes want to pass the 'ptr' directly, - * watch out that it remains valid!, possibly we could support this later if needed */ - BLI_assert(value_new == NULL); - if (value == Py_None) { - *((void **)data) = NULL; - } - else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { - *((PointerRNA **)data) = ¶m->ptr; - } - else { - raise_error = true; - } - } - } - else if (value == Py_None) { - *((void **)data) = NULL; - } - else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { - *((void **)data) = param->ptr.data; - } - else { - raise_error = true; - } - } - else { - /* data == NULL, assign to RNA */ - if (value == Py_None || RNA_struct_is_a(param->ptr.type, ptr_type)) { - RNA_property_pointer_set(ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr); - } - else { - raise_error = true; - } - } - - if (raise_error) { - if (pyrna_struct_validity_check(param) == -1) { - /* error set */ - } - else { - PointerRNA tmp; - RNA_pointer_create(NULL, ptr_type, NULL, &tmp); - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a %.200s type, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), RNA_struct_identifier(tmp.type), - RNA_struct_identifier(param->ptr.type)); - } - Py_XDECREF(value_new); return -1; - } - } - - Py_XDECREF(value_new); - - break; - } - case PROP_COLLECTION: - { - Py_ssize_t seq_len, i; - PyObject *item; - PointerRNA itemptr; - ListBase *lb; - CollectionPointerLink *link; - - lb = (data) ? (ListBase *)data : NULL; - - /* convert a sequence of dict's into a collection */ - if (!PySequence_Check(value)) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a sequence for an RNA collection, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(value)->tp_name); - return -1; - } - - seq_len = PySequence_Size(value); - for (i = 0; i < seq_len; i++) { - item = PySequence_GetItem(value, i); - - if (item == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s failed to get sequence index '%d' for an RNA collection", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), i); - Py_XDECREF(item); - return -1; - } - - if (PyDict_Check(item) == 0) { - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s expected a each sequence " - "member to be a dict for an RNA collection, not %.200s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), Py_TYPE(item)->tp_name); - Py_XDECREF(item); - return -1; - } - - if (lb) { - link = MEM_callocN(sizeof(CollectionPointerLink), "PyCollectionPointerLink"); - link->ptr = itemptr; - BLI_addtail(lb, link); - } - else { - RNA_property_collection_add(ptr, prop, &itemptr); - } - - if (pyrna_pydict_to_props( - &itemptr, item, true, - "Converting a python list to an RNA collection") == -1) - { - PyObject *msg = PyC_ExceptionBuffer(); - const char *msg_char = _PyUnicode_AsString(msg); - - PyErr_Format(PyExc_TypeError, - "%.200s %.200s.%.200s error converting a member of a collection " - "from a dicts into an RNA collection, failed with: %s", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop), msg_char); - - Py_DECREF(item); - Py_DECREF(msg); - return -1; - } - Py_DECREF(item); - } - - break; - } - default: - PyErr_Format(PyExc_AttributeError, - "%.200s %.200s.%.200s unknown property type (pyrna_py_to_prop)", - error_prefix, RNA_struct_identifier(ptr->type), - RNA_property_identifier(prop)); - return -1; - } - } - - /* Run rna property functions */ - if (RNA_property_update_check(prop)) { - RNA_property_update(BPy_GetContext(), ptr, prop); - } - - return 0; + Py_XDECREF(value_coerce); +#endif /* USE_STRING_COERCE */ + } + break; + } + case PROP_ENUM: { + int val = 0; + + /* type checkins is done by each function */ + if (RNA_property_flag(prop) & PROP_ENUM_FLAG) { + /* set of enum items, concatenate all values with OR */ + if (pyrna_prop_to_enum_bitfield(ptr, prop, value, &val, error_prefix) == -1) { + return -1; + } + } + else { + /* simple enum string */ + if (pyrna_string_to_enum(value, ptr, prop, &val, error_prefix) == -1) { + return -1; + } + } + + if (data) { + *((int *)data) = val; + } + else { + RNA_property_enum_set(ptr, prop, val); + } + + break; + } + case PROP_POINTER: { + PyObject *value_new = NULL; + + StructRNA *ptr_type = RNA_property_pointer_type(ptr, prop); + int flag = RNA_property_flag(prop); + int flag_parameter = RNA_parameter_flag(prop); + + /* this is really nasty!, so we can fake the operator having direct properties eg: + * layout.prop(self, "filepath") + * ... which in fact should be + * layout.prop(self.properties, "filepath") + * + * we need to do this trick. + * if the prop is not an operator type and the pyobject is an operator, + * use its properties in place of its self. + * + * this is so bad that its almost a good reason to do away with fake 'self.properties -> self' + * class mixing if this causes problems in the future it should be removed. + */ + if ((ptr_type == &RNA_AnyType) && (BPy_StructRNA_Check(value))) { + const StructRNA *base_type = RNA_struct_base_child_of( + ((const BPy_StructRNA *)value)->ptr.type, NULL); + if (ELEM(base_type, &RNA_Operator, &RNA_Gizmo)) { + value = PyObject_GetAttr(value, bpy_intern_str_properties); + value_new = value; + } + } + + /* if property is an OperatorProperties/GizmoProperties pointer and value is a map, + * forward back to pyrna_pydict_to_props */ + if (PyDict_Check(value)) { + const StructRNA *base_type = RNA_struct_base_child_of(ptr_type, NULL); + if (base_type == &RNA_OperatorProperties) { + PointerRNA opptr = RNA_property_pointer_get(ptr, prop); + return pyrna_pydict_to_props(&opptr, value, false, error_prefix); + } + else if (base_type == &RNA_GizmoProperties) { + PointerRNA opptr = RNA_property_pointer_get(ptr, prop); + return pyrna_pydict_to_props(&opptr, value, false, error_prefix); + } + } + + /* another exception, allow to pass a collection as an RNA property */ + if (Py_TYPE(value) == &pyrna_prop_collection_Type) { /* ok to ignore idprop collections */ + PointerRNA c_ptr; + BPy_PropertyRNA *value_prop = (BPy_PropertyRNA *)value; + if (RNA_property_collection_type_get(&value_prop->ptr, value_prop->prop, &c_ptr)) { + value = pyrna_struct_CreatePyObject(&c_ptr); + value_new = value; + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s collection has no type, " + "cant be used as a %.200s type", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + RNA_struct_identifier(ptr_type)); + return -1; + } + } + + if (!BPy_StructRNA_Check(value) && value != Py_None) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a %.200s type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + RNA_struct_identifier(ptr_type), + Py_TYPE(value)->tp_name); + Py_XDECREF(value_new); + return -1; + } + else if ((flag & PROP_NEVER_NULL) && value == Py_None) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s does not support a 'None' assignment %.200s type", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + RNA_struct_identifier(ptr_type)); + Py_XDECREF(value_new); + return -1; + } + else if ((value != Py_None) && ((flag & PROP_ID_SELF_CHECK) && + ptr->id.data == ((BPy_StructRNA *)value)->ptr.id.data)) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s ID type does not support assignment to its self", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + Py_XDECREF(value_new); + return -1; + } + else { + BPy_StructRNA *param = (BPy_StructRNA *)value; + bool raise_error = false; + if (data) { + + if (flag_parameter & PARM_RNAPTR) { + if (flag & PROP_THICK_WRAP) { + if (value == Py_None) { + memset(data, 0, sizeof(PointerRNA)); + } + else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { + *((PointerRNA *)data) = param->ptr; + } + else { + raise_error = true; + } + } + else { + /* for function calls, we sometimes want to pass the 'ptr' directly, + * watch out that it remains valid!, possibly we could support this later if needed */ + BLI_assert(value_new == NULL); + if (value == Py_None) { + *((void **)data) = NULL; + } + else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { + *((PointerRNA **)data) = ¶m->ptr; + } + else { + raise_error = true; + } + } + } + else if (value == Py_None) { + *((void **)data) = NULL; + } + else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { + *((void **)data) = param->ptr.data; + } + else { + raise_error = true; + } + } + else { + /* data == NULL, assign to RNA */ + if (value == Py_None || RNA_struct_is_a(param->ptr.type, ptr_type)) { + RNA_property_pointer_set(ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr); + } + else { + raise_error = true; + } + } + + if (raise_error) { + if (pyrna_struct_validity_check(param) == -1) { + /* error set */ + } + else { + PointerRNA tmp; + RNA_pointer_create(NULL, ptr_type, NULL, &tmp); + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a %.200s type, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + RNA_struct_identifier(tmp.type), + RNA_struct_identifier(param->ptr.type)); + } + Py_XDECREF(value_new); + return -1; + } + } + + Py_XDECREF(value_new); + + break; + } + case PROP_COLLECTION: { + Py_ssize_t seq_len, i; + PyObject *item; + PointerRNA itemptr; + ListBase *lb; + CollectionPointerLink *link; + + lb = (data) ? (ListBase *)data : NULL; + + /* convert a sequence of dict's into a collection */ + if (!PySequence_Check(value)) { + PyErr_Format( + PyExc_TypeError, + "%.200s %.200s.%.200s expected a sequence for an RNA collection, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(value)->tp_name); + return -1; + } + + seq_len = PySequence_Size(value); + for (i = 0; i < seq_len; i++) { + item = PySequence_GetItem(value, i); + + if (item == NULL) { + PyErr_Format( + PyExc_TypeError, + "%.200s %.200s.%.200s failed to get sequence index '%d' for an RNA collection", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + i); + Py_XDECREF(item); + return -1; + } + + if (PyDict_Check(item) == 0) { + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s expected a each sequence " + "member to be a dict for an RNA collection, not %.200s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + Py_TYPE(item)->tp_name); + Py_XDECREF(item); + return -1; + } + + if (lb) { + link = MEM_callocN(sizeof(CollectionPointerLink), "PyCollectionPointerLink"); + link->ptr = itemptr; + BLI_addtail(lb, link); + } + else { + RNA_property_collection_add(ptr, prop, &itemptr); + } + + if (pyrna_pydict_to_props( + &itemptr, item, true, "Converting a python list to an RNA collection") == -1) { + PyObject *msg = PyC_ExceptionBuffer(); + const char *msg_char = _PyUnicode_AsString(msg); + + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s error converting a member of a collection " + "from a dicts into an RNA collection, failed with: %s", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop), + msg_char); + + Py_DECREF(item); + Py_DECREF(msg); + return -1; + } + Py_DECREF(item); + } + + break; + } + default: + PyErr_Format(PyExc_AttributeError, + "%.200s %.200s.%.200s unknown property type (pyrna_py_to_prop)", + error_prefix, + RNA_struct_identifier(ptr->type), + RNA_property_identifier(prop)); + return -1; + } + } + + /* Run rna property functions */ + if (RNA_property_update_check(prop)) { + RNA_property_update(BPy_GetContext(), ptr, prop); + } + + return 0; } static PyObject *pyrna_prop_array_to_py_index(BPy_PropertyArrayRNA *self, int index) { - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); - return pyrna_py_from_array_index(self, &self->ptr, self->prop, index); + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); + return pyrna_py_from_array_index(self, &self->ptr, self->prop, index); } static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, PyObject *value) { - int ret = 0; - PointerRNA *ptr = &self->ptr; - PropertyRNA *prop = self->prop; - - const int totdim = RNA_property_array_dimension(ptr, prop, NULL); - - if (totdim > 1) { - /* char error_str[512]; */ - if (pyrna_py_to_array_index(&self->ptr, self->prop, self->arraydim, self->arrayoffset, index, value, "") == -1) { - /* error is set */ - ret = -1; - } - } - else { - /* see if we can coerce into a python type - PropertyType */ - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - { - int param = PyC_Long_AsBool(value); - - if (param == -1) { - /* error is set */ - ret = -1; - } - else { - RNA_property_boolean_set_index(ptr, prop, index, param); - } - break; - } - case PROP_INT: - { - int param = PyC_Long_AsI32(value); - if (param == -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected an int type"); - ret = -1; - } - else { - RNA_property_int_clamp(ptr, prop, ¶m); - RNA_property_int_set_index(ptr, prop, index, param); - } - break; - } - case PROP_FLOAT: - { - float param = PyFloat_AsDouble(value); - if (PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected a float type"); - ret = -1; - } - else { - RNA_property_float_clamp(ptr, prop, ¶m); - RNA_property_float_set_index(ptr, prop, index, param); - } - break; - } - default: - PyErr_SetString(PyExc_AttributeError, "not an array type"); - ret = -1; - break; - } - } - - /* Run rna property functions */ - if (RNA_property_update_check(prop)) { - RNA_property_update(BPy_GetContext(), ptr, prop); - } - - return ret; + int ret = 0; + PointerRNA *ptr = &self->ptr; + PropertyRNA *prop = self->prop; + + const int totdim = RNA_property_array_dimension(ptr, prop, NULL); + + if (totdim > 1) { + /* char error_str[512]; */ + if (pyrna_py_to_array_index( + &self->ptr, self->prop, self->arraydim, self->arrayoffset, index, value, "") == -1) { + /* error is set */ + ret = -1; + } + } + else { + /* see if we can coerce into a python type - PropertyType */ + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: { + int param = PyC_Long_AsBool(value); + + if (param == -1) { + /* error is set */ + ret = -1; + } + else { + RNA_property_boolean_set_index(ptr, prop, index, param); + } + break; + } + case PROP_INT: { + int param = PyC_Long_AsI32(value); + if (param == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected an int type"); + ret = -1; + } + else { + RNA_property_int_clamp(ptr, prop, ¶m); + RNA_property_int_set_index(ptr, prop, index, param); + } + break; + } + case PROP_FLOAT: { + float param = PyFloat_AsDouble(value); + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected a float type"); + ret = -1; + } + else { + RNA_property_float_clamp(ptr, prop, ¶m); + RNA_property_float_set_index(ptr, prop, index, param); + } + break; + } + default: + PyErr_SetString(PyExc_AttributeError, "not an array type"); + ret = -1; + break; + } + } + + /* Run rna property functions */ + if (RNA_property_update_check(prop)) { + RNA_property_update(BPy_GetContext(), ptr, prop); + } + + return ret; } /* ---------------sequence------------------------------------------- */ static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self) { - PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); + PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); - if (RNA_property_array_dimension(&self->ptr, self->prop, NULL) > 1) { - return RNA_property_multi_array_length(&self->ptr, self->prop, self->arraydim); - } - else { - return RNA_property_array_length(&self->ptr, self->prop); - } + if (RNA_property_array_dimension(&self->ptr, self->prop, NULL) > 1) { + return RNA_property_multi_array_length(&self->ptr, self->prop, self->arraydim); + } + else { + return RNA_property_array_length(&self->ptr, self->prop); + } } static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self) { - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - return RNA_property_collection_length(&self->ptr, self->prop); + return RNA_property_collection_length(&self->ptr, self->prop); } /* bool functions are for speed, so we can avoid getting the length * of 1000's of items in a linked list for eg. */ static int pyrna_prop_array_bool(BPy_PropertyRNA *self) { - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - return RNA_property_array_length(&self->ptr, self->prop) ? 1 : 0; + return RNA_property_array_length(&self->ptr, self->prop) ? 1 : 0; } static int pyrna_prop_collection_bool(BPy_PropertyRNA *self) { - /* no callback defined, just iterate and find the nth item */ - CollectionPropertyIterator iter; - int test; + /* no callback defined, just iterate and find the nth item */ + CollectionPropertyIterator iter; + int test; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - RNA_property_collection_begin(&self->ptr, self->prop, &iter); - test = iter.valid; - RNA_property_collection_end(&iter); - return test; + RNA_property_collection_begin(&self->ptr, self->prop, &iter); + test = iter.valid; + RNA_property_collection_end(&iter); + return test; } - /* notice getting the length of the collection is avoided unless negative * index is used or to detect internal error with a valid index. * This is done for faster lookups. */ -#define PYRNA_PROP_COLLECTION_ABS_INDEX(ret_err) \ - if (keynum < 0) { \ - keynum_abs += RNA_property_collection_length(&self->ptr, self->prop); \ - if (keynum_abs < 0) { \ - PyErr_Format(PyExc_IndexError, \ - "bpy_prop_collection[%d]: out of range.", keynum); \ - return ret_err; \ - } \ - } (void)0 - +#define PYRNA_PROP_COLLECTION_ABS_INDEX(ret_err) \ + if (keynum < 0) { \ + keynum_abs += RNA_property_collection_length(&self->ptr, self->prop); \ + if (keynum_abs < 0) { \ + PyErr_Format(PyExc_IndexError, "bpy_prop_collection[%d]: out of range.", keynum); \ + return ret_err; \ + } \ + } \ + (void)0 /* internal use only */ static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum) { - PointerRNA newptr; - Py_ssize_t keynum_abs = keynum; - - PYRNA_PROP_CHECK_OBJ(self); - - PYRNA_PROP_COLLECTION_ABS_INDEX(NULL); - - if (RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum_abs, &newptr)) { - return pyrna_struct_CreatePyObject(&newptr); - } - else { - const int len = RNA_property_collection_length(&self->ptr, self->prop); - if (keynum_abs >= len) { - PyErr_Format(PyExc_IndexError, - "bpy_prop_collection[index]: " - "index %d out of range, size %d", keynum, len); - } - else { - PyErr_Format(PyExc_RuntimeError, - "bpy_prop_collection[index]: internal error, " - "valid index %d given in %d sized collection but value not found", - keynum_abs, len); - } - - return NULL; - } + PointerRNA newptr; + Py_ssize_t keynum_abs = keynum; + + PYRNA_PROP_CHECK_OBJ(self); + + PYRNA_PROP_COLLECTION_ABS_INDEX(NULL); + + if (RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum_abs, &newptr)) { + return pyrna_struct_CreatePyObject(&newptr); + } + else { + const int len = RNA_property_collection_length(&self->ptr, self->prop); + if (keynum_abs >= len) { + PyErr_Format(PyExc_IndexError, + "bpy_prop_collection[index]: " + "index %d out of range, size %d", + keynum, + len); + } + else { + PyErr_Format(PyExc_RuntimeError, + "bpy_prop_collection[index]: internal error, " + "valid index %d given in %d sized collection but value not found", + keynum_abs, + len); + } + + return NULL; + } } /* values type must have been already checked */ -static int pyrna_prop_collection_ass_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum, PyObject *value) +static int pyrna_prop_collection_ass_subscript_int(BPy_PropertyRNA *self, + Py_ssize_t keynum, + PyObject *value) { - Py_ssize_t keynum_abs = keynum; - const PointerRNA *ptr = (value == Py_None) ? (&PointerRNA_NULL) : &((BPy_StructRNA *)value)->ptr; + Py_ssize_t keynum_abs = keynum; + const PointerRNA *ptr = (value == Py_None) ? (&PointerRNA_NULL) : &((BPy_StructRNA *)value)->ptr; - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - PYRNA_PROP_COLLECTION_ABS_INDEX(-1); + PYRNA_PROP_COLLECTION_ABS_INDEX(-1); - if (RNA_property_collection_assign_int(&self->ptr, self->prop, keynum_abs, ptr) == 0) { - const int len = RNA_property_collection_length(&self->ptr, self->prop); - if (keynum_abs >= len) { - PyErr_Format(PyExc_IndexError, - "bpy_prop_collection[index] = value: " - "index %d out of range, size %d", keynum, len); - } - else { + if (RNA_property_collection_assign_int(&self->ptr, self->prop, keynum_abs, ptr) == 0) { + const int len = RNA_property_collection_length(&self->ptr, self->prop); + if (keynum_abs >= len) { + PyErr_Format(PyExc_IndexError, + "bpy_prop_collection[index] = value: " + "index %d out of range, size %d", + keynum, + len); + } + else { - PyErr_Format(PyExc_IndexError, - "bpy_prop_collection[index] = value: " - "failed assignment (unknown reason)", keynum); - } - return -1; - } + PyErr_Format(PyExc_IndexError, + "bpy_prop_collection[index] = value: " + "failed assignment (unknown reason)", + keynum); + } + return -1; + } - return 0; + return 0; } static PyObject *pyrna_prop_array_subscript_int(BPy_PropertyArrayRNA *self, int keynum) { - int len; + int len; - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); - len = pyrna_prop_array_length(self); + len = pyrna_prop_array_length(self); - if (keynum < 0) { - keynum += len; - } + if (keynum < 0) { + keynum += len; + } - if (keynum >= 0 && keynum < len) { - return pyrna_prop_array_to_py_index(self, keynum); - } + if (keynum >= 0 && keynum < len) { + return pyrna_prop_array_to_py_index(self, keynum); + } - PyErr_Format(PyExc_IndexError, - "bpy_prop_array[index]: index %d out of range", keynum); - return NULL; + PyErr_Format(PyExc_IndexError, "bpy_prop_array[index]: index %d out of range", keynum); + return NULL; } static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, const char *keyname) { - PointerRNA newptr; + PointerRNA newptr; - PYRNA_PROP_CHECK_OBJ(self); + PYRNA_PROP_CHECK_OBJ(self); - if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) { - return pyrna_struct_CreatePyObject(&newptr); - } + if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) { + return pyrna_struct_CreatePyObject(&newptr); + } - PyErr_Format(PyExc_KeyError, "bpy_prop_collection[key]: key \"%.200s\" not found", keyname); - return NULL; + PyErr_Format(PyExc_KeyError, "bpy_prop_collection[key]: key \"%.200s\" not found", keyname); + return NULL; } /* static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) */ @@ -2363,482 +2397,498 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons * - 0: not found * - 1: found */ -static int pyrna_prop_collection_subscript_str_lib_pair_ptr( - BPy_PropertyRNA *self, PyObject *key, - const char *err_prefix, const short err_not_found, - PointerRNA *r_ptr) -{ - const 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 -1; - } - 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 -1; - } - 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 -1; - } - else { - PyObject *keylib = PyTuple_GET_ITEM(key, 1); - Library *lib; - bool found = false; - - 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->libraries, 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 -1; - } - else { - return 0; - } - - } - } - else { - PyErr_Format(PyExc_KeyError, - "%s: lib must be a string or None, not %.200s", - err_prefix, Py_TYPE(keylib)->tp_name); - return -1; - } - - /* lib is either a valid pointer 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 && (STREQLEN(keyname, id->name + 2, sizeof(id->name) - 2))) { - found = true; - if (r_ptr) { - *r_ptr = itemptr; - } - break; - } - } - RNA_PROP_END; - - /* we may want to fail silently as with collection.get() */ - if ((found == false) && err_not_found) { - /* only runs for getitem access so use fixed string */ - PyErr_SetString(PyExc_KeyError, - "bpy_prop_collection[key, lib]: not found"); - return -1; - } - else { - return found; /* 1 / 0, no exception */ - } - } -} - -static PyObject *pyrna_prop_collection_subscript_str_lib_pair( - BPy_PropertyRNA *self, PyObject *key, - const char *err_prefix, const bool err_not_found) -{ - PointerRNA ptr; - const int contains = pyrna_prop_collection_subscript_str_lib_pair_ptr(self, key, err_prefix, err_not_found, &ptr); - - if (contains == 1) { - return pyrna_struct_CreatePyObject(&ptr); - } - else { - return NULL; - } -} - - -static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py_ssize_t start, Py_ssize_t stop) -{ - CollectionPropertyIterator rna_macro_iter; - int count; - - PyObject *list; - PyObject *item; - - PYRNA_PROP_CHECK_OBJ(self); - - list = PyList_New(0); - - /* skip to start */ - RNA_property_collection_begin(&self->ptr, self->prop, &rna_macro_iter); - RNA_property_collection_skip(&rna_macro_iter, start); - - /* add items until stop */ - for (count = start; rna_macro_iter.valid; - RNA_property_collection_next(&rna_macro_iter)) - { - item = pyrna_struct_CreatePyObject(&rna_macro_iter.ptr); - PyList_APPEND(list, item); - - count++; - if (count == stop) { - break; - } - } - - RNA_property_collection_end(&rna_macro_iter); - - return list; +static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *self, + PyObject *key, + const char *err_prefix, + const short err_not_found, + PointerRNA *r_ptr) +{ + const 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 -1; + } + 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 -1; + } + 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 -1; + } + else { + PyObject *keylib = PyTuple_GET_ITEM(key, 1); + Library *lib; + bool found = false; + + 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->libraries, 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 -1; + } + else { + return 0; + } + } + } + else { + PyErr_Format(PyExc_KeyError, + "%s: lib must be a string or None, not %.200s", + err_prefix, + Py_TYPE(keylib)->tp_name); + return -1; + } + + /* lib is either a valid pointer 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 && (STREQLEN(keyname, id->name + 2, sizeof(id->name) - 2))) { + found = true; + if (r_ptr) { + *r_ptr = itemptr; + } + break; + } + } + RNA_PROP_END; + + /* we may want to fail silently as with collection.get() */ + if ((found == false) && err_not_found) { + /* only runs for getitem access so use fixed string */ + PyErr_SetString(PyExc_KeyError, "bpy_prop_collection[key, lib]: not found"); + return -1; + } + else { + return found; /* 1 / 0, no exception */ + } + } +} + +static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *self, + PyObject *key, + const char *err_prefix, + const bool err_not_found) +{ + PointerRNA ptr; + const int contains = pyrna_prop_collection_subscript_str_lib_pair_ptr( + self, key, err_prefix, err_not_found, &ptr); + + if (contains == 1) { + return pyrna_struct_CreatePyObject(&ptr); + } + else { + return NULL; + } +} + +static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, + Py_ssize_t start, + Py_ssize_t stop) +{ + CollectionPropertyIterator rna_macro_iter; + int count; + + PyObject *list; + PyObject *item; + + PYRNA_PROP_CHECK_OBJ(self); + + list = PyList_New(0); + + /* skip to start */ + RNA_property_collection_begin(&self->ptr, self->prop, &rna_macro_iter); + RNA_property_collection_skip(&rna_macro_iter, start); + + /* add items until stop */ + for (count = start; rna_macro_iter.valid; RNA_property_collection_next(&rna_macro_iter)) { + item = pyrna_struct_CreatePyObject(&rna_macro_iter.ptr); + PyList_APPEND(list, item); + + count++; + if (count == stop) { + break; + } + } + + RNA_property_collection_end(&rna_macro_iter); + + return list; } /* TODO - dimensions * note: could also use pyrna_prop_array_to_py_index(self, count) in a loop but its a lot slower * since at the moment it reads (and even allocates) the entire array for each index. */ -static PyObject *pyrna_prop_array_subscript_slice( - BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, - Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length) -{ - int count, totdim; - PyObject *tuple; - - /* isn't needed, internal use only */ - // PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); - - tuple = PyTuple_New(stop - start); - - totdim = RNA_property_array_dimension(ptr, prop, NULL); - - if (totdim > 1) { - for (count = start; count < stop; count++) { - PyTuple_SET_ITEM(tuple, count - start, pyrna_prop_array_to_py_index(self, count)); - } - } - else { - switch (RNA_property_type(prop)) { - case PROP_FLOAT: - { - float values_stack[PYRNA_STACK_ARRAY]; - float *values; - if (length > PYRNA_STACK_ARRAY) { values = PyMem_MALLOC(sizeof(float) * length); } - else { values = values_stack; } - RNA_property_float_get_array(ptr, prop, values); - - for (count = start; count < stop; count++) { - PyTuple_SET_ITEM(tuple, count - start, PyFloat_FromDouble(values[count])); - } - - if (values != values_stack) { - PyMem_FREE(values); - } - break; - } - case PROP_BOOLEAN: - { - bool values_stack[PYRNA_STACK_ARRAY]; - bool *values; - if (length > PYRNA_STACK_ARRAY) { values = PyMem_MALLOC(sizeof(bool) * length); } - else { values = values_stack; } - - RNA_property_boolean_get_array(ptr, prop, values); - for (count = start; count < stop; count++) { - PyTuple_SET_ITEM(tuple, count - start, PyBool_FromLong(values[count])); - } - - if (values != values_stack) { - PyMem_FREE(values); - } - break; - } - case PROP_INT: - { - int values_stack[PYRNA_STACK_ARRAY]; - int *values; - if (length > PYRNA_STACK_ARRAY) { values = PyMem_MALLOC(sizeof(int) * length); } - else { values = values_stack; } - - RNA_property_int_get_array(ptr, prop, values); - for (count = start; count < stop; count++) { - PyTuple_SET_ITEM(tuple, count - start, PyLong_FromLong(values[count])); - } - - if (values != values_stack) { - PyMem_FREE(values); - } - break; - } - default: - BLI_assert(!"Invalid array type"); - - PyErr_SetString(PyExc_TypeError, "not an array type"); - Py_DECREF(tuple); - tuple = NULL; - break; - } - } - return tuple; +static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, + PointerRNA *ptr, + PropertyRNA *prop, + Py_ssize_t start, + Py_ssize_t stop, + Py_ssize_t length) +{ + int count, totdim; + PyObject *tuple; + + /* isn't needed, internal use only */ + // PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); + + tuple = PyTuple_New(stop - start); + + totdim = RNA_property_array_dimension(ptr, prop, NULL); + + if (totdim > 1) { + for (count = start; count < stop; count++) { + PyTuple_SET_ITEM(tuple, count - start, pyrna_prop_array_to_py_index(self, count)); + } + } + else { + switch (RNA_property_type(prop)) { + case PROP_FLOAT: { + float values_stack[PYRNA_STACK_ARRAY]; + float *values; + if (length > PYRNA_STACK_ARRAY) { + values = PyMem_MALLOC(sizeof(float) * length); + } + else { + values = values_stack; + } + RNA_property_float_get_array(ptr, prop, values); + + for (count = start; count < stop; count++) { + PyTuple_SET_ITEM(tuple, count - start, PyFloat_FromDouble(values[count])); + } + + if (values != values_stack) { + PyMem_FREE(values); + } + break; + } + case PROP_BOOLEAN: { + bool values_stack[PYRNA_STACK_ARRAY]; + bool *values; + if (length > PYRNA_STACK_ARRAY) { + values = PyMem_MALLOC(sizeof(bool) * length); + } + else { + values = values_stack; + } + + RNA_property_boolean_get_array(ptr, prop, values); + for (count = start; count < stop; count++) { + PyTuple_SET_ITEM(tuple, count - start, PyBool_FromLong(values[count])); + } + + if (values != values_stack) { + PyMem_FREE(values); + } + break; + } + case PROP_INT: { + int values_stack[PYRNA_STACK_ARRAY]; + int *values; + if (length > PYRNA_STACK_ARRAY) { + values = PyMem_MALLOC(sizeof(int) * length); + } + else { + values = values_stack; + } + + RNA_property_int_get_array(ptr, prop, values); + for (count = start; count < stop; count++) { + PyTuple_SET_ITEM(tuple, count - start, PyLong_FromLong(values[count])); + } + + if (values != values_stack) { + PyMem_FREE(values); + } + break; + } + default: + BLI_assert(!"Invalid array type"); + + PyErr_SetString(PyExc_TypeError, "not an array type"); + Py_DECREF(tuple); + tuple = NULL; + break; + } + } + return tuple; } static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject *key) { - PYRNA_PROP_CHECK_OBJ(self); - - if (PyUnicode_Check(key)) { - return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); - } - else if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return NULL; - } - - return pyrna_prop_collection_subscript_int(self, i); - } - else if (PySlice_Check(key)) { - PySliceObject *key_slice = (PySliceObject *)key; - Py_ssize_t step = 1; - - if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { - return NULL; - } - else if (step != 1) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported"); - return NULL; - } - else if (key_slice->start == Py_None && key_slice->stop == Py_None) { - return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); - } - else { - Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX; - - /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */ - if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) { - return NULL; - } - if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) { - return NULL; - } - - if (start < 0 || stop < 0) { - /* only get the length for negative values */ - Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); - if (start < 0) { - start += len; - } - if (stop < 0) { - stop += len; - } - } - - if (stop - start <= 0) { - return PyList_New(0); - } - else { - return pyrna_prop_collection_subscript_slice(self, start, stop); - } - } - } - 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, " - "must be a string or an int, not %.200s", - Py_TYPE(key)->tp_name); - return NULL; - } + PYRNA_PROP_CHECK_OBJ(self); + + if (PyUnicode_Check(key)) { + return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); + } + else if (PyIndex_Check(key)) { + Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return NULL; + } + + return pyrna_prop_collection_subscript_int(self, i); + } + else if (PySlice_Check(key)) { + PySliceObject *key_slice = (PySliceObject *)key; + Py_ssize_t step = 1; + + if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { + return NULL; + } + else if (step != 1) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported"); + return NULL; + } + else if (key_slice->start == Py_None && key_slice->stop == Py_None) { + return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); + } + else { + Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX; + + /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */ + if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) { + return NULL; + } + if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) { + return NULL; + } + + if (start < 0 || stop < 0) { + /* only get the length for negative values */ + Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); + if (start < 0) { + start += len; + } + if (stop < 0) { + stop += len; + } + } + + if (stop - start <= 0) { + return PyList_New(0); + } + else { + return pyrna_prop_collection_subscript_slice(self, start, stop); + } + } + } + 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, " + "must be a string or an int, not %.200s", + Py_TYPE(key)->tp_name); + return NULL; + } } /* generic check to see if a PyObject is compatible with a collection * -1 on failure, 0 on success, sets the error */ static int pyrna_prop_collection_type_check(BPy_PropertyRNA *self, PyObject *value) { - StructRNA *prop_srna; - - if (value == Py_None) { - if (RNA_property_flag(self->prop) & PROP_NEVER_NULL) { - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key] = value: invalid, " - "this collection doesn't support None assignment"); - return -1; - } - else { - return 0; /* None is OK */ - } - } - else if (BPy_StructRNA_Check(value) == 0) { - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key] = value: invalid, " - "expected a StructRNA type or None, not a %.200s", - Py_TYPE(value)->tp_name); - return -1; - } - else if ((prop_srna = RNA_property_pointer_type(&self->ptr, self->prop))) { - StructRNA *value_srna = ((BPy_StructRNA *)value)->ptr.type; - if (RNA_struct_is_a(value_srna, prop_srna) == 0) { - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key] = value: invalid, " - "expected a '%.200s' type or None, not a '%.200s'", - RNA_struct_identifier(prop_srna), - RNA_struct_identifier(value_srna) - ); - return -1; - } - else { - return 0; /* OK, this is the correct type!*/ - } - } - - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key] = value: internal error, " - "failed to get the collection type"); - return -1; + StructRNA *prop_srna; + + if (value == Py_None) { + if (RNA_property_flag(self->prop) & PROP_NEVER_NULL) { + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key] = value: invalid, " + "this collection doesn't support None assignment"); + return -1; + } + else { + return 0; /* None is OK */ + } + } + else if (BPy_StructRNA_Check(value) == 0) { + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key] = value: invalid, " + "expected a StructRNA type or None, not a %.200s", + Py_TYPE(value)->tp_name); + return -1; + } + else if ((prop_srna = RNA_property_pointer_type(&self->ptr, self->prop))) { + StructRNA *value_srna = ((BPy_StructRNA *)value)->ptr.type; + if (RNA_struct_is_a(value_srna, prop_srna) == 0) { + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key] = value: invalid, " + "expected a '%.200s' type or None, not a '%.200s'", + RNA_struct_identifier(prop_srna), + RNA_struct_identifier(value_srna)); + return -1; + } + else { + return 0; /* OK, this is the correct type!*/ + } + } + + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key] = value: internal error, " + "failed to get the collection type"); + return -1; } /* note: currently this is a copy of 'pyrna_prop_collection_subscript' with * large blocks commented, we may support slice/key indices later */ -static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, PyObject *key, PyObject *value) +static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, + PyObject *key, + PyObject *value) { - PYRNA_PROP_CHECK_INT(self); + PYRNA_PROP_CHECK_INT(self); - /* validate the assigned value */ - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, - "del bpy_prop_collection[key]: not supported"); - return -1; - } - else if (pyrna_prop_collection_type_check(self, value) == -1) { - return -1; /* exception is set */ - } + /* validate the assigned value */ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "del bpy_prop_collection[key]: not supported"); + return -1; + } + else if (pyrna_prop_collection_type_check(self, value) == -1) { + return -1; /* exception is set */ + } #if 0 - if (PyUnicode_Check(key)) { - return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); - } - else + if (PyUnicode_Check(key)) { + return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); + } + else #endif - if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return -1; - } - - return pyrna_prop_collection_ass_subscript_int(self, i, value); - } + if (PyIndex_Check(key)) { + Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return -1; + } + + return pyrna_prop_collection_ass_subscript_int(self, i, value); + } #if 0 /* TODO, fake slice assignment */ - else if (PySlice_Check(key)) { - PySliceObject *key_slice = (PySliceObject *)key; - Py_ssize_t step = 1; - - if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { - return NULL; - } - else if (step != 1) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported"); - return NULL; - } - else if (key_slice->start == Py_None && key_slice->stop == Py_None) { - return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); - } - else { - Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX; - - /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */ - if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL; - if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL; - - if (start < 0 || stop < 0) { - /* only get the length for negative values */ - Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); - if (start < 0) start += len; - if (stop < 0) stop += len; - } - - if (stop - start <= 0) { - return PyList_New(0); - } - else { - return pyrna_prop_collection_subscript_slice(self, start, stop); - } - } - } + else if (PySlice_Check(key)) { + PySliceObject *key_slice = (PySliceObject *)key; + Py_ssize_t step = 1; + + if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { + return NULL; + } + else if (step != 1) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported"); + return NULL; + } + else if (key_slice->start == Py_None && key_slice->stop == Py_None) { + return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); + } + else { + Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX; + + /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */ + if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL; + if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL; + + if (start < 0 || stop < 0) { + /* only get the length for negative values */ + Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); + if (start < 0) start += len; + if (stop < 0) stop += len; + } + + if (stop - start <= 0) { + return PyList_New(0); + } + else { + return pyrna_prop_collection_subscript_slice(self, start, stop); + } + } + } #endif - else { - PyErr_Format(PyExc_TypeError, - "bpy_prop_collection[key]: invalid key, " - "must be a string or an int, not %.200s", - Py_TYPE(key)->tp_name); - return -1; - } + else { + PyErr_Format(PyExc_TypeError, + "bpy_prop_collection[key]: invalid key, " + "must be a string or an int, not %.200s", + Py_TYPE(key)->tp_name); + return -1; + } } static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject *key) { - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); #if 0 - if (PyUnicode_Check(key)) { - return pyrna_prop_array_subscript_str(self, _PyUnicode_AsString(key)); - } - else + if (PyUnicode_Check(key)) { + return pyrna_prop_array_subscript_str(self, _PyUnicode_AsString(key)); + } + else #endif - if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return NULL; - } - return pyrna_prop_array_subscript_int(self, i); - } - else if (PySlice_Check(key)) { - Py_ssize_t step = 1; - PySliceObject *key_slice = (PySliceObject *)key; - - if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { - return NULL; - } - else if (step != 1) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]: slice steps not supported"); - return NULL; - } - else if (key_slice->start == Py_None && key_slice->stop == Py_None) { - /* note, no significant advantage with optimizing [:] slice as with collections - * but include here for consistency with collection slice func */ - Py_ssize_t len = (Py_ssize_t)pyrna_prop_array_length(self); - return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len); - } - else { - int len = pyrna_prop_array_length(self); - Py_ssize_t start, stop, slicelength; - - if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { - return NULL; - } - - if (slicelength <= 0) { - return PyTuple_New(0); - } - else { - return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, start, stop, len); - } - } - } - else { - PyErr_SetString(PyExc_AttributeError, "bpy_prop_array[key]: invalid key, key must be an int"); - return NULL; - } + if (PyIndex_Check(key)) { + Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return NULL; + } + return pyrna_prop_array_subscript_int(self, i); + } + else if (PySlice_Check(key)) { + Py_ssize_t step = 1; + PySliceObject *key_slice = (PySliceObject *)key; + + if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) { + return NULL; + } + else if (step != 1) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_array[slice]: slice steps not supported"); + return NULL; + } + else if (key_slice->start == Py_None && key_slice->stop == Py_None) { + /* note, no significant advantage with optimizing [:] slice as with collections + * but include here for consistency with collection slice func */ + Py_ssize_t len = (Py_ssize_t)pyrna_prop_array_length(self); + return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len); + } + else { + int len = pyrna_prop_array_length(self); + Py_ssize_t start, stop, slicelength; + + if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { + return NULL; + } + + if (slicelength <= 0) { + return PyTuple_New(0); + } + else { + return pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, start, stop, len); + } + } + } + else { + PyErr_SetString(PyExc_AttributeError, "bpy_prop_array[key]: invalid key, key must be an int"); + return NULL; + } } /** @@ -2847,1041 +2897,1043 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject static PyObject *prop_subscript_ass_array_slice__as_seq_fast(PyObject *value, int length) { - PyObject *value_fast; - if (!(value_fast = PySequence_Fast( - value, - "bpy_prop_array[slice] = value: " - "element in assignment is not a sequence type"))) - { - return NULL; - } - else if (PySequence_Fast_GET_SIZE(value_fast) != length) { - Py_DECREF(value_fast); - PyErr_SetString( - PyExc_ValueError, - "bpy_prop_array[slice] = value: " - "re-sizing bpy_struct element in arrays isn't supported"); - - return NULL; - } - else { - return value_fast; - } + PyObject *value_fast; + if (!(value_fast = PySequence_Fast(value, + "bpy_prop_array[slice] = value: " + "element in assignment is not a sequence type"))) { + return NULL; + } + else if (PySequence_Fast_GET_SIZE(value_fast) != length) { + Py_DECREF(value_fast); + PyErr_SetString(PyExc_ValueError, + "bpy_prop_array[slice] = value: " + "re-sizing bpy_struct element in arrays isn't supported"); + + return NULL; + } + else { + return value_fast; + } } static int prop_subscript_ass_array_slice__float_recursive( - PyObject **value_items, float *value, - int totdim, const int dimsize[], - const float range[2]) -{ - const int length = dimsize[0]; - if (totdim > 1) { - int index = 0; - int i; - for (i = 0; i != length; i++) { - PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); - if (UNLIKELY(subvalue == NULL)) { - return 0; - } - - index += prop_subscript_ass_array_slice__float_recursive( - PySequence_Fast_ITEMS(subvalue), &value[index], - totdim - 1, &dimsize[1], range); - - Py_DECREF(subvalue); - } - return index; - } - else { - BLI_assert(totdim == 1); - const float min = range[0], max = range[1]; - int i; - for (i = 0; i != length; i++) { - float v = PyFloat_AsDouble(value_items[i]); - CLAMP(v, min, max); - value[i] = v; - } - return i; - } + PyObject **value_items, float *value, int totdim, const int dimsize[], const float range[2]) +{ + const int length = dimsize[0]; + if (totdim > 1) { + int index = 0; + int i; + for (i = 0; i != length; i++) { + PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); + if (UNLIKELY(subvalue == NULL)) { + return 0; + } + + index += prop_subscript_ass_array_slice__float_recursive( + PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1], range); + + Py_DECREF(subvalue); + } + return index; + } + else { + BLI_assert(totdim == 1); + const float min = range[0], max = range[1]; + int i; + for (i = 0; i != length; i++) { + float v = PyFloat_AsDouble(value_items[i]); + CLAMP(v, min, max); + value[i] = v; + } + return i; + } } static int prop_subscript_ass_array_slice__int_recursive( - PyObject **value_items, int *value, - int totdim, const int dimsize[], - const int range[2]) -{ - const int length = dimsize[0]; - if (totdim > 1) { - int index = 0; - int i; - for (i = 0; i != length; i++) { - PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); - if (UNLIKELY(subvalue == NULL)) { - return 0; - } - - index += prop_subscript_ass_array_slice__int_recursive( - PySequence_Fast_ITEMS(subvalue), &value[index], - totdim - 1, &dimsize[1], range); - - Py_DECREF(subvalue); - } - return index; - } - else { - BLI_assert(totdim == 1); - const int min = range[0], max = range[1]; - int i; - for (i = 0; i != length; i++) { - int v = PyLong_AsLong(value_items[i]); - CLAMP(v, min, max); - value[i] = v; - } - return i; - } -} - -static int prop_subscript_ass_array_slice__bool_recursive( - PyObject **value_items, bool *value, - int totdim, const int dimsize[]) -{ - const int length = dimsize[0]; - if (totdim > 1) { - int index = 0; - int i; - for (i = 0; i != length; i++) { - PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); - if (UNLIKELY(subvalue == NULL)) { - return 0; - } - - index += prop_subscript_ass_array_slice__bool_recursive( - PySequence_Fast_ITEMS(subvalue), &value[index], - totdim - 1, &dimsize[1]); - - Py_DECREF(subvalue); - } - return index; - } - else { - BLI_assert(totdim == 1); - int i; - for (i = 0; i != length; i++) { - int v = PyLong_AsLong(value_items[i]); - value[i] = v; - } - return i; - } + PyObject **value_items, int *value, int totdim, const int dimsize[], const int range[2]) +{ + const int length = dimsize[0]; + if (totdim > 1) { + int index = 0; + int i; + for (i = 0; i != length; i++) { + PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); + if (UNLIKELY(subvalue == NULL)) { + return 0; + } + + index += prop_subscript_ass_array_slice__int_recursive( + PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1], range); + + Py_DECREF(subvalue); + } + return index; + } + else { + BLI_assert(totdim == 1); + const int min = range[0], max = range[1]; + int i; + for (i = 0; i != length; i++) { + int v = PyLong_AsLong(value_items[i]); + CLAMP(v, min, max); + value[i] = v; + } + return i; + } +} + +static int prop_subscript_ass_array_slice__bool_recursive(PyObject **value_items, + bool *value, + int totdim, + const int dimsize[]) +{ + const int length = dimsize[0]; + if (totdim > 1) { + int index = 0; + int i; + for (i = 0; i != length; i++) { + PyObject *subvalue = prop_subscript_ass_array_slice__as_seq_fast(value_items[i], dimsize[1]); + if (UNLIKELY(subvalue == NULL)) { + return 0; + } + + index += prop_subscript_ass_array_slice__bool_recursive( + PySequence_Fast_ITEMS(subvalue), &value[index], totdim - 1, &dimsize[1]); + + Py_DECREF(subvalue); + } + return index; + } + else { + BLI_assert(totdim == 1); + int i; + for (i = 0; i != length; i++) { + int v = PyLong_AsLong(value_items[i]); + value[i] = v; + } + return i; + } } /* could call (pyrna_py_to_prop_array_index(self, i, value) in a loop but it is slow */ -static int prop_subscript_ass_array_slice( - PointerRNA *ptr, PropertyRNA *prop, int arraydim, int arrayoffset, - int start, int stop, int length, PyObject *value_orig) -{ - const int length_flat = RNA_property_array_length(ptr, prop); - PyObject *value; - PyObject **value_items; - void *values_alloc = NULL; - int ret = 0; - - if (value_orig == NULL) { - PyErr_SetString(PyExc_TypeError, - "bpy_prop_array[slice] = value: deleting with list types is not supported by bpy_struct"); - return -1; - } - - if (!(value = PySequence_Fast(value_orig, "bpy_prop_array[slice] = value: assignment is not a sequence type"))) { - return -1; - } - - if (PySequence_Fast_GET_SIZE(value) != stop - start) { - Py_DECREF(value); - PyErr_SetString(PyExc_TypeError, - "bpy_prop_array[slice] = value: re-sizing bpy_struct arrays isn't supported"); - return -1; - } - - int dimsize[3]; - int totdim = RNA_property_array_dimension(ptr, prop, dimsize); - if (totdim > 1) { - BLI_assert(dimsize[arraydim] == length); - } - - int span = 1; - if (totdim > 1) { - for (int i = arraydim + 1; i < totdim; i++) { - span *= dimsize[i]; - } - } - - value_items = PySequence_Fast_ITEMS(value); - switch (RNA_property_type(prop)) { - case PROP_FLOAT: - { - float values_stack[PYRNA_STACK_ARRAY]; - float *values = (length_flat > PYRNA_STACK_ARRAY) ? - (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) : values_stack; - if (start != 0 || stop != length) { - /* partial assignment? - need to get the array */ - RNA_property_float_get_array(ptr, prop, values); - } - - float range[2]; - RNA_property_float_range(ptr, prop, &range[0], &range[1]); - - dimsize[arraydim] = stop - start; - prop_subscript_ass_array_slice__float_recursive( - value_items, &values[arrayoffset + (start * span)], - totdim - arraydim, &dimsize[arraydim], - range); - - if (PyErr_Occurred()) { - ret = -1; - } - else { - RNA_property_float_set_array(ptr, prop, values); - } - break; - } - case PROP_INT: - { - int values_stack[PYRNA_STACK_ARRAY]; - int *values = (length_flat > PYRNA_STACK_ARRAY) ? - (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) : values_stack; - if (start != 0 || stop != length) { - /* partial assignment? - need to get the array */ - RNA_property_int_get_array(ptr, prop, values); - } - - int range[2]; - RNA_property_int_range(ptr, prop, &range[0], &range[1]); - - dimsize[arraydim] = stop - start; - prop_subscript_ass_array_slice__int_recursive( - value_items, &values[arrayoffset + (start * span)], - totdim - arraydim, &dimsize[arraydim], - range); - - if (PyErr_Occurred()) { - ret = -1; - } - else { - RNA_property_int_set_array(ptr, prop, values); - } - break; - } - case PROP_BOOLEAN: - { - bool values_stack[PYRNA_STACK_ARRAY]; - bool *values = (length_flat > PYRNA_STACK_ARRAY) ? - (values_alloc = PyMem_MALLOC(sizeof(bool) * length_flat)) : values_stack; - - if (start != 0 || stop != length) { - /* partial assignment? - need to get the array */ - RNA_property_boolean_get_array(ptr, prop, values); - } - - dimsize[arraydim] = stop - start; - prop_subscript_ass_array_slice__bool_recursive( - value_items, &values[arrayoffset + (start * span)], - totdim - arraydim, &dimsize[arraydim]); - - if (PyErr_Occurred()) { - ret = -1; - } - else { - RNA_property_boolean_set_array(ptr, prop, values); - } - break; - } - default: - PyErr_SetString(PyExc_TypeError, "not an array type"); - ret = -1; - break; - } - - Py_DECREF(value); - - if (values_alloc) { - PyMem_FREE(values_alloc); - } - - return ret; - -} - -static int prop_subscript_ass_array_int(BPy_PropertyArrayRNA *self, Py_ssize_t keynum, PyObject *value) -{ - int len; - - PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); - - len = pyrna_prop_array_length(self); - - if (keynum < 0) { - keynum += len; - } - - if (keynum >= 0 && keynum < len) { - return pyrna_py_to_prop_array_index(self, keynum, value); - } - - PyErr_SetString(PyExc_IndexError, - "bpy_prop_array[index] = value: index out of range"); - return -1; -} - -static int pyrna_prop_array_ass_subscript(BPy_PropertyArrayRNA *self, PyObject *key, PyObject *value) -{ - /* char *keyname = NULL; */ /* not supported yet */ - int ret = -1; - - PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); - - if (!RNA_property_editable_flag(&self->ptr, self->prop)) { - PyErr_Format(PyExc_AttributeError, - "bpy_prop_collection: attribute \"%.200s\" from \"%.200s\" is read-only", - RNA_property_identifier(self->prop), RNA_struct_identifier(self->ptr.type)); - ret = -1; - } - - else if (PyIndex_Check(key)) { - Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - ret = -1; - } - else { - ret = prop_subscript_ass_array_int(self, i, value); - } - } - else if (PySlice_Check(key)) { - Py_ssize_t len = pyrna_prop_array_length(self); - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { - ret = -1; - } - else if (slicelength <= 0) { - ret = 0; /* do nothing */ - } - else if (step == 1) { - ret = prop_subscript_ass_array_slice( - &self->ptr, self->prop, self->arraydim, self->arrayoffset, - start, stop, len, value); - } - else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); - ret = -1; - } - } - else { - PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int"); - ret = -1; - } - - if (ret != -1) { - if (RNA_property_update_check(self->prop)) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); - } - } - - return ret; +static int prop_subscript_ass_array_slice(PointerRNA *ptr, + PropertyRNA *prop, + int arraydim, + int arrayoffset, + int start, + int stop, + int length, + PyObject *value_orig) +{ + const int length_flat = RNA_property_array_length(ptr, prop); + PyObject *value; + PyObject **value_items; + void *values_alloc = NULL; + int ret = 0; + + if (value_orig == NULL) { + PyErr_SetString( + PyExc_TypeError, + "bpy_prop_array[slice] = value: deleting with list types is not supported by bpy_struct"); + return -1; + } + + if (!(value = PySequence_Fast( + value_orig, "bpy_prop_array[slice] = value: assignment is not a sequence type"))) { + return -1; + } + + if (PySequence_Fast_GET_SIZE(value) != stop - start) { + Py_DECREF(value); + PyErr_SetString(PyExc_TypeError, + "bpy_prop_array[slice] = value: re-sizing bpy_struct arrays isn't supported"); + return -1; + } + + int dimsize[3]; + int totdim = RNA_property_array_dimension(ptr, prop, dimsize); + if (totdim > 1) { + BLI_assert(dimsize[arraydim] == length); + } + + int span = 1; + if (totdim > 1) { + for (int i = arraydim + 1; i < totdim; i++) { + span *= dimsize[i]; + } + } + + value_items = PySequence_Fast_ITEMS(value); + switch (RNA_property_type(prop)) { + case PROP_FLOAT: { + float values_stack[PYRNA_STACK_ARRAY]; + float *values = (length_flat > PYRNA_STACK_ARRAY) ? + (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) : + values_stack; + if (start != 0 || stop != length) { + /* partial assignment? - need to get the array */ + RNA_property_float_get_array(ptr, prop, values); + } + + float range[2]; + RNA_property_float_range(ptr, prop, &range[0], &range[1]); + + dimsize[arraydim] = stop - start; + prop_subscript_ass_array_slice__float_recursive(value_items, + &values[arrayoffset + (start * span)], + totdim - arraydim, + &dimsize[arraydim], + range); + + if (PyErr_Occurred()) { + ret = -1; + } + else { + RNA_property_float_set_array(ptr, prop, values); + } + break; + } + case PROP_INT: { + int values_stack[PYRNA_STACK_ARRAY]; + int *values = (length_flat > PYRNA_STACK_ARRAY) ? + (values_alloc = PyMem_MALLOC(sizeof(*values) * length_flat)) : + values_stack; + if (start != 0 || stop != length) { + /* partial assignment? - need to get the array */ + RNA_property_int_get_array(ptr, prop, values); + } + + int range[2]; + RNA_property_int_range(ptr, prop, &range[0], &range[1]); + + dimsize[arraydim] = stop - start; + prop_subscript_ass_array_slice__int_recursive(value_items, + &values[arrayoffset + (start * span)], + totdim - arraydim, + &dimsize[arraydim], + range); + + if (PyErr_Occurred()) { + ret = -1; + } + else { + RNA_property_int_set_array(ptr, prop, values); + } + break; + } + case PROP_BOOLEAN: { + bool values_stack[PYRNA_STACK_ARRAY]; + bool *values = (length_flat > PYRNA_STACK_ARRAY) ? + (values_alloc = PyMem_MALLOC(sizeof(bool) * length_flat)) : + values_stack; + + if (start != 0 || stop != length) { + /* partial assignment? - need to get the array */ + RNA_property_boolean_get_array(ptr, prop, values); + } + + dimsize[arraydim] = stop - start; + prop_subscript_ass_array_slice__bool_recursive(value_items, + &values[arrayoffset + (start * span)], + totdim - arraydim, + &dimsize[arraydim]); + + if (PyErr_Occurred()) { + ret = -1; + } + else { + RNA_property_boolean_set_array(ptr, prop, values); + } + break; + } + default: + PyErr_SetString(PyExc_TypeError, "not an array type"); + ret = -1; + break; + } + + Py_DECREF(value); + + if (values_alloc) { + PyMem_FREE(values_alloc); + } + + return ret; +} + +static int prop_subscript_ass_array_int(BPy_PropertyArrayRNA *self, + Py_ssize_t keynum, + PyObject *value) +{ + int len; + + PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); + + len = pyrna_prop_array_length(self); + + if (keynum < 0) { + keynum += len; + } + + if (keynum >= 0 && keynum < len) { + return pyrna_py_to_prop_array_index(self, keynum, value); + } + + PyErr_SetString(PyExc_IndexError, "bpy_prop_array[index] = value: index out of range"); + return -1; +} + +static int pyrna_prop_array_ass_subscript(BPy_PropertyArrayRNA *self, + PyObject *key, + PyObject *value) +{ + /* char *keyname = NULL; */ /* not supported yet */ + int ret = -1; + + PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); + + if (!RNA_property_editable_flag(&self->ptr, self->prop)) { + PyErr_Format(PyExc_AttributeError, + "bpy_prop_collection: attribute \"%.200s\" from \"%.200s\" is read-only", + RNA_property_identifier(self->prop), + RNA_struct_identifier(self->ptr.type)); + ret = -1; + } + + else if (PyIndex_Check(key)) { + Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + ret = -1; + } + else { + ret = prop_subscript_ass_array_int(self, i, value); + } + } + else if (PySlice_Check(key)) { + Py_ssize_t len = pyrna_prop_array_length(self); + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { + ret = -1; + } + else if (slicelength <= 0) { + ret = 0; /* do nothing */ + } + else if (step == 1) { + ret = prop_subscript_ass_array_slice( + &self->ptr, self->prop, self->arraydim, self->arrayoffset, start, stop, len, value); + } + else { + PyErr_SetString(PyExc_TypeError, "slice steps not supported with rna"); + ret = -1; + } + } + else { + PyErr_SetString(PyExc_AttributeError, "invalid key, key must be an int"); + ret = -1; + } + + if (ret != -1) { + if (RNA_property_update_check(self->prop)) { + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + } + } + + return ret; } /* for slice only */ static PyMappingMethods pyrna_prop_array_as_mapping = { - (lenfunc) pyrna_prop_array_length, /* mp_length */ - (binaryfunc) pyrna_prop_array_subscript, /* mp_subscript */ - (objobjargproc) pyrna_prop_array_ass_subscript, /* mp_ass_subscript */ + (lenfunc)pyrna_prop_array_length, /* mp_length */ + (binaryfunc)pyrna_prop_array_subscript, /* mp_subscript */ + (objobjargproc)pyrna_prop_array_ass_subscript, /* mp_ass_subscript */ }; static PyMappingMethods pyrna_prop_collection_as_mapping = { - (lenfunc) pyrna_prop_collection_length, /* mp_length */ - (binaryfunc) pyrna_prop_collection_subscript, /* mp_subscript */ - (objobjargproc) pyrna_prop_collection_ass_subscript, /* mp_ass_subscript */ + (lenfunc)pyrna_prop_collection_length, /* mp_length */ + (binaryfunc)pyrna_prop_collection_subscript, /* mp_subscript */ + (objobjargproc)pyrna_prop_collection_ass_subscript, /* mp_ass_subscript */ }; /* only for fast bool's, large structs, assign nb_bool on init */ static PyNumberMethods pyrna_prop_array_as_number = { - NULL, /* nb_add */ - NULL, /* nb_subtract */ - NULL, /* nb_multiply */ - NULL, /* nb_remainder */ - NULL, /* nb_divmod */ - NULL, /* nb_power */ - NULL, /* nb_negative */ - NULL, /* nb_positive */ - NULL, /* nb_absolute */ - (inquiry) pyrna_prop_array_bool, /* nb_bool */ + NULL, /* nb_add */ + NULL, /* nb_subtract */ + NULL, /* nb_multiply */ + NULL, /* nb_remainder */ + NULL, /* nb_divmod */ + NULL, /* nb_power */ + NULL, /* nb_negative */ + NULL, /* nb_positive */ + NULL, /* nb_absolute */ + (inquiry)pyrna_prop_array_bool, /* nb_bool */ }; static PyNumberMethods pyrna_prop_collection_as_number = { - NULL, /* nb_add */ - NULL, /* nb_subtract */ - NULL, /* nb_multiply */ - NULL, /* nb_remainder */ - NULL, /* nb_divmod */ - NULL, /* nb_power */ - NULL, /* nb_negative */ - NULL, /* nb_positive */ - NULL, /* nb_absolute */ - (inquiry) pyrna_prop_collection_bool, /* nb_bool */ + NULL, /* nb_add */ + NULL, /* nb_subtract */ + NULL, /* nb_multiply */ + NULL, /* nb_remainder */ + NULL, /* nb_divmod */ + NULL, /* nb_power */ + NULL, /* nb_negative */ + NULL, /* nb_positive */ + NULL, /* nb_absolute */ + (inquiry)pyrna_prop_collection_bool, /* nb_bool */ }; static int pyrna_prop_array_contains(BPy_PropertyRNA *self, PyObject *value) { - return pyrna_array_contains_py(&self->ptr, self->prop, value); + return pyrna_array_contains_py(&self->ptr, self->prop, value); } static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *key) { - PointerRNA newptr; /* not used, just so RNA_property_collection_lookup_string runs */ + PointerRNA newptr; /* not used, just so RNA_property_collection_lookup_string runs */ - if (PyTuple_Check(key)) { - /* special case, for ID datablocks we */ - return pyrna_prop_collection_subscript_str_lib_pair_ptr(self, key, - "(id, lib) in bpy_prop_collection", false, NULL); - } - else { + if (PyTuple_Check(key)) { + /* special case, for ID datablocks we */ + return pyrna_prop_collection_subscript_str_lib_pair_ptr( + self, key, "(id, lib) in bpy_prop_collection", false, NULL); + } + else { - /* key in dict style check */ - const char *keyname = _PyUnicode_AsString(key); + /* key in dict style check */ + const char *keyname = _PyUnicode_AsString(key); - if (keyname == NULL) { - PyErr_SetString(PyExc_TypeError, - "bpy_prop_collection.__contains__: expected a string or a tuple of strings"); - return -1; - } + if (keyname == NULL) { + PyErr_SetString(PyExc_TypeError, + "bpy_prop_collection.__contains__: expected a string or a tuple of strings"); + return -1; + } - if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) { - return 1; - } + if (RNA_property_collection_lookup_string(&self->ptr, self->prop, keyname, &newptr)) { + return 1; + } - return 0; - } + return 0; + } } static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value) { - IDProperty *group; - const char *name = _PyUnicode_AsString(value); + IDProperty *group; + const char *name = _PyUnicode_AsString(value); - PYRNA_STRUCT_CHECK_INT(self); + PYRNA_STRUCT_CHECK_INT(self); - if (!name) { - PyErr_SetString(PyExc_TypeError, "bpy_struct.__contains__: expected a string"); - return -1; - } + if (!name) { + PyErr_SetString(PyExc_TypeError, "bpy_struct.__contains__: expected a string"); + return -1; + } - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "bpy_struct: this type doesn't support IDProperties"); - return -1; - } + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "bpy_struct: this type doesn't support IDProperties"); + return -1; + } - group = RNA_struct_idprops(&self->ptr, 0); + group = RNA_struct_idprops(&self->ptr, 0); - if (!group) { - return 0; - } + if (!group) { + return 0; + } - return IDP_GetPropertyFromGroup(group, name) ? 1 : 0; + return IDP_GetPropertyFromGroup(group, name) ? 1 : 0; } static PySequenceMethods pyrna_prop_array_as_sequence = { - (lenfunc)pyrna_prop_array_length, - NULL, /* sq_concat */ - NULL, /* sq_repeat */ - (ssizeargfunc)pyrna_prop_array_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */ - NULL, /* sq_slice */ - (ssizeobjargproc)prop_subscript_ass_array_int, /* sq_ass_item */ - NULL, /* *was* sq_ass_slice */ - (objobjproc)pyrna_prop_array_contains, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + (lenfunc)pyrna_prop_array_length, + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + (ssizeargfunc)pyrna_prop_array_subscript_int, + /* sq_item */ /* Only set this so PySequence_Check() returns True */ + NULL, /* sq_slice */ + (ssizeobjargproc)prop_subscript_ass_array_int, /* sq_ass_item */ + NULL, /* *was* sq_ass_slice */ + (objobjproc)pyrna_prop_array_contains, /* sq_contains */ + (binaryfunc)NULL, /* sq_inplace_concat */ + (ssizeargfunc)NULL, /* sq_inplace_repeat */ }; static PySequenceMethods pyrna_prop_collection_as_sequence = { - (lenfunc)pyrna_prop_collection_length, - NULL, /* sq_concat */ - NULL, /* sq_repeat */ - (ssizeargfunc)pyrna_prop_collection_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */ - NULL, /* *was* sq_slice */ - (ssizeobjargproc)/* pyrna_prop_collection_ass_subscript_int */ NULL /* let mapping take this one */, /* sq_ass_item */ - NULL, /* *was* sq_ass_slice */ - (objobjproc)pyrna_prop_collection_contains, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + (lenfunc)pyrna_prop_collection_length, + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + (ssizeargfunc)pyrna_prop_collection_subscript_int, + /* sq_item */ /* Only set this so PySequence_Check() returns True */ + NULL, /* *was* sq_slice */ + (ssizeobjargproc) /* pyrna_prop_collection_ass_subscript_int */ + NULL /* let mapping take this one */, /* sq_ass_item */ + NULL, /* *was* sq_ass_slice */ + (objobjproc)pyrna_prop_collection_contains, /* sq_contains */ + (binaryfunc)NULL, /* sq_inplace_concat */ + (ssizeargfunc)NULL, /* sq_inplace_repeat */ }; static PySequenceMethods pyrna_struct_as_sequence = { - NULL, /* Cant set the len otherwise it can evaluate as false */ - NULL, /* sq_concat */ - NULL, /* sq_repeat */ - NULL, /* sq_item */ /* Only set this so PySequence_Check() returns True */ - NULL, /* *was* sq_slice */ - NULL, /* sq_ass_item */ - NULL, /* *was* sq_ass_slice */ - (objobjproc)pyrna_struct_contains, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + NULL, /* Cant set the len otherwise it can evaluate as false */ + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + NULL, + /* sq_item */ /* Only set this so PySequence_Check() returns True */ + NULL, /* *was* sq_slice */ + NULL, /* sq_ass_item */ + NULL, /* *was* sq_ass_slice */ + (objobjproc)pyrna_struct_contains, /* sq_contains */ + (binaryfunc)NULL, /* sq_inplace_concat */ + (ssizeargfunc)NULL, /* sq_inplace_repeat */ }; static PyObject *pyrna_struct_subscript(BPy_StructRNA *self, PyObject *key) { - /* mostly copied from BPy_IDGroup_Map_GetItem */ - IDProperty *group, *idprop; - const char *name = _PyUnicode_AsString(key); + /* mostly copied from BPy_IDGroup_Map_GetItem */ + IDProperty *group, *idprop; + const char *name = _PyUnicode_AsString(key); - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); - return NULL; - } + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); + return NULL; + } - if (name == NULL) { - PyErr_SetString(PyExc_TypeError, "bpy_struct[key]: only strings are allowed as keys of ID properties"); - return NULL; - } + if (name == NULL) { + PyErr_SetString(PyExc_TypeError, + "bpy_struct[key]: only strings are allowed as keys of ID properties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); + group = RNA_struct_idprops(&self->ptr, 0); - if (group == NULL) { - PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); - return NULL; - } + if (group == NULL) { + PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); + return NULL; + } - idprop = IDP_GetPropertyFromGroup(group, name); + idprop = IDP_GetPropertyFromGroup(group, name); - if (idprop == NULL) { - PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); - return NULL; - } + if (idprop == NULL) { + PyErr_Format(PyExc_KeyError, "bpy_struct[key]: key \"%s\" not found", name); + return NULL; + } - return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); + return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); } static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObject *value) { - IDProperty *group; + IDProperty *group; - PYRNA_STRUCT_CHECK_INT(self); + PYRNA_STRUCT_CHECK_INT(self); - group = RNA_struct_idprops(&self->ptr, 1); + group = RNA_struct_idprops(&self->ptr, 1); #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, key)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ - - if (group == NULL) { - PyErr_SetString(PyExc_TypeError, "bpy_struct[key] = val: id properties not supported for this type"); - return -1; - } - - if (value && BPy_StructRNA_Check(value)) { - BPy_StructRNA *val = (BPy_StructRNA *)value; - if (val && self->ptr.type && val->ptr.type) { - if (!RNA_struct_idprops_datablock_allowed(self->ptr.type) && - RNA_struct_idprops_contains_datablock(val->ptr.type)) - { - PyErr_SetString( - PyExc_TypeError, - "bpy_struct[key] = val: datablock id properties not supported for this type"); - return -1; - } - } - } - - return BPy_Wrap_SetMapItem(group, key, value); + if (rna_disallow_writes && rna_id_write_error(&self->ptr, key)) { + return -1; + } +#endif /* USE_PEDANTIC_WRITE */ + + if (group == NULL) { + PyErr_SetString(PyExc_TypeError, + "bpy_struct[key] = val: id properties not supported for this type"); + return -1; + } + + if (value && BPy_StructRNA_Check(value)) { + BPy_StructRNA *val = (BPy_StructRNA *)value; + if (val && self->ptr.type && val->ptr.type) { + if (!RNA_struct_idprops_datablock_allowed(self->ptr.type) && + RNA_struct_idprops_contains_datablock(val->ptr.type)) { + PyErr_SetString( + PyExc_TypeError, + "bpy_struct[key] = val: datablock id properties not supported for this type"); + return -1; + } + } + } + + return BPy_Wrap_SetMapItem(group, key, value); } static PyMappingMethods pyrna_struct_as_mapping = { - (lenfunc) NULL, /* mp_length */ - (binaryfunc) pyrna_struct_subscript, /* mp_subscript */ - (objobjargproc) pyrna_struct_ass_subscript, /* mp_ass_subscript */ + (lenfunc)NULL, /* mp_length */ + (binaryfunc)pyrna_struct_subscript, /* mp_subscript */ + (objobjargproc)pyrna_struct_ass_subscript, /* mp_ass_subscript */ }; PyDoc_STRVAR(pyrna_struct_keys_doc, -".. method:: keys()\n" -"\n" -" Returns the keys of this objects custom properties (matches pythons\n" -" dictionary function of the same name).\n" -"\n" -" :return: custom property keys.\n" -" :rtype: list of strings\n" -"\n" -BPY_DOC_ID_PROP_TYPE_NOTE -); + ".. method:: keys()\n" + "\n" + " Returns the keys of this objects custom properties (matches pythons\n" + " dictionary function of the same name).\n" + "\n" + " :return: custom property keys.\n" + " :rtype: list of strings\n" + "\n" BPY_DOC_ID_PROP_TYPE_NOTE); static PyObject *pyrna_struct_keys(BPy_PropertyRNA *self) { - IDProperty *group; + IDProperty *group; - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "bpy_struct.keys(): this type doesn't support IDProperties"); - return NULL; - } + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "bpy_struct.keys(): this type doesn't support IDProperties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); + group = RNA_struct_idprops(&self->ptr, 0); - if (group == NULL) { - return PyList_New(0); - } + if (group == NULL) { + return PyList_New(0); + } - return BPy_Wrap_GetKeys(group); + return BPy_Wrap_GetKeys(group); } PyDoc_STRVAR(pyrna_struct_items_doc, -".. method:: items()\n" -"\n" -" Returns the items of this objects custom properties (matches pythons\n" -" dictionary function of the same name).\n" -"\n" -" :return: custom property key, value pairs.\n" -" :rtype: list of key, value tuples\n" -"\n" -BPY_DOC_ID_PROP_TYPE_NOTE -); + ".. method:: items()\n" + "\n" + " Returns the items of this objects custom properties (matches pythons\n" + " dictionary function of the same name).\n" + "\n" + " :return: custom property key, value pairs.\n" + " :rtype: list of key, value tuples\n" + "\n" BPY_DOC_ID_PROP_TYPE_NOTE); static PyObject *pyrna_struct_items(BPy_PropertyRNA *self) { - IDProperty *group; + IDProperty *group; - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "bpy_struct.items(): this type doesn't support IDProperties"); - return NULL; - } + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "bpy_struct.items(): this type doesn't support IDProperties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); + group = RNA_struct_idprops(&self->ptr, 0); - if (group == NULL) { - return PyList_New(0); - } + if (group == NULL) { + return PyList_New(0); + } - return BPy_Wrap_GetItems(self->ptr.id.data, group); + return BPy_Wrap_GetItems(self->ptr.id.data, group); } PyDoc_STRVAR(pyrna_struct_values_doc, -".. method:: values()\n" -"\n" -" Returns the values of this objects custom properties (matches pythons\n" -" dictionary function of the same name).\n" -"\n" -" :return: custom property values.\n" -" :rtype: list\n" -"\n" -BPY_DOC_ID_PROP_TYPE_NOTE -); + ".. method:: values()\n" + "\n" + " Returns the values of this objects custom properties (matches pythons\n" + " dictionary function of the same name).\n" + "\n" + " :return: custom property values.\n" + " :rtype: list\n" + "\n" BPY_DOC_ID_PROP_TYPE_NOTE); static PyObject *pyrna_struct_values(BPy_PropertyRNA *self) { - IDProperty *group; + IDProperty *group; - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "bpy_struct.values(): this type doesn't support IDProperties"); - return NULL; - } + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, + "bpy_struct.values(): this type doesn't support IDProperties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); + group = RNA_struct_idprops(&self->ptr, 0); - if (group == NULL) { - return PyList_New(0); - } + if (group == NULL) { + return PyList_New(0); + } - return BPy_Wrap_GetValues(self->ptr.id.data, group); + return BPy_Wrap_GetValues(self->ptr.id.data, group); } - PyDoc_STRVAR(pyrna_struct_is_property_set_doc, -".. method:: is_property_set(property)\n" -"\n" -" Check if a property is set, use for testing operator properties.\n" -"\n" -" :return: True when the property has been set.\n" -" :rtype: boolean\n" -); + ".. method:: is_property_set(property)\n" + "\n" + " Check if a property is set, use for testing operator properties.\n" + "\n" + " :return: True when the property has been set.\n" + " :rtype: boolean\n"); static PyObject *pyrna_struct_is_property_set(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; + PropertyRNA *prop; + const char *name; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:is_property_set", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:is_property_set", &name)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.is_property_set(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.is_property_set(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - return PyBool_FromLong(RNA_property_is_set(&self->ptr, prop)); + return PyBool_FromLong(RNA_property_is_set(&self->ptr, prop)); } PyDoc_STRVAR(pyrna_struct_property_unset_doc, -".. method:: property_unset(property)\n" -"\n" -" Unset a property, will use default value afterward.\n" -); + ".. method:: property_unset(property)\n" + "\n" + " Unset a property, will use default value afterward.\n"); static PyObject *pyrna_struct_property_unset(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; + PropertyRNA *prop; + const char *name; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:property_unset", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:property_unset", &name)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.property_unset(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.property_unset(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - RNA_property_unset(&self->ptr, prop); + RNA_property_unset(&self->ptr, prop); - Py_RETURN_NONE; + Py_RETURN_NONE; } PyDoc_STRVAR(pyrna_struct_is_property_hidden_doc, -".. method:: is_property_hidden(property)\n" -"\n" -" Check if a property is hidden.\n" -"\n" -" :return: True when the property is hidden.\n" -" :rtype: boolean\n" -); + ".. method:: is_property_hidden(property)\n" + "\n" + " Check if a property is hidden.\n" + "\n" + " :return: True when the property is hidden.\n" + " :rtype: boolean\n"); static PyObject *pyrna_struct_is_property_hidden(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; + PropertyRNA *prop; + const char *name; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:is_property_hidden", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:is_property_hidden", &name)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.is_property_hidden(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.is_property_hidden(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - return PyBool_FromLong(RNA_property_flag(prop) & PROP_HIDDEN); + return PyBool_FromLong(RNA_property_flag(prop) & PROP_HIDDEN); } PyDoc_STRVAR(pyrna_struct_is_property_readonly_doc, -".. method:: is_property_readonly(property)\n" -"\n" -" Check if a property is readonly.\n" -"\n" -" :return: True when the property is readonly (not writable).\n" -" :rtype: boolean\n" -); + ".. method:: is_property_readonly(property)\n" + "\n" + " Check if a property is readonly.\n" + "\n" + " :return: True when the property is readonly (not writable).\n" + " :rtype: boolean\n"); static PyObject *pyrna_struct_is_property_readonly(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; + PropertyRNA *prop; + const char *name; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:is_property_readonly", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:is_property_readonly", &name)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.is_property_readonly(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.is_property_readonly(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - return PyBool_FromLong(!RNA_property_editable(&self->ptr, prop)); + return PyBool_FromLong(!RNA_property_editable(&self->ptr, prop)); } - PyDoc_STRVAR(pyrna_struct_is_property_overridable_static_doc, -".. method:: is_property_overridable_static(property)\n" -"\n" -" Check if a property is statically overridable.\n" -"\n" -" :return: True when the property is statically overridable.\n" -" :rtype: boolean\n" -); + ".. method:: is_property_overridable_static(property)\n" + "\n" + " Check if a property is statically overridable.\n" + "\n" + " :return: True when the property is statically overridable.\n" + " :rtype: boolean\n"); static PyObject *pyrna_struct_is_property_overridable_static(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; + PropertyRNA *prop; + const char *name; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s:is_property_overridable_static", &name)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s:is_property_overridable_static", &name)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.is_property_overridable_static(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.is_property_overridable_static(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - return PyBool_FromLong((long)RNA_property_overridable_get(&self->ptr, prop)); + return PyBool_FromLong((long)RNA_property_overridable_get(&self->ptr, prop)); } -PyDoc_STRVAR(pyrna_struct_property_overridable_static_set_doc, -".. method:: property_overridable_static_set(property)\n" -"\n" -" Define a property as statically overridable or not (only for custom properties!).\n" -"\n" -" :return: True when the overridable status of the property was successfully set.\n" -" :rtype: boolean\n" -); +PyDoc_STRVAR( + pyrna_struct_property_overridable_static_set_doc, + ".. method:: property_overridable_static_set(property)\n" + "\n" + " Define a property as statically overridable or not (only for custom properties!).\n" + "\n" + " :return: True when the overridable status of the property was successfully set.\n" + " :rtype: boolean\n"); static PyObject *pyrna_struct_property_overridable_static_set(BPy_StructRNA *self, PyObject *args) { - PropertyRNA *prop; - const char *name; - int is_overridable; + PropertyRNA *prop; + const char *name; + int is_overridable; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "sp:property_overridable_static_set", &name, &is_overridable)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "sp:property_overridable_static_set", &name, &is_overridable)) { + return NULL; + } - if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s.property_overridable_static_set(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } + if ((prop = RNA_struct_find_property(&self->ptr, name)) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s.property_overridable_static_set(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } - return PyBool_FromLong((long)RNA_property_overridable_static_set(&self->ptr, prop, (bool)is_overridable)); + return PyBool_FromLong( + (long)RNA_property_overridable_static_set(&self->ptr, prop, (bool)is_overridable)); } - - PyDoc_STRVAR(pyrna_struct_path_resolve_doc, -".. method:: path_resolve(path, coerce=True)\n" -"\n" -" Returns the property from the path, raise an exception when not found.\n" -"\n" -" :arg path: path which this property resolves.\n" -" :type path: string\n" -" :arg coerce: optional argument, when True, the property will be converted\n" -" into its python representation.\n" -" :type coerce: boolean\n" -); + ".. method:: path_resolve(path, coerce=True)\n" + "\n" + " Returns the property from the path, raise an exception when not found.\n" + "\n" + " :arg path: path which this property resolves.\n" + " :type path: string\n" + " :arg coerce: optional argument, when True, the property will be converted\n" + " into its python representation.\n" + " :type coerce: boolean\n"); static PyObject *pyrna_struct_path_resolve(BPy_StructRNA *self, PyObject *args) { - const char *path; - PyObject *coerce = Py_True; - PointerRNA r_ptr; - PropertyRNA *r_prop; - int index = -1; - - PYRNA_STRUCT_CHECK_OBJ(self); - - if (!PyArg_ParseTuple(args, "s|O!:path_resolve", &path, &PyBool_Type, &coerce)) { - return NULL; - } - - if (RNA_path_resolve_full(&self->ptr, path, &r_ptr, &r_prop, &index)) { - if (r_prop) { - if (index != -1) { - if (index >= RNA_property_array_length(&r_ptr, r_prop) || index < 0) { - PyErr_Format(PyExc_IndexError, - "%.200s.path_resolve(\"%.200s\") index out of range", - RNA_struct_identifier(self->ptr.type), path); - return NULL; - } - else { - return pyrna_array_index(&r_ptr, r_prop, index); - } - } - else { - if (coerce == Py_False) { - return pyrna_prop_CreatePyObject(&r_ptr, r_prop); - } - else { - return pyrna_prop_to_py(&r_ptr, r_prop); - } - } - } - else { - return pyrna_struct_CreatePyObject(&r_ptr); - } - } - else { - PyErr_Format(PyExc_ValueError, - "%.200s.path_resolve(\"%.200s\") could not be resolved", - RNA_struct_identifier(self->ptr.type), path); - return NULL; - } + const char *path; + PyObject *coerce = Py_True; + PointerRNA r_ptr; + PropertyRNA *r_prop; + int index = -1; + + PYRNA_STRUCT_CHECK_OBJ(self); + + if (!PyArg_ParseTuple(args, "s|O!:path_resolve", &path, &PyBool_Type, &coerce)) { + return NULL; + } + + if (RNA_path_resolve_full(&self->ptr, path, &r_ptr, &r_prop, &index)) { + if (r_prop) { + if (index != -1) { + if (index >= RNA_property_array_length(&r_ptr, r_prop) || index < 0) { + PyErr_Format(PyExc_IndexError, + "%.200s.path_resolve(\"%.200s\") index out of range", + RNA_struct_identifier(self->ptr.type), + path); + return NULL; + } + else { + return pyrna_array_index(&r_ptr, r_prop, index); + } + } + else { + if (coerce == Py_False) { + return pyrna_prop_CreatePyObject(&r_ptr, r_prop); + } + else { + return pyrna_prop_to_py(&r_ptr, r_prop); + } + } + } + else { + return pyrna_struct_CreatePyObject(&r_ptr); + } + } + else { + PyErr_Format(PyExc_ValueError, + "%.200s.path_resolve(\"%.200s\") could not be resolved", + RNA_struct_identifier(self->ptr.type), + path); + return NULL; + } } PyDoc_STRVAR(pyrna_struct_path_from_id_doc, -".. method:: path_from_id(property=\"\")\n" -"\n" -" Returns the data path from the ID to this object (string).\n" -"\n" -" :arg property: Optional property name which can be used if the path is\n" -" to a property of this object.\n" -" :type property: string\n" -" :return: The path from :class:`bpy.types.bpy_struct.id_data`\n" -" to this struct and property (when given).\n" -" :rtype: str\n" -); + ".. method:: path_from_id(property=\"\")\n" + "\n" + " Returns the data path from the ID to this object (string).\n" + "\n" + " :arg property: Optional property name which can be used if the path is\n" + " to a property of this object.\n" + " :type property: string\n" + " :return: The path from :class:`bpy.types.bpy_struct.id_data`\n" + " to this struct and property (when given).\n" + " :rtype: str\n"); static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args) { - const char *name = NULL; - const char *path; - PropertyRNA *prop; - PyObject *ret; - - PYRNA_STRUCT_CHECK_OBJ(self); - - if (!PyArg_ParseTuple(args, "|s:path_from_id", &name)) { - return NULL; - } - - if (name) { - prop = RNA_struct_find_property(&self->ptr, name); - if (prop == NULL) { - PyErr_Format(PyExc_AttributeError, - "%.200s.path_from_id(\"%.200s\") not found", - RNA_struct_identifier(self->ptr.type), name); - return NULL; - } - - path = RNA_path_from_ID_to_property(&self->ptr, prop); - } - else { - path = RNA_path_from_ID_to_struct(&self->ptr); - } - - if (path == NULL) { - if (name) { - PyErr_Format(PyExc_ValueError, - "%.200s.path_from_id(\"%s\") found but does not support path creation", - RNA_struct_identifier(self->ptr.type), name); - } - else { - PyErr_Format(PyExc_ValueError, - "%.200s.path_from_id() does not support path creation for this type", - RNA_struct_identifier(self->ptr.type)); - } - return NULL; - } - - ret = PyUnicode_FromString(path); - MEM_freeN((void *)path); - - return ret; + const char *name = NULL; + const char *path; + PropertyRNA *prop; + PyObject *ret; + + PYRNA_STRUCT_CHECK_OBJ(self); + + if (!PyArg_ParseTuple(args, "|s:path_from_id", &name)) { + return NULL; + } + + if (name) { + prop = RNA_struct_find_property(&self->ptr, name); + if (prop == NULL) { + PyErr_Format(PyExc_AttributeError, + "%.200s.path_from_id(\"%.200s\") not found", + RNA_struct_identifier(self->ptr.type), + name); + return NULL; + } + + path = RNA_path_from_ID_to_property(&self->ptr, prop); + } + else { + path = RNA_path_from_ID_to_struct(&self->ptr); + } + + if (path == NULL) { + if (name) { + PyErr_Format(PyExc_ValueError, + "%.200s.path_from_id(\"%s\") found but does not support path creation", + RNA_struct_identifier(self->ptr.type), + name); + } + else { + PyErr_Format(PyExc_ValueError, + "%.200s.path_from_id() does not support path creation for this type", + RNA_struct_identifier(self->ptr.type)); + } + return NULL; + } + + ret = PyUnicode_FromString(path); + MEM_freeN((void *)path); + + return ret; } PyDoc_STRVAR(pyrna_prop_path_from_id_doc, -".. method:: path_from_id()\n" -"\n" -" Returns the data path from the ID to this property (string).\n" -"\n" -" :return: The path from :class:`bpy.types.bpy_struct.id_data` to this property.\n" -" :rtype: str\n" -); + ".. method:: path_from_id()\n" + "\n" + " Returns the data path from the ID to this property (string).\n" + "\n" + " :return: The path from :class:`bpy.types.bpy_struct.id_data` to this property.\n" + " :rtype: str\n"); static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self) { - const char *path; - PropertyRNA *prop = self->prop; - PyObject *ret; + const char *path; + PropertyRNA *prop = self->prop; + PyObject *ret; - path = RNA_path_from_ID_to_property(&self->ptr, self->prop); + path = RNA_path_from_ID_to_property(&self->ptr, self->prop); - if (path == NULL) { - PyErr_Format(PyExc_ValueError, - "%.200s.%.200s.path_from_id() does not support path creation for this type", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(prop)); - return NULL; - } + if (path == NULL) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s.path_from_id() does not support path creation for this type", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(prop)); + return NULL; + } - ret = PyUnicode_FromString(path); - MEM_freeN((void *)path); + ret = PyUnicode_FromString(path); + MEM_freeN((void *)path); - return ret; + return ret; } PyDoc_STRVAR(pyrna_prop_as_bytes_doc, -".. method:: as_bytes()\n" -"\n" -" Returns this string property as a byte rather than a python string.\n" -"\n" -" :return: The string as bytes.\n" -" :rtype: bytes\n" -); + ".. method:: as_bytes()\n" + "\n" + " Returns this string property as a byte rather than a python string.\n" + "\n" + " :return: The string as bytes.\n" + " :rtype: bytes\n"); static PyObject *pyrna_prop_as_bytes(BPy_PropertyRNA *self) { - if (RNA_property_type(self->prop) != PROP_STRING) { - PyErr_Format(PyExc_TypeError, - "%.200s.%.200s.as_bytes() must be a string", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop)); - return NULL; - } - else { - PyObject *ret; - char buf_fixed[256], *buf; - int buf_len; + if (RNA_property_type(self->prop) != PROP_STRING) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s.as_bytes() must be a string", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop)); + return NULL; + } + else { + PyObject *ret; + char buf_fixed[256], *buf; + int buf_len; - buf = RNA_property_string_get_alloc(&self->ptr, self->prop, buf_fixed, sizeof(buf_fixed), &buf_len); + buf = RNA_property_string_get_alloc( + &self->ptr, self->prop, buf_fixed, sizeof(buf_fixed), &buf_len); - ret = PyBytes_FromStringAndSize(buf, buf_len); + ret = PyBytes_FromStringAndSize(buf, buf_len); - if (buf_fixed != buf) { - MEM_freeN(buf); - } + if (buf_fixed != buf) { + MEM_freeN(buf); + } - return ret; - } + return ret; + } } PyDoc_STRVAR(pyrna_prop_update_doc, -".. method:: update()\n" -"\n" -" Execute the properties update callback.\n" -"\n" -" .. note::\n" -" This is called when assigning a property,\n" -" however in rare cases its useful to call explicitly.\n" -); + ".. method:: update()\n" + "\n" + " Execute the properties update callback.\n" + "\n" + " .. note::\n" + " This is called when assigning a property,\n" + " however in rare cases its useful to call explicitly.\n"); static PyObject *pyrna_prop_update(BPy_PropertyRNA *self) { - RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); - Py_RETURN_NONE; + RNA_property_update(BPy_GetContext(), &self->ptr, self->prop); + Py_RETURN_NONE; } PyDoc_STRVAR(pyrna_struct_type_recast_doc, -".. method:: type_recast()\n" -"\n" -" Return a new instance, this is needed because types\n" -" such as textures can be changed at runtime.\n" -"\n" -" :return: a new instance of this object with the type initialized again.\n" -" :rtype: subclass of :class:`bpy.types.bpy_struct`\n" -); + ".. method:: type_recast()\n" + "\n" + " Return a new instance, this is needed because types\n" + " such as textures can be changed at runtime.\n" + "\n" + " :return: a new instance of this object with the type initialized again.\n" + " :rtype: subclass of :class:`bpy.types.bpy_struct`\n"); static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self) { - PointerRNA r_ptr; + PointerRNA r_ptr; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - RNA_pointer_recast(&self->ptr, &r_ptr); - return pyrna_struct_CreatePyObject(&r_ptr); + RNA_pointer_recast(&self->ptr, &r_ptr); + return pyrna_struct_CreatePyObject(&r_ptr); } /** @@ -3889,1441 +3941,1445 @@ static PyObject *pyrna_struct_type_recast(BPy_StructRNA *self) */ static PyObject *pyrna_struct_bl_rna_find_subclass_recursive(PyObject *cls, const char *id) { - PyObject *ret_test = NULL; - PyObject *subclasses = ((PyTypeObject *)cls)->tp_subclasses; - if (subclasses) { - /* Unfortunately we can't use the dict key because Python class names - * don't match the bl_idname used internally. */ - BLI_assert(PyDict_CheckExact(subclasses)); - PyObject *key = NULL; - Py_ssize_t pos = 0; - PyObject *value = NULL; - while (PyDict_Next(subclasses, &pos, &key, &value)) { - BLI_assert(PyWeakref_CheckRef(value)); - PyObject *subcls = PyWeakref_GET_OBJECT(value); - if (subcls != Py_None) { - BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem( - ((PyTypeObject *)subcls)->tp_dict, bpy_intern_str_bl_rna); - if (py_srna) { - StructRNA *srna = py_srna->ptr.data; - if (STREQ(id, RNA_struct_identifier(srna))) { - ret_test = subcls; - break; - } - } - ret_test = pyrna_struct_bl_rna_find_subclass_recursive(subcls, id); - if (ret_test) { - break; - } - } - } - } - return ret_test; + PyObject *ret_test = NULL; + PyObject *subclasses = ((PyTypeObject *)cls)->tp_subclasses; + if (subclasses) { + /* Unfortunately we can't use the dict key because Python class names + * don't match the bl_idname used internally. */ + BLI_assert(PyDict_CheckExact(subclasses)); + PyObject *key = NULL; + Py_ssize_t pos = 0; + PyObject *value = NULL; + while (PyDict_Next(subclasses, &pos, &key, &value)) { + BLI_assert(PyWeakref_CheckRef(value)); + PyObject *subcls = PyWeakref_GET_OBJECT(value); + if (subcls != Py_None) { + BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)subcls)->tp_dict, + bpy_intern_str_bl_rna); + if (py_srna) { + StructRNA *srna = py_srna->ptr.data; + if (STREQ(id, RNA_struct_identifier(srna))) { + ret_test = subcls; + break; + } + } + ret_test = pyrna_struct_bl_rna_find_subclass_recursive(subcls, id); + if (ret_test) { + break; + } + } + } + } + return ret_test; } PyDoc_STRVAR(pyrna_struct_bl_rna_get_subclass_py_doc, -".. classmethod:: bl_rna_get_subclass_py(id, default=None)\n" -"\n" -" :arg id: The RNA type identifier.\n" -" :type id: string\n" -" :return: The class or default when not found.\n" -" :rtype: type\n" -); + ".. classmethod:: bl_rna_get_subclass_py(id, default=None)\n" + "\n" + " :arg id: The RNA type identifier.\n" + " :type id: string\n" + " :return: The class or default when not found.\n" + " :rtype: type\n"); static PyObject *pyrna_struct_bl_rna_get_subclass_py(PyObject *cls, PyObject *args) { - char *id; - PyObject *ret_default = Py_None; + char *id; + PyObject *ret_default = Py_None; - if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass_py", &id, &ret_default)) { - return NULL; - } - PyObject *ret = pyrna_struct_bl_rna_find_subclass_recursive(cls, id); - if (ret == NULL) { - ret = ret_default; - } - return Py_INCREF_RET(ret); + if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass_py", &id, &ret_default)) { + return NULL; + } + PyObject *ret = pyrna_struct_bl_rna_find_subclass_recursive(cls, id); + if (ret == NULL) { + ret = ret_default; + } + return Py_INCREF_RET(ret); } PyDoc_STRVAR(pyrna_struct_bl_rna_get_subclass_doc, -".. classmethod:: bl_rna_get_subclass(id, default=None)\n" -"\n" -" :arg id: The RNA type identifier.\n" -" :type id: string\n" -" :return: The RNA type or default when not found.\n" -" :rtype: :class:`bpy.types.Struct` subclass\n" -); + ".. classmethod:: bl_rna_get_subclass(id, default=None)\n" + "\n" + " :arg id: The RNA type identifier.\n" + " :type id: string\n" + " :return: The RNA type or default when not found.\n" + " :rtype: :class:`bpy.types.Struct` subclass\n"); static PyObject *pyrna_struct_bl_rna_get_subclass(PyObject *cls, PyObject *args) { - char *id; - PyObject *ret_default = Py_None; - - if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass", &id, &ret_default)) { - return NULL; - } - - - const BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)cls)->tp_dict, bpy_intern_str_bl_rna); - if (py_srna == NULL) { - PyErr_SetString(PyExc_ValueError, "Not a registered class"); - return NULL; - - } - const StructRNA *srna_base = py_srna->ptr.data; - - PointerRNA ptr; - if (srna_base == &RNA_Node) { - bNodeType *nt = nodeTypeFind(id); - if (nt) { - RNA_pointer_create(NULL, &RNA_Struct, nt->ext.srna, &ptr); - return pyrna_struct_CreatePyObject(&ptr); - } - } - else { - /* TODO, panels, menus etc. */ - PyErr_Format(PyExc_ValueError, "Class type \"%.200s\" not supported", - RNA_struct_identifier(srna_base)); - return NULL; - } - - return Py_INCREF_RET(ret_default); + char *id; + PyObject *ret_default = Py_None; + + if (!PyArg_ParseTuple(args, "s|O:bl_rna_get_subclass", &id, &ret_default)) { + return NULL; + } + + const BPy_StructRNA *py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)cls)->tp_dict, + bpy_intern_str_bl_rna); + if (py_srna == NULL) { + PyErr_SetString(PyExc_ValueError, "Not a registered class"); + return NULL; + } + const StructRNA *srna_base = py_srna->ptr.data; + + PointerRNA ptr; + if (srna_base == &RNA_Node) { + bNodeType *nt = nodeTypeFind(id); + if (nt) { + RNA_pointer_create(NULL, &RNA_Struct, nt->ext.srna, &ptr); + return pyrna_struct_CreatePyObject(&ptr); + } + } + else { + /* TODO, panels, menus etc. */ + PyErr_Format( + PyExc_ValueError, "Class type \"%.200s\" not supported", RNA_struct_identifier(srna_base)); + return NULL; + } + + return Py_INCREF_RET(ret_default); } static void pyrna_dir_members_py__add_keys(PyObject *list, PyObject *dict) { - PyObject *list_tmp; + PyObject *list_tmp; - list_tmp = PyDict_Keys(dict); - PyList_SetSlice(list, INT_MAX, INT_MAX, list_tmp); - Py_DECREF(list_tmp); + list_tmp = PyDict_Keys(dict); + PyList_SetSlice(list, INT_MAX, INT_MAX, list_tmp); + Py_DECREF(list_tmp); } static void pyrna_dir_members_py(PyObject *list, PyObject *self) { - PyObject *dict; - PyObject **dict_ptr; + PyObject *dict; + PyObject **dict_ptr; - dict_ptr = _PyObject_GetDictPtr((PyObject *)self); + dict_ptr = _PyObject_GetDictPtr((PyObject *)self); - if (dict_ptr && (dict = *dict_ptr)) { - pyrna_dir_members_py__add_keys(list, dict); - } + if (dict_ptr && (dict = *dict_ptr)) { + pyrna_dir_members_py__add_keys(list, dict); + } - dict = ((PyTypeObject *)Py_TYPE(self))->tp_dict; - if (dict) { - pyrna_dir_members_py__add_keys(list, dict); - } + dict = ((PyTypeObject *)Py_TYPE(self))->tp_dict; + if (dict) { + pyrna_dir_members_py__add_keys(list, dict); + } - /* since this is least common case, handle it last */ - if (BPy_PropertyRNA_Check(self)) { - BPy_PropertyRNA *self_prop = (BPy_PropertyRNA *)self; - if (RNA_property_type(self_prop->prop) == PROP_COLLECTION) { - PointerRNA r_ptr; + /* since this is least common case, handle it last */ + if (BPy_PropertyRNA_Check(self)) { + BPy_PropertyRNA *self_prop = (BPy_PropertyRNA *)self; + if (RNA_property_type(self_prop->prop) == PROP_COLLECTION) { + PointerRNA r_ptr; - if (RNA_property_collection_type_get(&self_prop->ptr, self_prop->prop, &r_ptr)) { - PyObject *cls = pyrna_struct_Subtype(&r_ptr); /* borrows */ - dict = ((PyTypeObject *)cls)->tp_dict; - pyrna_dir_members_py__add_keys(list, dict); - Py_DECREF(cls); - } - } - } + if (RNA_property_collection_type_get(&self_prop->ptr, self_prop->prop, &r_ptr)) { + PyObject *cls = pyrna_struct_Subtype(&r_ptr); /* borrows */ + dict = ((PyTypeObject *)cls)->tp_dict; + pyrna_dir_members_py__add_keys(list, dict); + Py_DECREF(cls); + } + } + } } static void pyrna_dir_members_rna(PyObject *list, PointerRNA *ptr) { - const char *idname; + const char *idname; - /* for looping over attrs and funcs */ - PointerRNA tptr; - PropertyRNA *iterprop; + /* for looping over attrs and funcs */ + PointerRNA tptr; + PropertyRNA *iterprop; - { - RNA_pointer_create(NULL, &RNA_Struct, ptr->type, &tptr); - iterprop = RNA_struct_find_property(&tptr, "functions"); + { + RNA_pointer_create(NULL, &RNA_Struct, ptr->type, &tptr); + iterprop = RNA_struct_find_property(&tptr, "functions"); - RNA_PROP_BEGIN (&tptr, itemptr, iterprop) - { - FunctionRNA *func = itemptr.data; - if (RNA_function_defined(func)) { - idname = RNA_function_identifier(itemptr.data); - PyList_APPEND(list, PyUnicode_FromString(idname)); - } - } - RNA_PROP_END; - } + RNA_PROP_BEGIN (&tptr, itemptr, iterprop) { + FunctionRNA *func = itemptr.data; + if (RNA_function_defined(func)) { + idname = RNA_function_identifier(itemptr.data); + PyList_APPEND(list, PyUnicode_FromString(idname)); + } + } + RNA_PROP_END; + } - { - /* - * Collect RNA attributes - */ - char name[256], *nameptr; - int namelen; + { + /* + * Collect RNA attributes + */ + char name[256], *nameptr; + int namelen; - iterprop = RNA_struct_iterator_property(ptr->type); + iterprop = RNA_struct_iterator_property(ptr->type); - RNA_PROP_BEGIN (ptr, itemptr, iterprop) - { - nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); + RNA_PROP_BEGIN (ptr, itemptr, iterprop) { + nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); - if (nameptr) { - PyList_APPEND(list, PyUnicode_FromStringAndSize(nameptr, namelen)); + if (nameptr) { + PyList_APPEND(list, PyUnicode_FromStringAndSize(nameptr, namelen)); - if (name != nameptr) { - MEM_freeN(nameptr); - } - } - } - RNA_PROP_END; - } + if (name != nameptr) { + MEM_freeN(nameptr); + } + } + } + RNA_PROP_END; + } } - static PyObject *pyrna_struct_dir(BPy_StructRNA *self) { - PyObject *ret; + PyObject *ret; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - /* Include this in case this instance is a subtype of a python class - * In these instances we may want to return a function or variable provided by the subtype - * */ - ret = PyList_New(0); + /* Include this in case this instance is a subtype of a python class + * In these instances we may want to return a function or variable provided by the subtype + * */ + ret = PyList_New(0); - if (!BPy_StructRNA_CheckExact(self)) { - pyrna_dir_members_py(ret, (PyObject *)self); - } + if (!BPy_StructRNA_CheckExact(self)) { + pyrna_dir_members_py(ret, (PyObject *)self); + } - pyrna_dir_members_rna(ret, &self->ptr); + pyrna_dir_members_rna(ret, &self->ptr); - if (self->ptr.type == &RNA_Context) { - ListBase lb = CTX_data_dir_get(self->ptr.data); - LinkData *link; + if (self->ptr.type == &RNA_Context) { + ListBase lb = CTX_data_dir_get(self->ptr.data); + LinkData *link; - for (link = lb.first; link; link = link->next) { - PyList_APPEND(ret, PyUnicode_FromString(link->data)); - } + for (link = lb.first; link; link = link->next) { + PyList_APPEND(ret, PyUnicode_FromString(link->data)); + } - BLI_freelistN(&lb); - } + BLI_freelistN(&lb); + } - { - /* set(), this is needed to remove-doubles because the deferred - * register-props will be in both the python __dict__ and accessed as RNA */ + { + /* set(), this is needed to remove-doubles because the deferred + * register-props will be in both the python __dict__ and accessed as RNA */ - PyObject *set = PySet_New(ret); + PyObject *set = PySet_New(ret); - Py_DECREF(ret); - ret = PySequence_List(set); - Py_DECREF(set); - } + Py_DECREF(ret); + ret = PySequence_List(set); + Py_DECREF(set); + } - return ret; + return ret; } /* ---------------getattr-------------------------------------------- */ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) { - const char *name = _PyUnicode_AsString(pyname); - PyObject *ret; - PropertyRNA *prop; - FunctionRNA *func; - - PYRNA_STRUCT_CHECK_OBJ(self); - - if (name == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_struct: __getattr__ must be a string"); - ret = NULL; - } - else if (name[0] == '_') { /* rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups */ - /* annoying exception, maybe we need to have different types for this... */ - if (STR_ELEM(name, "__getitem__", "__setitem__") && !RNA_struct_idprops_check(self->ptr.type)) { - PyErr_SetString(PyExc_AttributeError, "bpy_struct: no __getitem__ support for this type"); - ret = NULL; - } - else { - ret = PyObject_GenericGetAttr((PyObject *)self, pyname); - } - } - else if ((prop = RNA_struct_find_property(&self->ptr, name))) { - ret = pyrna_prop_to_py(&self->ptr, prop); - } - /* RNA function only if callback is declared (no optional functions) */ - else if ((func = RNA_struct_find_function(self->ptr.type, name)) && RNA_function_defined(func)) { - ret = pyrna_func_to_py(&self->ptr, func); - } - else if (self->ptr.type == &RNA_Context) { - bContext *C = self->ptr.data; - if (C == NULL) { - PyErr_Format(PyExc_AttributeError, - "bpy_struct: Context is 'NULL', can't get \"%.200s\" from context", - name); - ret = NULL; - } - else { - PointerRNA newptr; - ListBase newlb; - short newtype; - - int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); - - if (done == 1) { /* found */ - switch (newtype) { - case CTX_DATA_TYPE_POINTER: - if (newptr.data == NULL) { - ret = Py_None; - Py_INCREF(ret); - } - else { - ret = pyrna_struct_CreatePyObject(&newptr); - } - break; - case CTX_DATA_TYPE_COLLECTION: - { - CollectionPointerLink *link; - - ret = PyList_New(0); - - for (link = newlb.first; link; link = link->next) { - PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr)); - } - break; - } - default: - /* should never happen */ - BLI_assert(!"Invalid context type"); - - PyErr_Format(PyExc_AttributeError, - "bpy_struct: Context type invalid %d, can't get \"%.200s\" from context", - newtype, name); - ret = NULL; - break; - } - } - 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); - } - } - else { + const char *name = _PyUnicode_AsString(pyname); + PyObject *ret; + PropertyRNA *prop; + FunctionRNA *func; + + PYRNA_STRUCT_CHECK_OBJ(self); + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_struct: __getattr__ must be a string"); + ret = NULL; + } + else if ( + name[0] == + '_') { /* rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups */ + /* annoying exception, maybe we need to have different types for this... */ + if (STR_ELEM(name, "__getitem__", "__setitem__") && + !RNA_struct_idprops_check(self->ptr.type)) { + PyErr_SetString(PyExc_AttributeError, "bpy_struct: no __getitem__ support for this type"); + ret = NULL; + } + else { + ret = PyObject_GenericGetAttr((PyObject *)self, pyname); + } + } + else if ((prop = RNA_struct_find_property(&self->ptr, name))) { + ret = pyrna_prop_to_py(&self->ptr, prop); + } + /* RNA function only if callback is declared (no optional functions) */ + else if ((func = RNA_struct_find_function(self->ptr.type, name)) && RNA_function_defined(func)) { + ret = pyrna_func_to_py(&self->ptr, func); + } + else if (self->ptr.type == &RNA_Context) { + bContext *C = self->ptr.data; + if (C == NULL) { + PyErr_Format(PyExc_AttributeError, + "bpy_struct: Context is 'NULL', can't get \"%.200s\" from context", + name); + ret = NULL; + } + else { + PointerRNA newptr; + ListBase newlb; + short newtype; + + int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); + + if (done == 1) { /* found */ + switch (newtype) { + case CTX_DATA_TYPE_POINTER: + if (newptr.data == NULL) { + ret = Py_None; + Py_INCREF(ret); + } + else { + ret = pyrna_struct_CreatePyObject(&newptr); + } + break; + case CTX_DATA_TYPE_COLLECTION: { + CollectionPointerLink *link; + + ret = PyList_New(0); + + for (link = newlb.first; link; link = link->next) { + PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr)); + } + break; + } + default: + /* should never happen */ + BLI_assert(!"Invalid context type"); + + PyErr_Format(PyExc_AttributeError, + "bpy_struct: Context type invalid %d, can't get \"%.200s\" from context", + newtype, + name); + ret = NULL; + break; + } + } + 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); + } + } + else { #if 0 - PyErr_Format(PyExc_AttributeError, - "bpy_struct: attribute \"%.200s\" not found", - name); - ret = NULL; + PyErr_Format(PyExc_AttributeError, + "bpy_struct: attribute \"%.200s\" not found", + name); + ret = NULL; #endif - /* Include this in case this instance is a subtype of a python class - * In these instances we may want to return a function or variable provided by the subtype - * - * Also needed to return methods when its not a subtype - * */ + /* Include this in case this instance is a subtype of a python class + * In these instances we may want to return a function or variable provided by the subtype + * + * Also needed to return methods when its not a subtype + * */ - /* The error raised here will be displayed */ - ret = PyObject_GenericGetAttr((PyObject *)self, pyname); - } + /* The error raised here will be displayed */ + ret = PyObject_GenericGetAttr((PyObject *)self, pyname); + } - return ret; + return ret; } #if 0 static int pyrna_struct_pydict_contains(PyObject *self, PyObject *pyname) { - PyObject *dict = *(_PyObject_GetDictPtr((PyObject *)self)); - if (dict == NULL) /* unlikely */ - return 0; + PyObject *dict = *(_PyObject_GetDictPtr((PyObject *)self)); + if (dict == NULL) /* unlikely */ + return 0; - return PyDict_Contains(dict, pyname); + return PyDict_Contains(dict, pyname); } #endif /* --------------- setattr------------------------------------------- */ static bool pyrna_is_deferred_prop(const PyObject *value) { - return PyTuple_CheckExact(value) && - PyTuple_GET_SIZE(value) == 2 && - PyCFunction_Check(PyTuple_GET_ITEM(value, 0)) && - PyDict_CheckExact(PyTuple_GET_ITEM(value, 1)); + return PyTuple_CheckExact(value) && PyTuple_GET_SIZE(value) == 2 && + PyCFunction_Check(PyTuple_GET_ITEM(value, 0)) && + PyDict_CheckExact(PyTuple_GET_ITEM(value, 1)); } #if 0 static PyObject *pyrna_struct_meta_idprop_getattro(PyObject *cls, PyObject *attr) { - PyObject *ret = PyType_Type.tp_getattro(cls, attr); - - /* Allows: - * >>> bpy.types.Scene.foo = BoolProperty() - * >>> bpy.types.Scene.foo - * <bpy_struct, BoolProperty("foo")> - * ...rather than returning the deferred class register tuple as checked by pyrna_is_deferred_prop() - * - * Disable for now, this is faking internal behavior in a way that's too tricky to maintain well. */ -#if 0 - if (ret == NULL) { // || pyrna_is_deferred_prop(ret) - StructRNA *srna = srna_from_self(cls, "StructRNA.__getattr__"); - if (srna) { - PropertyRNA *prop = RNA_struct_type_find_property(srna, _PyUnicode_AsString(attr)); - if (prop) { - PointerRNA tptr; - PyErr_Clear(); /* clear error from tp_getattro */ - RNA_pointer_create(NULL, &RNA_Property, prop, &tptr); - ret = pyrna_struct_CreatePyObject(&tptr); - } - } - } -#endif - - return ret; + PyObject *ret = PyType_Type.tp_getattro(cls, attr); + + /* Allows: + * >>> bpy.types.Scene.foo = BoolProperty() + * >>> bpy.types.Scene.foo + * <bpy_struct, BoolProperty("foo")> + * ...rather than returning the deferred class register tuple as checked by pyrna_is_deferred_prop() + * + * Disable for now, this is faking internal behavior in a way that's too tricky to maintain well. */ +# if 0 + if (ret == NULL) { // || pyrna_is_deferred_prop(ret) + StructRNA *srna = srna_from_self(cls, "StructRNA.__getattr__"); + if (srna) { + PropertyRNA *prop = RNA_struct_type_find_property(srna, _PyUnicode_AsString(attr)); + if (prop) { + PointerRNA tptr; + PyErr_Clear(); /* clear error from tp_getattro */ + RNA_pointer_create(NULL, &RNA_Property, prop, &tptr); + ret = pyrna_struct_CreatePyObject(&tptr); + } + } + } +# endif + + return ret; } #endif static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyObject *value) { - StructRNA *srna = srna_from_self(cls, "StructRNA.__setattr__"); - const bool is_deferred_prop = (value && pyrna_is_deferred_prop(value)); - const char *attr_str = _PyUnicode_AsString(attr); - - if (srna && !pyrna_write_check() && (is_deferred_prop || RNA_struct_type_find_property(srna, attr_str))) { - PyErr_Format(PyExc_AttributeError, - "pyrna_struct_meta_idprop_setattro() " - "can't set in readonly state '%.200s.%S'", - ((PyTypeObject *)cls)->tp_name, attr); - return -1; - } - - if (srna == NULL) { - /* allow setting on unregistered classes which can be registered later on */ + StructRNA *srna = srna_from_self(cls, "StructRNA.__setattr__"); + const bool is_deferred_prop = (value && pyrna_is_deferred_prop(value)); + const char *attr_str = _PyUnicode_AsString(attr); + + if (srna && !pyrna_write_check() && + (is_deferred_prop || RNA_struct_type_find_property(srna, attr_str))) { + PyErr_Format(PyExc_AttributeError, + "pyrna_struct_meta_idprop_setattro() " + "can't set in readonly state '%.200s.%S'", + ((PyTypeObject *)cls)->tp_name, + attr); + return -1; + } + + if (srna == NULL) { + /* allow setting on unregistered classes which can be registered later on */ #if 0 - if (value && is_deferred_prop) { - PyErr_Format(PyExc_AttributeError, - "pyrna_struct_meta_idprop_setattro() unable to get srna from class '%.200s'", - ((PyTypeObject *)cls)->tp_name); - return -1; - } + if (value && is_deferred_prop) { + PyErr_Format(PyExc_AttributeError, + "pyrna_struct_meta_idprop_setattro() unable to get srna from class '%.200s'", + ((PyTypeObject *)cls)->tp_name); + return -1; + } #endif - /* srna_from_self may set an error */ - PyErr_Clear(); - return PyType_Type.tp_setattro(cls, attr, value); - } - - if (value) { - /* check if the value is a property */ - if (is_deferred_prop) { - int ret = deferred_register_prop(srna, attr, value); - if (ret == -1) { - /* error set */ - return ret; - } - - /* pass through and assign to the classes __dict__ as well - * when the value isn't assigned it still creates the RNA property - * but gets confusing from script writers POV if the assigned value cant be read back. */ - } - else { - /* remove existing property if its set or we also end up with confusion */ - RNA_def_property_free_identifier(srna, attr_str); /* ignore on failure */ - } - } - else { /* __delattr__ */ - /* first find if this is a registered property */ - const int ret = RNA_def_property_free_identifier(srna, attr_str); - if (ret == -1) { - PyErr_Format(PyExc_TypeError, - "struct_meta_idprop.detattr(): '%s' not a dynamic property", - attr_str); - return -1; - } - } - - /* fallback to standard py, delattr/setattr */ - return PyType_Type.tp_setattro(cls, attr, value); + /* srna_from_self may set an error */ + PyErr_Clear(); + return PyType_Type.tp_setattro(cls, attr, value); + } + + if (value) { + /* check if the value is a property */ + if (is_deferred_prop) { + int ret = deferred_register_prop(srna, attr, value); + if (ret == -1) { + /* error set */ + return ret; + } + + /* pass through and assign to the classes __dict__ as well + * when the value isn't assigned it still creates the RNA property + * but gets confusing from script writers POV if the assigned value cant be read back. */ + } + else { + /* remove existing property if its set or we also end up with confusion */ + RNA_def_property_free_identifier(srna, attr_str); /* ignore on failure */ + } + } + else { /* __delattr__ */ + /* first find if this is a registered property */ + const int ret = RNA_def_property_free_identifier(srna, attr_str); + if (ret == -1) { + PyErr_Format( + PyExc_TypeError, "struct_meta_idprop.detattr(): '%s' not a dynamic property", attr_str); + return -1; + } + } + + /* fallback to standard py, delattr/setattr */ + return PyType_Type.tp_setattro(cls, attr, value); } static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject *value) { - const char *name = _PyUnicode_AsString(pyname); - PropertyRNA *prop = NULL; + const char *name = _PyUnicode_AsString(pyname); + PropertyRNA *prop = NULL; - PYRNA_STRUCT_CHECK_INT(self); + PYRNA_STRUCT_CHECK_INT(self); #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ - - if (name == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_struct: __setattr__ must be a string"); - return -1; - } - else if (name[0] != '_' && (prop = RNA_struct_find_property(&self->ptr, name))) { - if (!RNA_property_editable_flag(&self->ptr, prop)) { - PyErr_Format(PyExc_AttributeError, - "bpy_struct: attribute \"%.200s\" from \"%.200s\" is read-only", - RNA_property_identifier(prop), RNA_struct_identifier(self->ptr.type)); - return -1; - } - } - else if (self->ptr.type == &RNA_Context) { - /* code just raises correct error, context prop's cant be set, unless its apart of the py class */ - bContext *C = self->ptr.data; - if (C == NULL) { - PyErr_Format(PyExc_AttributeError, - "bpy_struct: Context is 'NULL', can't set \"%.200s\" from context", - name); - return -1; - } - else { - PointerRNA newptr; - ListBase newlb; - short newtype; - - int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); - - if (done == 1) { - PyErr_Format(PyExc_AttributeError, - "bpy_struct: Context property \"%.200s\" is read-only", - name); - BLI_freelistN(&newlb); - return -1; - } - - BLI_freelistN(&newlb); - } - } - - /* pyrna_py_to_prop sets its own exceptions */ - if (prop) { - if (value == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_struct: del not supported"); - return -1; - } - return pyrna_py_to_prop(&self->ptr, prop, NULL, value, "bpy_struct: item.attr = val:"); - } - else { - return PyObject_GenericSetAttr((PyObject *)self, pyname, value); - } + if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { + return -1; + } +#endif /* USE_PEDANTIC_WRITE */ + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_struct: __setattr__ must be a string"); + return -1; + } + else if (name[0] != '_' && (prop = RNA_struct_find_property(&self->ptr, name))) { + if (!RNA_property_editable_flag(&self->ptr, prop)) { + PyErr_Format(PyExc_AttributeError, + "bpy_struct: attribute \"%.200s\" from \"%.200s\" is read-only", + RNA_property_identifier(prop), + RNA_struct_identifier(self->ptr.type)); + return -1; + } + } + else if (self->ptr.type == &RNA_Context) { + /* code just raises correct error, context prop's cant be set, unless its apart of the py class */ + bContext *C = self->ptr.data; + if (C == NULL) { + PyErr_Format(PyExc_AttributeError, + "bpy_struct: Context is 'NULL', can't set \"%.200s\" from context", + name); + return -1; + } + else { + PointerRNA newptr; + ListBase newlb; + short newtype; + + int done = CTX_data_get(C, name, &newptr, &newlb, &newtype); + + if (done == 1) { + PyErr_Format( + PyExc_AttributeError, "bpy_struct: Context property \"%.200s\" is read-only", name); + BLI_freelistN(&newlb); + return -1; + } + + BLI_freelistN(&newlb); + } + } + + /* pyrna_py_to_prop sets its own exceptions */ + if (prop) { + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_struct: del not supported"); + return -1; + } + return pyrna_py_to_prop(&self->ptr, prop, NULL, value, "bpy_struct: item.attr = val:"); + } + else { + return PyObject_GenericSetAttr((PyObject *)self, pyname, value); + } } static PyObject *pyrna_prop_dir(BPy_PropertyRNA *self) { - PyObject *ret; - PointerRNA r_ptr; + PyObject *ret; + PointerRNA r_ptr; - /* Include this in case this instance is a subtype of a python class - * In these instances we may want to return a function or variable provided by the subtype - * */ - ret = PyList_New(0); + /* Include this in case this instance is a subtype of a python class + * In these instances we may want to return a function or variable provided by the subtype + * */ + ret = PyList_New(0); - if (!BPy_PropertyRNA_CheckExact(self)) { - pyrna_dir_members_py(ret, (PyObject *)self); - } + if (!BPy_PropertyRNA_CheckExact(self)) { + pyrna_dir_members_py(ret, (PyObject *)self); + } - if (RNA_property_type(self->prop) == PROP_COLLECTION) { - if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - pyrna_dir_members_rna(ret, &r_ptr); - } - } + if (RNA_property_type(self->prop) == PROP_COLLECTION) { + if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + pyrna_dir_members_rna(ret, &r_ptr); + } + } - return ret; + return ret; } - static PyObject *pyrna_prop_array_getattro(BPy_PropertyRNA *self, PyObject *pyname) { - return PyObject_GenericGetAttr((PyObject *)self, pyname); + return PyObject_GenericGetAttr((PyObject *)self, pyname); } static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject *pyname) { - const char *name = _PyUnicode_AsString(pyname); - - if (name == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_prop_collection: __getattr__ must be a string"); - return NULL; - } - else if (name[0] != '_') { - PyObject *ret; - PropertyRNA *prop; - FunctionRNA *func; - - PointerRNA r_ptr; - if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - if ((prop = RNA_struct_find_property(&r_ptr, name))) { - ret = pyrna_prop_to_py(&r_ptr, prop); - - return ret; - } - else if ((func = RNA_struct_find_function(r_ptr.type, name))) { - PyObject *self_collection = pyrna_struct_CreatePyObject(&r_ptr); - ret = pyrna_func_to_py(&((BPy_DummyPointerRNA *)self_collection)->ptr, func); - Py_DECREF(self_collection); - - return ret; - } - } - } + const char *name = _PyUnicode_AsString(pyname); + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_prop_collection: __getattr__ must be a string"); + return NULL; + } + else if (name[0] != '_') { + PyObject *ret; + PropertyRNA *prop; + FunctionRNA *func; + + PointerRNA r_ptr; + if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + if ((prop = RNA_struct_find_property(&r_ptr, name))) { + ret = pyrna_prop_to_py(&r_ptr, prop); + + return ret; + } + else if ((func = RNA_struct_find_function(r_ptr.type, name))) { + PyObject *self_collection = pyrna_struct_CreatePyObject(&r_ptr); + ret = pyrna_func_to_py(&((BPy_DummyPointerRNA *)self_collection)->ptr, func); + Py_DECREF(self_collection); + + return ret; + } + } + } #if 0 - return PyObject_GenericGetAttr((PyObject *)self, pyname); + return PyObject_GenericGetAttr((PyObject *)self, pyname); #else - { - /* Could just do this except for 1 awkward case. - * PyObject_GenericGetAttr((PyObject *)self, pyname); - * so as to support 'bpy.data.library.load()' - * note, this _only_ supports static methods */ - - PyObject *ret = PyObject_GenericGetAttr((PyObject *)self, pyname); - - if (ret == NULL && name[0] != '_') { /* avoid inheriting __call__ and similar */ - /* since this is least common case, handle it last */ - PointerRNA r_ptr; - if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - PyObject *cls; - - PyObject *error_type, *error_value, *error_traceback; - PyErr_Fetch(&error_type, &error_value, &error_traceback); - PyErr_Clear(); - - cls = pyrna_struct_Subtype(&r_ptr); - ret = PyObject_GenericGetAttr(cls, pyname); - Py_DECREF(cls); - - /* restore the original error */ - if (ret == NULL) { - PyErr_Restore(error_type, error_value, error_traceback); - } - } - } - - return ret; - } + { + /* Could just do this except for 1 awkward case. + * PyObject_GenericGetAttr((PyObject *)self, pyname); + * so as to support 'bpy.data.library.load()' + * note, this _only_ supports static methods */ + + PyObject *ret = PyObject_GenericGetAttr((PyObject *)self, pyname); + + if (ret == NULL && name[0] != '_') { /* avoid inheriting __call__ and similar */ + /* since this is least common case, handle it last */ + PointerRNA r_ptr; + if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + PyObject *cls; + + PyObject *error_type, *error_value, *error_traceback; + PyErr_Fetch(&error_type, &error_value, &error_traceback); + PyErr_Clear(); + + cls = pyrna_struct_Subtype(&r_ptr); + ret = PyObject_GenericGetAttr(cls, pyname); + Py_DECREF(cls); + + /* restore the original error */ + if (ret == NULL) { + PyErr_Restore(error_type, error_value, error_traceback); + } + } + } + + return ret; + } #endif } /* --------------- setattr------------------------------------------- */ static int pyrna_prop_collection_setattro(BPy_PropertyRNA *self, PyObject *pyname, PyObject *value) { - const char *name = _PyUnicode_AsString(pyname); - PropertyRNA *prop; - PointerRNA r_ptr; + const char *name = _PyUnicode_AsString(pyname); + PropertyRNA *prop; + PointerRNA r_ptr; #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { - return -1; - } -#endif /* USE_PEDANTIC_WRITE */ - - if (name == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_prop: __setattr__ must be a string"); - return -1; - } - else if (value == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy_prop: del not supported"); - return -1; - } - else if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { - if ((prop = RNA_struct_find_property(&r_ptr, name))) { - /* pyrna_py_to_prop sets its own exceptions */ - return pyrna_py_to_prop(&r_ptr, prop, NULL, value, "BPy_PropertyRNA - Attribute (setattr):"); - } - } - - PyErr_Format(PyExc_AttributeError, - "bpy_prop_collection: attribute \"%.200s\" not found", - name); - return -1; + if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { + return -1; + } +#endif /* USE_PEDANTIC_WRITE */ + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_prop: __setattr__ must be a string"); + return -1; + } + else if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_prop: del not supported"); + return -1; + } + else if (RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + if ((prop = RNA_struct_find_property(&r_ptr, name))) { + /* pyrna_py_to_prop sets its own exceptions */ + return pyrna_py_to_prop(&r_ptr, prop, NULL, value, "BPy_PropertyRNA - Attribute (setattr):"); + } + } + + PyErr_Format(PyExc_AttributeError, "bpy_prop_collection: attribute \"%.200s\" not found", name); + return -1; } /* odd case, we need to be able return a python method from a tp_getset */ static PyObject *pyrna_prop_collection_idprop_add(BPy_PropertyRNA *self) { - PointerRNA r_ptr; + PointerRNA r_ptr; #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return NULL; - } -#endif /* USE_PEDANTIC_WRITE */ - - RNA_property_collection_add(&self->ptr, self->prop, &r_ptr); - if (!r_ptr.data) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.add(): not supported for this collection"); - return NULL; - } - else { - return pyrna_struct_CreatePyObject(&r_ptr); - } + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ + + RNA_property_collection_add(&self->ptr, self->prop, &r_ptr); + if (!r_ptr.data) { + PyErr_SetString(PyExc_TypeError, + "bpy_prop_collection.add(): not supported for this collection"); + return NULL; + } + else { + return pyrna_struct_CreatePyObject(&r_ptr); + } } static PyObject *pyrna_prop_collection_idprop_remove(BPy_PropertyRNA *self, PyObject *value) { - int key = PyLong_AsLong(value); + int key = PyLong_AsLong(value); #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return NULL; - } -#endif /* USE_PEDANTIC_WRITE */ + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ - if (key == -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.remove(): expected one int argument"); - return NULL; - } + if (key == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.remove(): expected one int argument"); + return NULL; + } - if (!RNA_property_collection_remove(&self->ptr, self->prop, key)) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.remove() not supported for this collection"); - return NULL; - } + if (!RNA_property_collection_remove(&self->ptr, self->prop, key)) { + PyErr_SetString(PyExc_TypeError, + "bpy_prop_collection.remove() not supported for this collection"); + return NULL; + } - Py_RETURN_NONE; + Py_RETURN_NONE; } static PyObject *pyrna_prop_collection_idprop_clear(BPy_PropertyRNA *self) { #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return NULL; - } -#endif /* USE_PEDANTIC_WRITE */ + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ - RNA_property_collection_clear(&self->ptr, self->prop); + RNA_property_collection_clear(&self->ptr, self->prop); - Py_RETURN_NONE; + Py_RETURN_NONE; } static PyObject *pyrna_prop_collection_idprop_move(BPy_PropertyRNA *self, PyObject *args) { - int key = 0, pos = 0; + int key = 0, pos = 0; #ifdef USE_PEDANTIC_WRITE - if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { - return NULL; - } -#endif /* USE_PEDANTIC_WRITE */ + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ - if (!PyArg_ParseTuple(args, "ii", &key, &pos)) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.move(): expected two ints as arguments"); - return NULL; - } + if (!PyArg_ParseTuple(args, "ii", &key, &pos)) { + PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.move(): expected two ints as arguments"); + return NULL; + } - if (!RNA_property_collection_move(&self->ptr, self->prop, key, pos)) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.move() not supported for this collection"); - return NULL; - } + if (!RNA_property_collection_move(&self->ptr, self->prop, key, pos)) { + PyErr_SetString(PyExc_TypeError, + "bpy_prop_collection.move() not supported for this collection"); + return NULL; + } - Py_RETURN_NONE; + Py_RETURN_NONE; } - PyDoc_STRVAR(pyrna_struct_get_id_data_doc, -"The :class:`bpy.types.ID` object this datablock is from or None, (not available for all data types)" -); + "The :class:`bpy.types.ID` object this datablock is from or None, (not available for " + "all data types)"); static PyObject *pyrna_struct_get_id_data(BPy_DummyPointerRNA *self) { - /* used for struct and pointer since both have a ptr */ - 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); - } + /* used for struct and pointer since both have a ptr */ + 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); + } - Py_RETURN_NONE; + Py_RETURN_NONE; } PyDoc_STRVAR(pyrna_struct_get_data_doc, -"The data this property is using, *type* :class:`bpy.types.bpy_struct`" -); + "The data this property is using, *type* :class:`bpy.types.bpy_struct`"); static PyObject *pyrna_struct_get_data(BPy_DummyPointerRNA *self) { - return pyrna_struct_CreatePyObject(&self->ptr); + return pyrna_struct_CreatePyObject(&self->ptr); } -PyDoc_STRVAR(pyrna_struct_get_rna_type_doc, -"The property type for introspection" -); +PyDoc_STRVAR(pyrna_struct_get_rna_type_doc, "The property type for introspection"); static PyObject *pyrna_struct_get_rna_type(BPy_PropertyRNA *self) { - PointerRNA tptr; - RNA_pointer_create(NULL, &RNA_Property, self->prop, &tptr); - return pyrna_struct_Subtype(&tptr); + PointerRNA tptr; + RNA_pointer_create(NULL, &RNA_Property, self->prop, &tptr); + return pyrna_struct_Subtype(&tptr); } - - /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef pyrna_prop_getseters[] = { - {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)pyrna_struct_get_id_data_doc, NULL}, - {(char *)"data", (getter)pyrna_struct_get_data, (setter)NULL, (char *)pyrna_struct_get_data_doc, NULL}, - {(char *)"rna_type", (getter)pyrna_struct_get_rna_type, (setter)NULL, (char *)pyrna_struct_get_rna_type_doc, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {(char *)"id_data", + (getter)pyrna_struct_get_id_data, + (setter)NULL, + (char *)pyrna_struct_get_id_data_doc, + NULL}, + {(char *)"data", + (getter)pyrna_struct_get_data, + (setter)NULL, + (char *)pyrna_struct_get_data_doc, + NULL}, + {(char *)"rna_type", + (getter)pyrna_struct_get_rna_type, + (setter)NULL, + (char *)pyrna_struct_get_rna_type_doc, + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; static PyGetSetDef pyrna_struct_getseters[] = { - {(char *)"id_data", (getter)pyrna_struct_get_id_data, (setter)NULL, (char *)pyrna_struct_get_id_data_doc, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {(char *)"id_data", + (getter)pyrna_struct_get_id_data, + (setter)NULL, + (char *)pyrna_struct_get_id_data_doc, + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void *closure); static PyGetSetDef pyrna_func_getseters[] = { - {(char *)"__doc__", (getter)pyrna_func_doc_get, (setter)NULL, NULL, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {(char *)"__doc__", (getter)pyrna_func_doc_get, (setter)NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; PyDoc_STRVAR(pyrna_prop_collection_keys_doc, -".. method:: keys()\n" -"\n" -" Return the identifiers of collection members\n" -" (matching pythons dict.keys() functionality).\n" -"\n" -" :return: the identifiers for each member of this collection.\n" -" :rtype: list of strings\n" -); + ".. method:: keys()\n" + "\n" + " Return the identifiers of collection members\n" + " (matching pythons dict.keys() functionality).\n" + "\n" + " :return: the identifiers for each member of this collection.\n" + " :rtype: list of strings\n"); static PyObject *pyrna_prop_collection_keys(BPy_PropertyRNA *self) { - PyObject *ret = PyList_New(0); - char name[256], *nameptr; - int namelen; + PyObject *ret = PyList_New(0); + char name[256], *nameptr; + int namelen; - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); - if (nameptr) { - PyList_APPEND(ret, PyUnicode_FromStringAndSize(nameptr, namelen)); + if (nameptr) { + PyList_APPEND(ret, PyUnicode_FromStringAndSize(nameptr, namelen)); - if (name != nameptr) { - MEM_freeN(nameptr); - } - } - } - RNA_PROP_END; + if (name != nameptr) { + MEM_freeN(nameptr); + } + } + } + RNA_PROP_END; - return ret; + return ret; } PyDoc_STRVAR(pyrna_prop_collection_items_doc, -".. method:: items()\n" -"\n" -" Return the identifiers of collection members\n" -" (matching pythons dict.items() functionality).\n" -"\n" -" :return: (key, value) pairs for each member of this collection.\n" -" :rtype: list of tuples\n" -); + ".. method:: items()\n" + "\n" + " Return the identifiers of collection members\n" + " (matching pythons dict.items() functionality).\n" + "\n" + " :return: (key, value) pairs for each member of this collection.\n" + " :rtype: list of tuples\n"); static PyObject *pyrna_prop_collection_items(BPy_PropertyRNA *self) { - PyObject *ret = PyList_New(0); - PyObject *item; - char name[256], *nameptr; - int namelen; - int i = 0; - - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - if (itemptr.data) { - /* add to python list */ - item = PyTuple_New(2); - nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); - if (nameptr) { - PyTuple_SET_ITEM(item, 0, PyUnicode_FromStringAndSize(nameptr, namelen)); - if (name != nameptr) { - MEM_freeN(nameptr); - } - } - else { - /* a bit strange but better then returning an empty list */ - PyTuple_SET_ITEM(item, 0, PyLong_FromLong(i)); - } - PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); - - PyList_APPEND(ret, item); - - i++; - } - } - RNA_PROP_END; - - return ret; + PyObject *ret = PyList_New(0); + PyObject *item; + char name[256], *nameptr; + int namelen; + int i = 0; + + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + if (itemptr.data) { + /* add to python list */ + item = PyTuple_New(2); + nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); + if (nameptr) { + PyTuple_SET_ITEM(item, 0, PyUnicode_FromStringAndSize(nameptr, namelen)); + if (name != nameptr) { + MEM_freeN(nameptr); + } + } + else { + /* a bit strange but better then returning an empty list */ + PyTuple_SET_ITEM(item, 0, PyLong_FromLong(i)); + } + PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); + + PyList_APPEND(ret, item); + + i++; + } + } + RNA_PROP_END; + + return ret; } PyDoc_STRVAR(pyrna_prop_collection_values_doc, -".. method:: values()\n" -"\n" -" Return the values of collection\n" -" (matching pythons dict.values() functionality).\n" -"\n" -" :return: the members of this collection.\n" -" :rtype: list\n" -); + ".. method:: values()\n" + "\n" + " Return the values of collection\n" + " (matching pythons dict.values() functionality).\n" + "\n" + " :return: the members of this collection.\n" + " :rtype: list\n"); static PyObject *pyrna_prop_collection_values(BPy_PropertyRNA *self) { - /* re-use slice*/ - return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); + /* re-use slice*/ + return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX); } PyDoc_STRVAR(pyrna_struct_get_doc, -".. method:: get(key, default=None)\n" -"\n" -" Returns the value of the custom property assigned to key or default\n" -" when not found (matches pythons dictionary function of the same name).\n" -"\n" -" :arg key: The key associated with the custom property.\n" -" :type key: string\n" -" :arg default: Optional argument for the value to return if\n" -" *key* is not found.\n" -" :type default: Undefined\n" -"\n" -BPY_DOC_ID_PROP_TYPE_NOTE -); + ".. method:: get(key, default=None)\n" + "\n" + " Returns the value of the custom property assigned to key or default\n" + " when not found (matches pythons dictionary function of the same name).\n" + "\n" + " :arg key: The key associated with the custom property.\n" + " :type key: string\n" + " :arg default: Optional argument for the value to return if\n" + " *key* is not found.\n" + " :type default: Undefined\n" + "\n" BPY_DOC_ID_PROP_TYPE_NOTE); static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args) { - IDProperty *group, *idprop; + IDProperty *group, *idprop; - const char *key; - PyObject *def = Py_None; + const char *key; + PyObject *def = Py_None; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) { + return NULL; + } - /* mostly copied from BPy_IDGroup_Map_GetItem */ - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); - return NULL; - } + /* mostly copied from BPy_IDGroup_Map_GetItem */ + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); - if (group) { - idprop = IDP_GetPropertyFromGroup(group, key); + group = RNA_struct_idprops(&self->ptr, 0); + if (group) { + idprop = IDP_GetPropertyFromGroup(group, key); - if (idprop) { - return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); - } - } + if (idprop) { + return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); + } + } - return Py_INCREF_RET(def); + return Py_INCREF_RET(def); } PyDoc_STRVAR(pyrna_struct_pop_doc, -".. method:: pop(key, default=None)\n" -"\n" -" Remove and return the value of the custom property assigned to key or default\n" -" when not found (matches pythons dictionary function of the same name).\n" -"\n" -" :arg key: The key associated with the custom property.\n" -" :type key: string\n" -" :arg default: Optional argument for the value to return if\n" -" *key* is not found.\n" -" :type default: Undefined\n" -"\n" -BPY_DOC_ID_PROP_TYPE_NOTE -); + ".. method:: pop(key, default=None)\n" + "\n" + " Remove and return the value of the custom property assigned to key or default\n" + " when not found (matches pythons dictionary function of the same name).\n" + "\n" + " :arg key: The key associated with the custom property.\n" + " :type key: string\n" + " :arg default: Optional argument for the value to return if\n" + " *key* is not found.\n" + " :type default: Undefined\n" + "\n" BPY_DOC_ID_PROP_TYPE_NOTE); static PyObject *pyrna_struct_pop(BPy_StructRNA *self, PyObject *args) { - IDProperty *group, *idprop; + IDProperty *group, *idprop; - const char *key; - PyObject *def = NULL; + const char *key; + PyObject *def = NULL; - PYRNA_STRUCT_CHECK_OBJ(self); + PYRNA_STRUCT_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) { + return NULL; + } - /* mostly copied from BPy_IDGroup_Map_GetItem */ - if (RNA_struct_idprops_check(self->ptr.type) == 0) { - PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); - return NULL; - } + /* mostly copied from BPy_IDGroup_Map_GetItem */ + if (RNA_struct_idprops_check(self->ptr.type) == 0) { + PyErr_SetString(PyExc_TypeError, "this type doesn't support IDProperties"); + return NULL; + } - group = RNA_struct_idprops(&self->ptr, 0); - if (group) { - idprop = IDP_GetPropertyFromGroup(group, key); + group = RNA_struct_idprops(&self->ptr, 0); + if (group) { + idprop = IDP_GetPropertyFromGroup(group, key); - if (idprop) { - PyObject *ret = BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); - IDP_RemoveFromGroup(group, idprop); - return ret; - } - } + if (idprop) { + PyObject *ret = BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group); + IDP_RemoveFromGroup(group, idprop); + return ret; + } + } - if (def == NULL) { - PyErr_SetString(PyExc_KeyError, "key not found"); - return NULL; - } - return Py_INCREF_RET(def); + if (def == NULL) { + PyErr_SetString(PyExc_KeyError, "key not found"); + return NULL; + } + return Py_INCREF_RET(def); } PyDoc_STRVAR(pyrna_struct_as_pointer_doc, -".. method:: as_pointer()\n" -"\n" -" Returns the memory address which holds a pointer to blenders internal data\n" -"\n" -" :return: int (memory address).\n" -" :rtype: int\n" -"\n" -" .. note:: This is intended only for advanced script writers who need to\n" -" pass blender data to their own C/Python modules.\n" -); + ".. method:: as_pointer()\n" + "\n" + " Returns the memory address which holds a pointer to blenders internal data\n" + "\n" + " :return: int (memory address).\n" + " :rtype: int\n" + "\n" + " .. note:: This is intended only for advanced script writers who need to\n" + " pass blender data to their own C/Python modules.\n"); static PyObject *pyrna_struct_as_pointer(BPy_StructRNA *self) { - return PyLong_FromVoidPtr(self->ptr.data); + return PyLong_FromVoidPtr(self->ptr.data); } PyDoc_STRVAR(pyrna_prop_collection_get_doc, -".. method:: get(key, default=None)\n" -"\n" -" Returns the value of the item assigned to key or default when not found\n" -" (matches pythons dictionary function of the same name).\n" -"\n" -" :arg key: The identifier for the collection member.\n" -" :type key: string\n" -" :arg default: Optional argument for the value to return if\n" -" *key* is not found.\n" -" :type default: Undefined\n" -); + ".. method:: get(key, default=None)\n" + "\n" + " Returns the value of the item assigned to key or default when not found\n" + " (matches pythons dictionary function of the same name).\n" + "\n" + " :arg key: The identifier for the collection member.\n" + " :type key: string\n" + " :arg default: Optional argument for the value to return if\n" + " *key* is not found.\n" + " :type default: Undefined\n"); static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args) { - PointerRNA newptr; + PointerRNA newptr; - PyObject *key_ob; - PyObject *def = Py_None; + PyObject *key_ob; + PyObject *def = Py_None; - PYRNA_PROP_CHECK_OBJ(self); + PYRNA_PROP_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "O|O:get", &key_ob, &def)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "O|O:get", &key_ob, &def)) { + return NULL; + } - if (PyUnicode_Check(key_ob)) { - const char *key = _PyUnicode_AsString(key_ob); + 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); - } + 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_RET(def); + return Py_INCREF_RET(def); } PyDoc_STRVAR(pyrna_prop_collection_find_doc, -".. method:: find(key)\n" -"\n" -" Returns the index of a key in a collection or -1 when not found\n" -" (matches pythons string find function of the same name).\n" -"\n" -" :arg key: The identifier for the collection member.\n" -" :type key: string\n" -" :return: index of the key.\n" -" :rtype: int\n" -); + ".. method:: find(key)\n" + "\n" + " Returns the index of a key in a collection or -1 when not found\n" + " (matches pythons string find function of the same name).\n" + "\n" + " :arg key: The identifier for the collection member.\n" + " :type key: string\n" + " :return: index of the key.\n" + " :rtype: int\n"); static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key_ob) { - Py_ssize_t key_len_ssize_t; - const char *key = _PyUnicode_AsStringAndSize(key_ob, &key_len_ssize_t); - const int key_len = (int)key_len_ssize_t; /* comare with same type */ - - char name[256], *nameptr; - int namelen; - int i = 0; - int index = -1; - - PYRNA_PROP_CHECK_OBJ(self); - - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); - - if (nameptr) { - if ((key_len == namelen) && memcmp(nameptr, key, key_len) == 0) { - index = i; - break; - } - - if (name != nameptr) { - MEM_freeN(nameptr); - } - } - - i++; - } - RNA_PROP_END; - - return PyLong_FromLong(index); -} - -static bool foreach_attr_type( - BPy_PropertyRNA *self, const char *attr, - /* values to assign */ - RawPropertyType *raw_type, int *attr_tot, bool *attr_signed) -{ - PropertyRNA *prop; - bool attr_ok = true; - *raw_type = PROP_RAW_UNSET; - *attr_tot = 0; - *attr_signed = false; - - /* note: this is fail with zero length lists, so don't let this get caled in that case */ - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - prop = RNA_struct_find_property(&itemptr, attr); - if (prop) { - *raw_type = RNA_property_raw_type(prop); - *attr_tot = RNA_property_array_length(&itemptr, prop); - *attr_signed = (RNA_property_subtype(prop) != PROP_UNSIGNED); - } - else { - attr_ok = false; - } - break; - } - RNA_PROP_END; - - return attr_ok; + Py_ssize_t key_len_ssize_t; + const char *key = _PyUnicode_AsStringAndSize(key_ob, &key_len_ssize_t); + const int key_len = (int)key_len_ssize_t; /* comare with same type */ + + char name[256], *nameptr; + int namelen; + int i = 0; + int index = -1; + + PYRNA_PROP_CHECK_OBJ(self); + + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen); + + if (nameptr) { + if ((key_len == namelen) && memcmp(nameptr, key, key_len) == 0) { + index = i; + break; + } + + if (name != nameptr) { + MEM_freeN(nameptr); + } + } + + i++; + } + RNA_PROP_END; + + return PyLong_FromLong(index); +} + +static bool foreach_attr_type(BPy_PropertyRNA *self, + const char *attr, + /* values to assign */ + RawPropertyType *raw_type, + int *attr_tot, + bool *attr_signed) +{ + PropertyRNA *prop; + bool attr_ok = true; + *raw_type = PROP_RAW_UNSET; + *attr_tot = 0; + *attr_signed = false; + + /* note: this is fail with zero length lists, so don't let this get caled in that case */ + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + prop = RNA_struct_find_property(&itemptr, attr); + if (prop) { + *raw_type = RNA_property_raw_type(prop); + *attr_tot = RNA_property_array_length(&itemptr, prop); + *attr_signed = (RNA_property_subtype(prop) != PROP_UNSIGNED); + } + else { + attr_ok = false; + } + break; + } + RNA_PROP_END; + + return attr_ok; } /* pyrna_prop_collection_foreach_get/set both use this */ -static int foreach_parse_args( - BPy_PropertyRNA *self, PyObject *args, - - /* values to assign */ - const char **attr, PyObject **seq, int *tot, int *size, - RawPropertyType *raw_type, int *attr_tot, bool *attr_signed) +static int foreach_parse_args(BPy_PropertyRNA *self, + PyObject *args, + + /* values to assign */ + const char **attr, + PyObject **seq, + int *tot, + int *size, + RawPropertyType *raw_type, + int *attr_tot, + bool *attr_signed) { #if 0 - int array_tot; - int target_tot; + int array_tot; + int target_tot; #endif - *size = *attr_tot = 0; - *attr_signed = false; - *raw_type = PROP_RAW_UNSET; - - if (!PyArg_ParseTuple(args, "sO:foreach_get/set", attr, seq)) { - return -1; - } - - if (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq)) { - PyErr_Format(PyExc_TypeError, - "foreach_get/set expected second argument to be a sequence or buffer, not a %.200s", - Py_TYPE(*seq)->tp_name); - return -1; - } - - *tot = PySequence_Size(*seq); /* TODO - buffer may not be a sequence! array.array() is tho. */ - - if (*tot > 0) { - if (!foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed)) { - PyErr_Format(PyExc_AttributeError, - "foreach_get/set '%.200s.%200s[...]' elements have no attribute '%.200s'", - RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), *attr); - return -1; - } - *size = RNA_raw_type_sizeof(*raw_type); - -#if 0 /* works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks */ - if ((*attr_tot) < 1) { - *attr_tot = 1; - } - - if (RNA_property_type(self->prop) == PROP_COLLECTION) { - array_tot = RNA_property_collection_length(&self->ptr, self->prop); - } - else { - array_tot = RNA_property_array_length(&self->ptr, self->prop); - } - - - target_tot = array_tot * (*attr_tot); - - /* rna_access.c - rna_raw_access(...) uses this same method */ - if (target_tot != (*tot)) { - PyErr_Format(PyExc_TypeError, - "foreach_get(attr, sequence) sequence length mismatch given %d, needed %d", - *tot, target_tot); - return -1; - } + *size = *attr_tot = 0; + *attr_signed = false; + *raw_type = PROP_RAW_UNSET; + + if (!PyArg_ParseTuple(args, "sO:foreach_get/set", attr, seq)) { + return -1; + } + + if (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq)) { + PyErr_Format( + PyExc_TypeError, + "foreach_get/set expected second argument to be a sequence or buffer, not a %.200s", + Py_TYPE(*seq)->tp_name); + return -1; + } + + *tot = PySequence_Size(*seq); /* TODO - buffer may not be a sequence! array.array() is tho. */ + + if (*tot > 0) { + if (!foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed)) { + PyErr_Format(PyExc_AttributeError, + "foreach_get/set '%.200s.%200s[...]' elements have no attribute '%.200s'", + RNA_struct_identifier(self->ptr.type), + RNA_property_identifier(self->prop), + *attr); + return -1; + } + *size = RNA_raw_type_sizeof(*raw_type); + +#if 0 /* works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks */ + if ((*attr_tot) < 1) { + *attr_tot = 1; + } + + if (RNA_property_type(self->prop) == PROP_COLLECTION) { + array_tot = RNA_property_collection_length(&self->ptr, self->prop); + } + else { + array_tot = RNA_property_array_length(&self->ptr, self->prop); + } + + + target_tot = array_tot * (*attr_tot); + + /* rna_access.c - rna_raw_access(...) uses this same method */ + if (target_tot != (*tot)) { + PyErr_Format(PyExc_TypeError, + "foreach_get(attr, sequence) sequence length mismatch given %d, needed %d", + *tot, target_tot); + return -1; + } #endif - } + } - /* check 'attr_tot' otherwise we don't know if any values were set - * this isn't ideal because it means running on an empty list may fail silently when its not compatible. */ - if (*size == 0 && *attr_tot != 0) { - PyErr_SetString(PyExc_AttributeError, "attribute does not support foreach method"); - return -1; - } - return 0; + /* check 'attr_tot' otherwise we don't know if any values were set + * this isn't ideal because it means running on an empty list may fail silently when its not compatible. */ + if (*size == 0 && *attr_tot != 0) { + PyErr_SetString(PyExc_AttributeError, "attribute does not support foreach method"); + return -1; + } + return 0; } static bool foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, const char *format) { - char f = format ? *format : 'B'; /* B is assumed when not set */ - - switch (raw_type) { - case PROP_RAW_CHAR: - if (attr_signed) { - return (f == 'b') ? 1 : 0; - } - else { - return (f == 'B') ? 1 : 0; - } - case PROP_RAW_SHORT: - if (attr_signed) { - return (f == 'h') ? 1 : 0; - } - else { - return (f == 'H') ? 1 : 0; - } - case PROP_RAW_INT: - if (attr_signed) { - return (f == 'i') ? 1 : 0; - } - else { - return (f == 'I') ? 1 : 0; - } - case PROP_RAW_BOOLEAN: - return (f == '?') ? 1 : 0; - case PROP_RAW_FLOAT: - return (f == 'f') ? 1 : 0; - case PROP_RAW_DOUBLE: - return (f == 'd') ? 1 : 0; - case PROP_RAW_UNSET: - return 0; - } - - return 0; + char f = format ? *format : 'B'; /* B is assumed when not set */ + + switch (raw_type) { + case PROP_RAW_CHAR: + if (attr_signed) { + return (f == 'b') ? 1 : 0; + } + else { + return (f == 'B') ? 1 : 0; + } + case PROP_RAW_SHORT: + if (attr_signed) { + return (f == 'h') ? 1 : 0; + } + else { + return (f == 'H') ? 1 : 0; + } + case PROP_RAW_INT: + if (attr_signed) { + return (f == 'i') ? 1 : 0; + } + else { + return (f == 'I') ? 1 : 0; + } + case PROP_RAW_BOOLEAN: + return (f == '?') ? 1 : 0; + case PROP_RAW_FLOAT: + return (f == 'f') ? 1 : 0; + case PROP_RAW_DOUBLE: + return (f == 'd') ? 1 : 0; + case PROP_RAW_UNSET: + return 0; + } + + return 0; } static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) { - PyObject *item = NULL; - int i = 0, ok = 0; - bool buffer_is_compat; - void *array = NULL; - - /* get/set both take the same args currently */ - const char *attr; - PyObject *seq; - int tot, size, attr_tot; - bool attr_signed; - RawPropertyType raw_type; - - if (foreach_parse_args(self, args, &attr, &seq, &tot, &size, &raw_type, &attr_tot, &attr_signed) == -1) { - return NULL; - } - - if (tot == 0) { - Py_RETURN_NONE; - } - - - - if (set) { /* get the array from python */ - buffer_is_compat = false; - if (PyObject_CheckBuffer(seq)) { - Py_buffer buf; - PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); - - /* check if the buffer matches */ - - buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); - - if (buffer_is_compat) { - ok = RNA_property_collection_raw_set(NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); - } - - PyBuffer_Release(&buf); - } - - /* could not use the buffer, fallback to sequence */ - if (!buffer_is_compat) { - array = PyMem_Malloc(size * tot); - - for ( ; i < tot; i++) { - item = PySequence_GetItem(seq, i); - switch (raw_type) { - case PROP_RAW_CHAR: - ((char *)array)[i] = (char)PyLong_AsLong(item); - break; - case PROP_RAW_SHORT: - ((short *)array)[i] = (short)PyLong_AsLong(item); - break; - case PROP_RAW_INT: - ((int *)array)[i] = (int)PyLong_AsLong(item); - break; - case PROP_RAW_BOOLEAN: - ((bool *)array)[i] = (int)PyLong_AsLong(item) != 0; - break; - case PROP_RAW_FLOAT: - ((float *)array)[i] = (float)PyFloat_AsDouble(item); - break; - case PROP_RAW_DOUBLE: - ((double *)array)[i] = (double)PyFloat_AsDouble(item); - break; - case PROP_RAW_UNSET: - /* should never happen */ - BLI_assert(!"Invalid array type - set"); - break; - } - - Py_DECREF(item); - } - - ok = RNA_property_collection_raw_set(NULL, &self->ptr, self->prop, attr, array, raw_type, tot); - } - } - else { - buffer_is_compat = false; - if (PyObject_CheckBuffer(seq)) { - Py_buffer buf; - PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); - - /* check if the buffer matches, TODO - signed/unsigned types */ - - buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); - - if (buffer_is_compat) { - ok = RNA_property_collection_raw_get(NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); - } - - PyBuffer_Release(&buf); - } - - /* could not use the buffer, fallback to sequence */ - if (!buffer_is_compat) { - array = PyMem_Malloc(size * tot); - - ok = RNA_property_collection_raw_get(NULL, &self->ptr, self->prop, attr, array, raw_type, tot); - - if (!ok) { - /* skip the loop */ - i = tot; - } - - for ( ; i < tot; i++) { - - switch (raw_type) { - case PROP_RAW_CHAR: - item = PyLong_FromLong((long) ((char *)array)[i]); - break; - case PROP_RAW_SHORT: - item = PyLong_FromLong((long) ((short *)array)[i]); - break; - case PROP_RAW_INT: - item = PyLong_FromLong((long) ((int *)array)[i]); - break; - case PROP_RAW_FLOAT: - item = PyFloat_FromDouble((double) ((float *)array)[i]); - break; - case PROP_RAW_DOUBLE: - item = PyFloat_FromDouble((double) ((double *)array)[i]); - break; - case PROP_RAW_BOOLEAN: - item = PyBool_FromLong((long) ((bool *)array)[i]); - break; - default: /* PROP_RAW_UNSET */ - /* should never happen */ - BLI_assert(!"Invalid array type - get"); - item = Py_None; - Py_INCREF(item); - break; - } - - PySequence_SetItem(seq, i, item); - Py_DECREF(item); - } - } - } - - if (array) { - PyMem_Free(array); - } - - if (PyErr_Occurred()) { - /* Maybe we could make our own error */ - PyErr_Print(); - PyErr_SetString(PyExc_TypeError, "couldn't access the py sequence"); - return NULL; - } - if (!ok) { - PyErr_SetString(PyExc_RuntimeError, "internal error setting the array"); - return NULL; - } - - Py_RETURN_NONE; + PyObject *item = NULL; + int i = 0, ok = 0; + bool buffer_is_compat; + void *array = NULL; + + /* get/set both take the same args currently */ + const char *attr; + PyObject *seq; + int tot, size, attr_tot; + bool attr_signed; + RawPropertyType raw_type; + + if (foreach_parse_args( + self, args, &attr, &seq, &tot, &size, &raw_type, &attr_tot, &attr_signed) == -1) { + return NULL; + } + + if (tot == 0) { + Py_RETURN_NONE; + } + + if (set) { /* get the array from python */ + buffer_is_compat = false; + if (PyObject_CheckBuffer(seq)) { + Py_buffer buf; + PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); + + /* check if the buffer matches */ + + buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); + + if (buffer_is_compat) { + ok = RNA_property_collection_raw_set( + NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); + } + + PyBuffer_Release(&buf); + } + + /* could not use the buffer, fallback to sequence */ + if (!buffer_is_compat) { + array = PyMem_Malloc(size * tot); + + for (; i < tot; i++) { + item = PySequence_GetItem(seq, i); + switch (raw_type) { + case PROP_RAW_CHAR: + ((char *)array)[i] = (char)PyLong_AsLong(item); + break; + case PROP_RAW_SHORT: + ((short *)array)[i] = (short)PyLong_AsLong(item); + break; + case PROP_RAW_INT: + ((int *)array)[i] = (int)PyLong_AsLong(item); + break; + case PROP_RAW_BOOLEAN: + ((bool *)array)[i] = (int)PyLong_AsLong(item) != 0; + break; + case PROP_RAW_FLOAT: + ((float *)array)[i] = (float)PyFloat_AsDouble(item); + break; + case PROP_RAW_DOUBLE: + ((double *)array)[i] = (double)PyFloat_AsDouble(item); + break; + case PROP_RAW_UNSET: + /* should never happen */ + BLI_assert(!"Invalid array type - set"); + break; + } + + Py_DECREF(item); + } + + ok = RNA_property_collection_raw_set( + NULL, &self->ptr, self->prop, attr, array, raw_type, tot); + } + } + else { + buffer_is_compat = false; + if (PyObject_CheckBuffer(seq)) { + Py_buffer buf; + PyObject_GetBuffer(seq, &buf, PyBUF_SIMPLE | PyBUF_FORMAT); + + /* check if the buffer matches, TODO - signed/unsigned types */ + + buffer_is_compat = foreach_compat_buffer(raw_type, attr_signed, buf.format); + + if (buffer_is_compat) { + ok = RNA_property_collection_raw_get( + NULL, &self->ptr, self->prop, attr, buf.buf, raw_type, tot); + } + + PyBuffer_Release(&buf); + } + + /* could not use the buffer, fallback to sequence */ + if (!buffer_is_compat) { + array = PyMem_Malloc(size * tot); + + ok = RNA_property_collection_raw_get( + NULL, &self->ptr, self->prop, attr, array, raw_type, tot); + + if (!ok) { + /* skip the loop */ + i = tot; + } + + for (; i < tot; i++) { + + switch (raw_type) { + case PROP_RAW_CHAR: + item = PyLong_FromLong((long)((char *)array)[i]); + break; + case PROP_RAW_SHORT: + item = PyLong_FromLong((long)((short *)array)[i]); + break; + case PROP_RAW_INT: + item = PyLong_FromLong((long)((int *)array)[i]); + break; + case PROP_RAW_FLOAT: + item = PyFloat_FromDouble((double)((float *)array)[i]); + break; + case PROP_RAW_DOUBLE: + item = PyFloat_FromDouble((double)((double *)array)[i]); + break; + case PROP_RAW_BOOLEAN: + item = PyBool_FromLong((long)((bool *)array)[i]); + break; + default: /* PROP_RAW_UNSET */ + /* should never happen */ + BLI_assert(!"Invalid array type - get"); + item = Py_None; + Py_INCREF(item); + break; + } + + PySequence_SetItem(seq, i, item); + Py_DECREF(item); + } + } + } + + if (array) { + PyMem_Free(array); + } + + if (PyErr_Occurred()) { + /* Maybe we could make our own error */ + PyErr_Print(); + PyErr_SetString(PyExc_TypeError, "couldn't access the py sequence"); + return NULL; + } + if (!ok) { + PyErr_SetString(PyExc_RuntimeError, "internal error setting the array"); + return NULL; + } + + Py_RETURN_NONE; } PyDoc_STRVAR(pyrna_prop_collection_foreach_get_doc, -".. method:: foreach_get(attr, seq)\n" -"\n" -" This is a function to give fast access to attributes within a collection.\n" -); + ".. method:: foreach_get(attr, seq)\n" + "\n" + " This is a function to give fast access to attributes within a collection.\n"); static PyObject *pyrna_prop_collection_foreach_get(BPy_PropertyRNA *self, PyObject *args) { - PYRNA_PROP_CHECK_OBJ(self); + PYRNA_PROP_CHECK_OBJ(self); - return foreach_getset(self, args, 0); + return foreach_getset(self, args, 0); } PyDoc_STRVAR(pyrna_prop_collection_foreach_set_doc, -".. method:: foreach_set(attr, seq)\n" -"\n" -" This is a function to give fast access to attributes within a collection.\n" -); + ".. method:: foreach_set(attr, seq)\n" + "\n" + " This is a function to give fast access to attributes within a collection.\n"); static PyObject *pyrna_prop_collection_foreach_set(BPy_PropertyRNA *self, PyObject *args) { - PYRNA_PROP_CHECK_OBJ(self); + PYRNA_PROP_CHECK_OBJ(self); - return foreach_getset(self, args, 1); + return foreach_getset(self, args, 1); } /* A bit of a kludge, make a list out of a collection or array, * then return the lists iter function, not especially fast but convenient for now */ static PyObject *pyrna_prop_array_iter(BPy_PropertyArrayRNA *self) { - /* Try get values from a collection */ - PyObject *ret; - PyObject *iter = NULL; - int len; + /* Try get values from a collection */ + PyObject *ret; + PyObject *iter = NULL; + int len; - PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); + PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self); - len = pyrna_prop_array_length(self); - ret = pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len); + len = pyrna_prop_array_length(self); + ret = pyrna_prop_array_subscript_slice(self, &self->ptr, self->prop, 0, len, len); - /* we know this is a list so no need to PyIter_Check - * otherwise it could be NULL (unlikely) if conversion failed */ - if (ret) { - iter = PyObject_GetIter(ret); - Py_DECREF(ret); - } + /* we know this is a list so no need to PyIter_Check + * otherwise it could be NULL (unlikely) if conversion failed */ + if (ret) { + iter = PyObject_GetIter(ret); + Py_DECREF(ret); + } - return iter; + return iter; } static PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self); @@ -5331,348 +5387,400 @@ static PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self); #ifndef USE_PYRNA_ITER static PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self) { - /* Try get values from a collection */ - PyObject *ret; - PyObject *iter = NULL; - ret = pyrna_prop_collection_values(self); + /* Try get values from a collection */ + PyObject *ret; + PyObject *iter = NULL; + ret = pyrna_prop_collection_values(self); - /* we know this is a list so no need to PyIter_Check - * otherwise it could be NULL (unlikely) if conversion failed */ - if (ret) { - iter = PyObject_GetIter(ret); - Py_DECREF(ret); - } + /* we know this is a list so no need to PyIter_Check + * otherwise it could be NULL (unlikely) if conversion failed */ + if (ret) { + iter = PyObject_GetIter(ret); + Py_DECREF(ret); + } - return iter; + return iter; } #endif /* # !USE_PYRNA_ITER */ static struct PyMethodDef pyrna_struct_methods[] = { - /* only for PointerRNA's with ID'props */ - {"keys", (PyCFunction)pyrna_struct_keys, METH_NOARGS, pyrna_struct_keys_doc}, - {"values", (PyCFunction)pyrna_struct_values, METH_NOARGS, pyrna_struct_values_doc}, - {"items", (PyCFunction)pyrna_struct_items, METH_NOARGS, pyrna_struct_items_doc}, - - {"get", (PyCFunction)pyrna_struct_get, METH_VARARGS, pyrna_struct_get_doc}, - {"pop", (PyCFunction)pyrna_struct_pop, METH_VARARGS, pyrna_struct_pop_doc}, - - {"as_pointer", (PyCFunction)pyrna_struct_as_pointer, METH_NOARGS, pyrna_struct_as_pointer_doc}, - - /* bpy_rna_anim.c */ - {"keyframe_insert", (PyCFunction)pyrna_struct_keyframe_insert, METH_VARARGS | METH_KEYWORDS, pyrna_struct_keyframe_insert_doc}, - {"keyframe_delete", (PyCFunction)pyrna_struct_keyframe_delete, METH_VARARGS | METH_KEYWORDS, pyrna_struct_keyframe_delete_doc}, - {"driver_add", (PyCFunction)pyrna_struct_driver_add, METH_VARARGS, pyrna_struct_driver_add_doc}, - {"driver_remove", (PyCFunction)pyrna_struct_driver_remove, METH_VARARGS, pyrna_struct_driver_remove_doc}, - - {"is_property_set", (PyCFunction)pyrna_struct_is_property_set, METH_VARARGS, pyrna_struct_is_property_set_doc}, - {"property_unset", (PyCFunction)pyrna_struct_property_unset, METH_VARARGS, pyrna_struct_property_unset_doc}, - {"is_property_hidden", (PyCFunction)pyrna_struct_is_property_hidden, METH_VARARGS, pyrna_struct_is_property_hidden_doc}, - {"is_property_readonly", (PyCFunction)pyrna_struct_is_property_readonly, METH_VARARGS, pyrna_struct_is_property_readonly_doc}, - {"is_property_overridable_static", (PyCFunction)pyrna_struct_is_property_overridable_static, METH_VARARGS, pyrna_struct_is_property_overridable_static_doc}, - {"property_overridable_static_set", (PyCFunction)pyrna_struct_property_overridable_static_set, METH_VARARGS, pyrna_struct_property_overridable_static_set_doc}, - {"path_resolve", (PyCFunction)pyrna_struct_path_resolve, METH_VARARGS, pyrna_struct_path_resolve_doc}, - {"path_from_id", (PyCFunction)pyrna_struct_path_from_id, METH_VARARGS, pyrna_struct_path_from_id_doc}, - {"type_recast", (PyCFunction)pyrna_struct_type_recast, METH_NOARGS, pyrna_struct_type_recast_doc}, - {"bl_rna_get_subclass_py", (PyCFunction) pyrna_struct_bl_rna_get_subclass_py, METH_VARARGS | METH_CLASS, pyrna_struct_bl_rna_get_subclass_py_doc}, - {"bl_rna_get_subclass", (PyCFunction) pyrna_struct_bl_rna_get_subclass, METH_VARARGS | METH_CLASS, pyrna_struct_bl_rna_get_subclass_doc}, - {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL}, - - /* experimental */ - /* unused for now */ + /* only for PointerRNA's with ID'props */ + {"keys", (PyCFunction)pyrna_struct_keys, METH_NOARGS, pyrna_struct_keys_doc}, + {"values", (PyCFunction)pyrna_struct_values, METH_NOARGS, pyrna_struct_values_doc}, + {"items", (PyCFunction)pyrna_struct_items, METH_NOARGS, pyrna_struct_items_doc}, + + {"get", (PyCFunction)pyrna_struct_get, METH_VARARGS, pyrna_struct_get_doc}, + {"pop", (PyCFunction)pyrna_struct_pop, METH_VARARGS, pyrna_struct_pop_doc}, + + {"as_pointer", (PyCFunction)pyrna_struct_as_pointer, METH_NOARGS, pyrna_struct_as_pointer_doc}, + + /* bpy_rna_anim.c */ + {"keyframe_insert", + (PyCFunction)pyrna_struct_keyframe_insert, + METH_VARARGS | METH_KEYWORDS, + pyrna_struct_keyframe_insert_doc}, + {"keyframe_delete", + (PyCFunction)pyrna_struct_keyframe_delete, + METH_VARARGS | METH_KEYWORDS, + pyrna_struct_keyframe_delete_doc}, + {"driver_add", + (PyCFunction)pyrna_struct_driver_add, + METH_VARARGS, + pyrna_struct_driver_add_doc}, + {"driver_remove", + (PyCFunction)pyrna_struct_driver_remove, + METH_VARARGS, + pyrna_struct_driver_remove_doc}, + + {"is_property_set", + (PyCFunction)pyrna_struct_is_property_set, + METH_VARARGS, + pyrna_struct_is_property_set_doc}, + {"property_unset", + (PyCFunction)pyrna_struct_property_unset, + METH_VARARGS, + pyrna_struct_property_unset_doc}, + {"is_property_hidden", + (PyCFunction)pyrna_struct_is_property_hidden, + METH_VARARGS, + pyrna_struct_is_property_hidden_doc}, + {"is_property_readonly", + (PyCFunction)pyrna_struct_is_property_readonly, + METH_VARARGS, + pyrna_struct_is_property_readonly_doc}, + {"is_property_overridable_static", + (PyCFunction)pyrna_struct_is_property_overridable_static, + METH_VARARGS, + pyrna_struct_is_property_overridable_static_doc}, + {"property_overridable_static_set", + (PyCFunction)pyrna_struct_property_overridable_static_set, + METH_VARARGS, + pyrna_struct_property_overridable_static_set_doc}, + {"path_resolve", + (PyCFunction)pyrna_struct_path_resolve, + METH_VARARGS, + pyrna_struct_path_resolve_doc}, + {"path_from_id", + (PyCFunction)pyrna_struct_path_from_id, + METH_VARARGS, + pyrna_struct_path_from_id_doc}, + {"type_recast", + (PyCFunction)pyrna_struct_type_recast, + METH_NOARGS, + pyrna_struct_type_recast_doc}, + {"bl_rna_get_subclass_py", + (PyCFunction)pyrna_struct_bl_rna_get_subclass_py, + METH_VARARGS | METH_CLASS, + pyrna_struct_bl_rna_get_subclass_py_doc}, + {"bl_rna_get_subclass", + (PyCFunction)pyrna_struct_bl_rna_get_subclass, + METH_VARARGS | METH_CLASS, + pyrna_struct_bl_rna_get_subclass_doc}, + {"__dir__", (PyCFunction)pyrna_struct_dir, METH_NOARGS, NULL}, + +/* experimental */ +/* unused for now */ #if 0 - {"callback_add", (PyCFunction)pyrna_callback_add, METH_VARARGS, NULL}, - {"callback_remove", (PyCFunction)pyrna_callback_remove, METH_VARARGS, NULL}, + {"callback_add", (PyCFunction)pyrna_callback_add, METH_VARARGS, NULL}, + {"callback_remove", (PyCFunction)pyrna_callback_remove, METH_VARARGS, NULL}, - {"callback_add", (PyCFunction)pyrna_callback_classmethod_add, METH_VARARGS | METH_CLASS, NULL}, - {"callback_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_CLASS, NULL}, + {"callback_add", (PyCFunction)pyrna_callback_classmethod_add, METH_VARARGS | METH_CLASS, NULL}, + {"callback_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_CLASS, NULL}, #endif - {NULL, NULL, 0, NULL}, + {NULL, NULL, 0, NULL}, }; static struct PyMethodDef pyrna_prop_methods[] = { - {"path_from_id", (PyCFunction)pyrna_prop_path_from_id, METH_NOARGS, pyrna_prop_path_from_id_doc}, - {"as_bytes", (PyCFunction)pyrna_prop_as_bytes, METH_NOARGS, pyrna_prop_as_bytes_doc}, - {"update", (PyCFunction)pyrna_prop_update, METH_NOARGS, pyrna_prop_update_doc}, - {"__dir__", (PyCFunction)pyrna_prop_dir, METH_NOARGS, NULL}, - {NULL, NULL, 0, NULL}, + {"path_from_id", + (PyCFunction)pyrna_prop_path_from_id, + METH_NOARGS, + pyrna_prop_path_from_id_doc}, + {"as_bytes", (PyCFunction)pyrna_prop_as_bytes, METH_NOARGS, pyrna_prop_as_bytes_doc}, + {"update", (PyCFunction)pyrna_prop_update, METH_NOARGS, pyrna_prop_update_doc}, + {"__dir__", (PyCFunction)pyrna_prop_dir, METH_NOARGS, NULL}, + {NULL, NULL, 0, NULL}, }; static struct PyMethodDef pyrna_prop_array_methods[] = { - {NULL, NULL, 0, NULL}, + {NULL, NULL, 0, NULL}, }; static struct PyMethodDef pyrna_prop_collection_methods[] = { - {"foreach_get", (PyCFunction)pyrna_prop_collection_foreach_get, METH_VARARGS, pyrna_prop_collection_foreach_get_doc}, - {"foreach_set", (PyCFunction)pyrna_prop_collection_foreach_set, METH_VARARGS, pyrna_prop_collection_foreach_set_doc}, - - {"keys", (PyCFunction)pyrna_prop_collection_keys, METH_NOARGS, pyrna_prop_collection_keys_doc}, - {"items", (PyCFunction)pyrna_prop_collection_items, METH_NOARGS, pyrna_prop_collection_items_doc}, - {"values", (PyCFunction)pyrna_prop_collection_values, METH_NOARGS, pyrna_prop_collection_values_doc}, - - {"get", (PyCFunction)pyrna_prop_collection_get, METH_VARARGS, pyrna_prop_collection_get_doc}, - {"find", (PyCFunction)pyrna_prop_collection_find, METH_O, pyrna_prop_collection_find_doc}, - {NULL, NULL, 0, NULL}, + {"foreach_get", + (PyCFunction)pyrna_prop_collection_foreach_get, + METH_VARARGS, + pyrna_prop_collection_foreach_get_doc}, + {"foreach_set", + (PyCFunction)pyrna_prop_collection_foreach_set, + METH_VARARGS, + pyrna_prop_collection_foreach_set_doc}, + + {"keys", (PyCFunction)pyrna_prop_collection_keys, METH_NOARGS, pyrna_prop_collection_keys_doc}, + {"items", + (PyCFunction)pyrna_prop_collection_items, + METH_NOARGS, + pyrna_prop_collection_items_doc}, + {"values", + (PyCFunction)pyrna_prop_collection_values, + METH_NOARGS, + pyrna_prop_collection_values_doc}, + + {"get", (PyCFunction)pyrna_prop_collection_get, METH_VARARGS, pyrna_prop_collection_get_doc}, + {"find", (PyCFunction)pyrna_prop_collection_find, METH_O, pyrna_prop_collection_find_doc}, + {NULL, NULL, 0, NULL}, }; static struct PyMethodDef pyrna_prop_collection_idprop_methods[] = { - {"add", (PyCFunction)pyrna_prop_collection_idprop_add, METH_NOARGS, NULL}, - {"remove", (PyCFunction)pyrna_prop_collection_idprop_remove, METH_O, NULL}, - {"clear", (PyCFunction)pyrna_prop_collection_idprop_clear, METH_NOARGS, NULL}, - {"move", (PyCFunction)pyrna_prop_collection_idprop_move, METH_VARARGS, NULL}, - {NULL, NULL, 0, NULL}, + {"add", (PyCFunction)pyrna_prop_collection_idprop_add, METH_NOARGS, NULL}, + {"remove", (PyCFunction)pyrna_prop_collection_idprop_remove, METH_O, NULL}, + {"clear", (PyCFunction)pyrna_prop_collection_idprop_clear, METH_NOARGS, NULL}, + {"move", (PyCFunction)pyrna_prop_collection_idprop_move, METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL}, }; /* only needed for subtyping, so a new class gets a valid BPy_StructRNA * todo - also accept useful args */ static PyObject *pyrna_struct_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds)) { - if (PyTuple_GET_SIZE(args) == 1) { - BPy_StructRNA *base = (BPy_StructRNA *)PyTuple_GET_ITEM(args, 0); - if (Py_TYPE(base) == type) { - Py_INCREF(base); - return (PyObject *)base; - } - else if (PyType_IsSubtype(Py_TYPE(base), &pyrna_struct_Type)) { - /* this almost never runs, only when using user defined subclasses of built-in object. - * this isn't common since its NOT related to registerable subclasses. eg: - * - * >>> class MyObSubclass(bpy.types.Object): - * ... def test_func(self): - * ... print(100) - * ... - * >>> myob = MyObSubclass(bpy.context.object) - * >>> myob.test_func() - * 100 - * - * Keep this since it could be useful. - */ - BPy_StructRNA *ret; - if ((ret = (BPy_StructRNA *)type->tp_alloc(type, 0))) { - ret->ptr = base->ptr; - } - /* pass on exception & NULL if tp_alloc fails */ - return (PyObject *)ret; - } - - /* error, invalid type given */ - PyErr_Format(PyExc_TypeError, - "bpy_struct.__new__(type): type '%.200s' is not a subtype of bpy_struct", - type->tp_name); - return NULL; - } - else { - PyErr_Format(PyExc_TypeError, - "bpy_struct.__new__(type): expected a single argument"); - return NULL; - } + if (PyTuple_GET_SIZE(args) == 1) { + BPy_StructRNA *base = (BPy_StructRNA *)PyTuple_GET_ITEM(args, 0); + if (Py_TYPE(base) == type) { + Py_INCREF(base); + return (PyObject *)base; + } + else if (PyType_IsSubtype(Py_TYPE(base), &pyrna_struct_Type)) { + /* this almost never runs, only when using user defined subclasses of built-in object. + * this isn't common since its NOT related to registerable subclasses. eg: + * + * >>> class MyObSubclass(bpy.types.Object): + * ... def test_func(self): + * ... print(100) + * ... + * >>> myob = MyObSubclass(bpy.context.object) + * >>> myob.test_func() + * 100 + * + * Keep this since it could be useful. + */ + BPy_StructRNA *ret; + if ((ret = (BPy_StructRNA *)type->tp_alloc(type, 0))) { + ret->ptr = base->ptr; + } + /* pass on exception & NULL if tp_alloc fails */ + return (PyObject *)ret; + } + + /* error, invalid type given */ + PyErr_Format(PyExc_TypeError, + "bpy_struct.__new__(type): type '%.200s' is not a subtype of bpy_struct", + type->tp_name); + return NULL; + } + else { + PyErr_Format(PyExc_TypeError, "bpy_struct.__new__(type): expected a single argument"); + return NULL; + } } /* only needed for subtyping, so a new class gets a valid BPy_StructRNA * todo - also accept useful args */ static PyObject *pyrna_prop_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds)) { - BPy_PropertyRNA *base; - - if (!PyArg_ParseTuple(args, "O!:bpy_prop.__new__", &pyrna_prop_Type, &base)) { - return NULL; - } - - if (type == Py_TYPE(base)) { - return Py_INCREF_RET((PyObject *)base); - } - else if (PyType_IsSubtype(type, &pyrna_prop_Type)) { - BPy_PropertyRNA *ret = (BPy_PropertyRNA *) type->tp_alloc(type, 0); - ret->ptr = base->ptr; - ret->prop = base->prop; - return (PyObject *)ret; - } - else { - PyErr_Format(PyExc_TypeError, - "bpy_prop.__new__(type): type '%.200s' is not a subtype of bpy_prop", - type->tp_name); - return NULL; - } + BPy_PropertyRNA *base; + + if (!PyArg_ParseTuple(args, "O!:bpy_prop.__new__", &pyrna_prop_Type, &base)) { + return NULL; + } + + if (type == Py_TYPE(base)) { + return Py_INCREF_RET((PyObject *)base); + } + else if (PyType_IsSubtype(type, &pyrna_prop_Type)) { + BPy_PropertyRNA *ret = (BPy_PropertyRNA *)type->tp_alloc(type, 0); + ret->ptr = base->ptr; + ret->prop = base->prop; + return (PyObject *)ret; + } + else { + PyErr_Format(PyExc_TypeError, + "bpy_prop.__new__(type): type '%.200s' is not a subtype of bpy_prop", + type->tp_name); + return NULL; + } } static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) { - PyObject *ret; - const int type = RNA_property_type(prop); - const int flag = RNA_property_flag(prop); - const int flag_parameter = RNA_parameter_flag(prop); - - if (RNA_property_array_check(prop)) { - int a, len; - - if (flag & PROP_DYNAMIC) { - ParameterDynAlloc *data_alloc = data; - len = data_alloc->array_tot; - data = data_alloc->array; - } - else { - len = RNA_property_array_length(ptr, prop); - } - - /* resolve the array from a new pytype */ - - /* kazanbas: TODO make multidim sequences here */ - - switch (type) { - case PROP_BOOLEAN: - ret = PyTuple_New(len); - for (a = 0; a < len; a++) { - PyTuple_SET_ITEM(ret, a, PyBool_FromLong(((bool *)data)[a])); - } - break; - case PROP_INT: - ret = PyTuple_New(len); - for (a = 0; a < len; a++) { - PyTuple_SET_ITEM(ret, a, PyLong_FromLong(((int *)data)[a])); - } - break; - case PROP_FLOAT: - switch (RNA_property_subtype(prop)) { + PyObject *ret; + const int type = RNA_property_type(prop); + const int flag = RNA_property_flag(prop); + const int flag_parameter = RNA_parameter_flag(prop); + + if (RNA_property_array_check(prop)) { + int a, len; + + if (flag & PROP_DYNAMIC) { + ParameterDynAlloc *data_alloc = data; + len = data_alloc->array_tot; + data = data_alloc->array; + } + else { + len = RNA_property_array_length(ptr, prop); + } + + /* resolve the array from a new pytype */ + + /* kazanbas: TODO make multidim sequences here */ + + switch (type) { + case PROP_BOOLEAN: + ret = PyTuple_New(len); + for (a = 0; a < len; a++) { + PyTuple_SET_ITEM(ret, a, PyBool_FromLong(((bool *)data)[a])); + } + break; + case PROP_INT: + ret = PyTuple_New(len); + for (a = 0; a < len; a++) { + PyTuple_SET_ITEM(ret, a, PyLong_FromLong(((int *)data)[a])); + } + break; + case PROP_FLOAT: + switch (RNA_property_subtype(prop)) { #ifdef USE_MATHUTILS - case PROP_ALL_VECTOR_SUBTYPES: - ret = Vector_CreatePyObject(data, len, NULL); - break; - case PROP_MATRIX: - if (len == 16) { - ret = Matrix_CreatePyObject(data, 4, 4, NULL); - break; - } - else if (len == 9) { - ret = Matrix_CreatePyObject(data, 3, 3, NULL); - break; - } - ATTR_FALLTHROUGH; + case PROP_ALL_VECTOR_SUBTYPES: + ret = Vector_CreatePyObject(data, len, NULL); + break; + case PROP_MATRIX: + if (len == 16) { + ret = Matrix_CreatePyObject(data, 4, 4, NULL); + break; + } + else if (len == 9) { + ret = Matrix_CreatePyObject(data, 3, 3, NULL); + break; + } + ATTR_FALLTHROUGH; #endif - default: - ret = PyTuple_New(len); - for (a = 0; a < len; a++) { - PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble(((float *)data)[a])); - } - break; - } - break; - default: - PyErr_Format(PyExc_TypeError, - "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", - type); - ret = NULL; - break; - } - } - else { - /* see if we can coerce into a python type - PropertyType */ - switch (type) { - case PROP_BOOLEAN: - ret = PyBool_FromLong(*(bool *)data); - break; - case PROP_INT: - ret = PyLong_FromLong(*(int *)data); - break; - case PROP_FLOAT: - ret = PyFloat_FromDouble(*(float *)data); - break; - case PROP_STRING: - { - const char *data_ch; - PyObject *value_coerce = NULL; - const int subtype = RNA_property_subtype(prop); - - if (flag & PROP_THICK_WRAP) { - data_ch = (char *)data; - } - else { - data_ch = *(char **)data; - } + default: + ret = PyTuple_New(len); + for (a = 0; a < len; a++) { + PyTuple_SET_ITEM(ret, a, PyFloat_FromDouble(((float *)data)[a])); + } + break; + } + break; + default: + PyErr_Format( + PyExc_TypeError, "RNA Error: unknown array type \"%d\" (pyrna_param_to_py)", type); + ret = NULL; + break; + } + } + else { + /* see if we can coerce into a python type - PropertyType */ + switch (type) { + case PROP_BOOLEAN: + ret = PyBool_FromLong(*(bool *)data); + break; + case PROP_INT: + ret = PyLong_FromLong(*(int *)data); + break; + case PROP_FLOAT: + ret = PyFloat_FromDouble(*(float *)data); + break; + case PROP_STRING: { + const char *data_ch; + PyObject *value_coerce = NULL; + const int subtype = RNA_property_subtype(prop); + + if (flag & PROP_THICK_WRAP) { + data_ch = (char *)data; + } + else { + data_ch = *(char **)data; + } #ifdef USE_STRING_COERCE - if (subtype == PROP_BYTESTRING) { - ret = PyBytes_FromString(data_ch); - } - else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - ret = PyC_UnicodeFromByte(data_ch); - } - else { - ret = PyUnicode_FromString(data_ch); - } + if (subtype == PROP_BYTESTRING) { + ret = PyBytes_FromString(data_ch); + } + else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { + ret = PyC_UnicodeFromByte(data_ch); + } + else { + ret = PyUnicode_FromString(data_ch); + } #else - if (subtype == PROP_BYTESTRING) { - ret = PyBytes_FromString(buf); - } - else { - ret = PyUnicode_FromString(data_ch); - } + if (subtype == PROP_BYTESTRING) { + ret = PyBytes_FromString(buf); + } + else { + ret = PyUnicode_FromString(data_ch); + } #endif #ifdef USE_STRING_COERCE - Py_XDECREF(value_coerce); + Py_XDECREF(value_coerce); #endif - break; - } - case PROP_ENUM: - { - ret = pyrna_enum_to_py(ptr, prop, *(int *)data); - break; - } - case PROP_POINTER: - { - PointerRNA newptr; - StructRNA *ptype = RNA_property_pointer_type(ptr, prop); - - if (flag_parameter & PARM_RNAPTR) { - /* in this case we get the full ptr */ - newptr = *(PointerRNA *)data; - } - else { - if (RNA_struct_is_ID(ptype)) { - RNA_id_pointer_create(*(void **)data, &newptr); - } - else { - /* note: this is taken from the function's ID pointer - * and will break if a function returns a pointer from - * another ID block, watch this! - it should at least be - * easy to debug since they are all ID's */ - RNA_pointer_create(ptr->id.data, ptype, *(void **)data, &newptr); - } - } - - if (newptr.data) { - ret = pyrna_struct_CreatePyObject(&newptr); - } - else { - ret = Py_None; - Py_INCREF(ret); - } - break; - } - case PROP_COLLECTION: - { - CollectionListBase *lb = (CollectionListBase *)data; - CollectionPointerLink *link; - - ret = PyList_New(0); - - for (link = lb->first; link; link = link->next) { - PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr)); - } - - break; - } - default: - PyErr_Format(PyExc_TypeError, - "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", - type); - ret = NULL; - break; - } - } - - return ret; + break; + } + case PROP_ENUM: { + ret = pyrna_enum_to_py(ptr, prop, *(int *)data); + break; + } + case PROP_POINTER: { + PointerRNA newptr; + StructRNA *ptype = RNA_property_pointer_type(ptr, prop); + + if (flag_parameter & PARM_RNAPTR) { + /* in this case we get the full ptr */ + newptr = *(PointerRNA *)data; + } + else { + if (RNA_struct_is_ID(ptype)) { + RNA_id_pointer_create(*(void **)data, &newptr); + } + else { + /* note: this is taken from the function's ID pointer + * and will break if a function returns a pointer from + * another ID block, watch this! - it should at least be + * easy to debug since they are all ID's */ + RNA_pointer_create(ptr->id.data, ptype, *(void **)data, &newptr); + } + } + + if (newptr.data) { + ret = pyrna_struct_CreatePyObject(&newptr); + } + else { + ret = Py_None; + Py_INCREF(ret); + } + break; + } + case PROP_COLLECTION: { + CollectionListBase *lb = (CollectionListBase *)data; + CollectionPointerLink *link; + + ret = PyList_New(0); + + for (link = lb->first; link; link = link->next) { + PyList_APPEND(ret, pyrna_struct_CreatePyObject(&link->ptr)); + } + + break; + } + default: + PyErr_Format(PyExc_TypeError, "RNA Error: unknown type \"%d\" (pyrna_param_to_py)", type); + ret = NULL; + break; + } + } + + return ret; } /* Use to replace PyDict_GetItemString() when the overhead of converting a @@ -5680,954 +5788,963 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat * works on small dict's such as keyword args. */ static PyObject *small_dict_get_item_string(PyObject *dict, const char *key_lookup) { - PyObject *key = NULL; - Py_ssize_t pos = 0; - PyObject *value = NULL; + PyObject *key = NULL; + Py_ssize_t pos = 0; + PyObject *value = NULL; - while (PyDict_Next(dict, &pos, &key, &value)) { - if (PyUnicode_Check(key)) { - if (STREQ(key_lookup, _PyUnicode_AsString(key))) { - return value; - } - } - } + while (PyDict_Next(dict, &pos, &key, &value)) { + if (PyUnicode_Check(key)) { + if (STREQ(key_lookup, _PyUnicode_AsString(key))) { + return value; + } + } + } - return NULL; + return NULL; } static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject *kw) { - /* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here */ - PointerRNA *self_ptr = &self->ptr; - FunctionRNA *self_func = self->func; + /* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here */ + PointerRNA *self_ptr = &self->ptr; + FunctionRNA *self_func = self->func; - PointerRNA funcptr; - ParameterList parms; - ParameterIterator iter; - PropertyRNA *parm; - PyObject *ret, *item; - int i, pyargs_len, pykw_len, parms_len, ret_len, flag_parameter, err = 0, kw_tot = 0; - bool kw_arg; + PointerRNA funcptr; + ParameterList parms; + ParameterIterator iter; + PropertyRNA *parm; + PyObject *ret, *item; + int i, pyargs_len, pykw_len, parms_len, ret_len, flag_parameter, err = 0, kw_tot = 0; + bool kw_arg; - PropertyRNA *pret_single = NULL; - void *retdata_single = NULL; + PropertyRNA *pret_single = NULL; + void *retdata_single = NULL; - /* enable this so all strings are copied and freed after calling. - * this exposes bugs where the pointer to the string is held and re-used */ -// #define DEBUG_STRING_FREE + /* enable this so all strings are copied and freed after calling. + * this exposes bugs where the pointer to the string is held and re-used */ + // #define DEBUG_STRING_FREE #ifdef DEBUG_STRING_FREE - PyObject *string_free_ls = PyList_New(0); + PyObject *string_free_ls = PyList_New(0); #endif - /* Should never happen but it does in rare cases */ - BLI_assert(self_ptr != NULL); + /* Should never happen but it does in rare cases */ + BLI_assert(self_ptr != NULL); - if (self_ptr == NULL) { - PyErr_SetString(PyExc_RuntimeError, "rna functions internal rna pointer is NULL, this is a bug. aborting"); - return NULL; - } + if (self_ptr == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "rna functions internal rna pointer is NULL, this is a bug. aborting"); + return NULL; + } - if (self_func == NULL) { - PyErr_Format(PyExc_RuntimeError, - "%.200s.<unknown>(): rna function internal function is NULL, this is a bug. aborting", - RNA_struct_identifier(self_ptr->type)); - return NULL; - } + if (self_func == NULL) { + PyErr_Format( + PyExc_RuntimeError, + "%.200s.<unknown>(): rna function internal function is NULL, this is a bug. aborting", + RNA_struct_identifier(self_ptr->type)); + return NULL; + } - /* for testing */ + /* for testing */ #if 0 - { - const char *fn; - int lineno; - PyC_FileAndNum(&fn, &lineno); - printf("pyrna_func_call > %.200s.%.200s : %.200s:%d\n", - RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), fn, lineno); - } + { + const char *fn; + int lineno; + PyC_FileAndNum(&fn, &lineno); + printf("pyrna_func_call > %.200s.%.200s : %.200s:%d\n", + RNA_struct_identifier(self_ptr->type), RNA_function_identifier(self_func), fn, lineno); + } #endif - /* include the ID pointer for pyrna_param_to_py() so we can include the - * ID pointer on return values, this only works when returned values have - * the same ID as the functions. */ - RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr); - - pyargs_len = PyTuple_GET_SIZE(args); - pykw_len = kw ? PyDict_Size(kw) : 0; - - RNA_parameter_list_create(&parms, self_ptr, self_func); - RNA_parameter_list_begin(&parms, &iter); - parms_len = RNA_parameter_list_arg_count(&parms); - ret_len = 0; - - if (pyargs_len + pykw_len > parms_len) { - RNA_parameter_list_end(&iter); - 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, pyargs_len + pykw_len); - err = -1; - } - - /* parse function parameters */ - for (i = 0; iter.valid && err == 0; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - flag_parameter = RNA_parameter_flag(parm); - - /* only useful for single argument returns, we'll need another list loop for multiple */ - if (flag_parameter & PARM_OUTPUT) { - ret_len++; - if (pret_single == NULL) { - pret_single = parm; - retdata_single = iter.data; - } - - continue; - } - - item = NULL; - - if (i < pyargs_len) { - /* New in 2.8x, optional arguments must be keywords. */ - if (UNLIKELY((flag_parameter & PARM_REQUIRED) == 0)) { - PyErr_Format(PyExc_TypeError, - "%.200s.%.200s(): required parameter \"%.200s\" to be a keyword argument!", - RNA_struct_identifier(self_ptr->type), - RNA_function_identifier(self_func), - RNA_property_identifier(parm)); - err = -1; - break; - } - - item = PyTuple_GET_ITEM(args, i); - kw_arg = false; - } - else if (kw != NULL) { + /* include the ID pointer for pyrna_param_to_py() so we can include the + * ID pointer on return values, this only works when returned values have + * the same ID as the functions. */ + RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr); + + pyargs_len = PyTuple_GET_SIZE(args); + pykw_len = kw ? PyDict_Size(kw) : 0; + + RNA_parameter_list_create(&parms, self_ptr, self_func); + RNA_parameter_list_begin(&parms, &iter); + parms_len = RNA_parameter_list_arg_count(&parms); + ret_len = 0; + + if (pyargs_len + pykw_len > parms_len) { + RNA_parameter_list_end(&iter); + 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, + pyargs_len + pykw_len); + err = -1; + } + + /* parse function parameters */ + for (i = 0; iter.valid && err == 0; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + flag_parameter = RNA_parameter_flag(parm); + + /* only useful for single argument returns, we'll need another list loop for multiple */ + if (flag_parameter & PARM_OUTPUT) { + ret_len++; + if (pret_single == NULL) { + pret_single = parm; + retdata_single = iter.data; + } + + continue; + } + + item = NULL; + + if (i < pyargs_len) { + /* New in 2.8x, optional arguments must be keywords. */ + if (UNLIKELY((flag_parameter & PARM_REQUIRED) == 0)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s(): required parameter \"%.200s\" to be a keyword argument!", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + RNA_property_identifier(parm)); + err = -1; + break; + } + + item = PyTuple_GET_ITEM(args, i); + kw_arg = false; + } + else if (kw != NULL) { #if 0 - item = PyDict_GetItemString(kw, RNA_property_identifier(parm)); /* borrow ref */ + item = PyDict_GetItemString(kw, RNA_property_identifier(parm)); /* borrow ref */ #else - item = small_dict_get_item_string(kw, RNA_property_identifier(parm)); /* borrow ref */ + item = small_dict_get_item_string(kw, RNA_property_identifier(parm)); /* borrow ref */ #endif - if (item) { - kw_tot++; /* make sure invalid keywords are not given */ - } - - kw_arg = true; - } - - i++; /* current argument */ - - if (item == NULL) { - if (flag_parameter & PARM_REQUIRED) { - PyErr_Format(PyExc_TypeError, - "%.200s.%.200s(): required parameter \"%.200s\" not specified", - RNA_struct_identifier(self_ptr->type), - RNA_function_identifier(self_func), - RNA_property_identifier(parm)); - err = -1; - break; - } - else { /* PyDict_GetItemString wont raise an error */ - continue; - } - } + if (item) { + kw_tot++; /* make sure invalid keywords are not given */ + } + + kw_arg = true; + } + + i++; /* current argument */ + + if (item == NULL) { + if (flag_parameter & PARM_REQUIRED) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s(): required parameter \"%.200s\" not specified", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + RNA_property_identifier(parm)); + err = -1; + break; + } + else { /* PyDict_GetItemString wont raise an error */ + continue; + } + } #ifdef DEBUG_STRING_FREE - if (item) { - if (PyUnicode_Check(item)) { - PyList_APPEND(string_free_ls, PyUnicode_FromString(_PyUnicode_AsString(item))); - } - } + if (item) { + if (PyUnicode_Check(item)) { + PyList_APPEND(string_free_ls, PyUnicode_FromString(_PyUnicode_AsString(item))); + } + } #endif - err = pyrna_py_to_prop(&funcptr, parm, iter.data, item, ""); - - if (err != 0) { - /* the error generated isn't that useful, so generate it again with a useful prefix - * could also write a function to prepend to error messages */ - char error_prefix[512]; - PyErr_Clear(); /* re-raise */ - - if (kw_arg == true) { - BLI_snprintf(error_prefix, sizeof(error_prefix), - "%.200s.%.200s(): error with keyword argument \"%.200s\" - ", - RNA_struct_identifier(self_ptr->type), - RNA_function_identifier(self_func), - RNA_property_identifier(parm)); - } - else { - BLI_snprintf(error_prefix, sizeof(error_prefix), - "%.200s.%.200s(): error with argument %d, \"%.200s\" - ", - RNA_struct_identifier(self_ptr->type), - RNA_function_identifier(self_func), - i, - RNA_property_identifier(parm)); - } - - pyrna_py_to_prop(&funcptr, parm, iter.data, item, error_prefix); - - break; - } - } - - RNA_parameter_list_end(&iter); - - /* Check if we gave args that don't 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. - * (Don't overwrite the error if we have one, otherwise can skip important messages and confuse with args) - */ - if (err == 0 && kw && (pykw_len > kw_tot)) { - PyObject *key, *value; - Py_ssize_t pos = 0; - - DynStr *bad_args = BLI_dynstr_new(); - DynStr *good_args = BLI_dynstr_new(); - - const char *arg_name, *bad_args_str, *good_args_str; - bool found = false, first = true; - - while (PyDict_Next(kw, &pos, &key, &value)) { - - arg_name = _PyUnicode_AsString(key); - found = false; - - 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 (STREQ(arg_name, RNA_property_identifier(parm))) { - found = true; - break; - } - } - - RNA_parameter_list_end(&iter); - - if (found == false) { - BLI_dynstr_appendf(bad_args, first ? "%s" : ", %s", arg_name); - first = false; - } - } - } - - /* list good args */ - first = true; - - RNA_parameter_list_begin(&parms, &iter); - for (; iter.valid; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - if (RNA_parameter_flag(parm) & PARM_OUTPUT) { - continue; - } - - BLI_dynstr_appendf(good_args, first ? "%s" : ", %s", RNA_property_identifier(parm)); - first = false; - } - 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 argument(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((void *)bad_args_str); - MEM_freeN((void *)good_args_str); - - err = -1; - } - - ret = NULL; - if (err == 0) { - /* call function */ - ReportList reports; - bContext *C = BPy_GetContext(); - - BKE_reports_init(&reports, RPT_STORE); - RNA_function_call(C, &reports, self_ptr, self_func, &parms); - - err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true)); - - /* return value */ - if (err != -1) { - if (ret_len > 0) { - if (ret_len > 1) { - ret = PyTuple_New(ret_len); - i = 0; /* arg index */ - - RNA_parameter_list_begin(&parms, &iter); - - for (; iter.valid; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - - if (RNA_parameter_flag(parm) & PARM_OUTPUT) { - PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, parm, iter.data)); - } - } - - RNA_parameter_list_end(&iter); - } - else { - ret = pyrna_param_to_py(&funcptr, pret_single, retdata_single); - } - - /* possible there is an error in conversion */ - if (ret == NULL) { - err = -1; - } - } - } - } - + err = pyrna_py_to_prop(&funcptr, parm, iter.data, item, ""); + + if (err != 0) { + /* the error generated isn't that useful, so generate it again with a useful prefix + * could also write a function to prepend to error messages */ + char error_prefix[512]; + PyErr_Clear(); /* re-raise */ + + if (kw_arg == true) { + BLI_snprintf(error_prefix, + sizeof(error_prefix), + "%.200s.%.200s(): error with keyword argument \"%.200s\" - ", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + RNA_property_identifier(parm)); + } + else { + BLI_snprintf(error_prefix, + sizeof(error_prefix), + "%.200s.%.200s(): error with argument %d, \"%.200s\" - ", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + i, + RNA_property_identifier(parm)); + } + + pyrna_py_to_prop(&funcptr, parm, iter.data, item, error_prefix); + + break; + } + } + + RNA_parameter_list_end(&iter); + + /* Check if we gave args that don't 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. + * (Don't overwrite the error if we have one, otherwise can skip important messages and confuse with args) + */ + if (err == 0 && kw && (pykw_len > kw_tot)) { + PyObject *key, *value; + Py_ssize_t pos = 0; + + DynStr *bad_args = BLI_dynstr_new(); + DynStr *good_args = BLI_dynstr_new(); + + const char *arg_name, *bad_args_str, *good_args_str; + bool found = false, first = true; + + while (PyDict_Next(kw, &pos, &key, &value)) { + + arg_name = _PyUnicode_AsString(key); + found = false; + + 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 (STREQ(arg_name, RNA_property_identifier(parm))) { + found = true; + break; + } + } + + RNA_parameter_list_end(&iter); + + if (found == false) { + BLI_dynstr_appendf(bad_args, first ? "%s" : ", %s", arg_name); + first = false; + } + } + } + + /* list good args */ + first = true; + + RNA_parameter_list_begin(&parms, &iter); + for (; iter.valid; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + if (RNA_parameter_flag(parm) & PARM_OUTPUT) { + continue; + } + + BLI_dynstr_appendf(good_args, first ? "%s" : ", %s", RNA_property_identifier(parm)); + first = false; + } + 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 argument(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((void *)bad_args_str); + MEM_freeN((void *)good_args_str); + + err = -1; + } + + ret = NULL; + if (err == 0) { + /* call function */ + ReportList reports; + bContext *C = BPy_GetContext(); + + BKE_reports_init(&reports, RPT_STORE); + RNA_function_call(C, &reports, self_ptr, self_func, &parms); + + err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true)); + + /* return value */ + if (err != -1) { + if (ret_len > 0) { + if (ret_len > 1) { + ret = PyTuple_New(ret_len); + i = 0; /* arg index */ + + RNA_parameter_list_begin(&parms, &iter); + + for (; iter.valid; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + + if (RNA_parameter_flag(parm) & PARM_OUTPUT) { + PyTuple_SET_ITEM(ret, i++, pyrna_param_to_py(&funcptr, parm, iter.data)); + } + } + + RNA_parameter_list_end(&iter); + } + else { + ret = pyrna_param_to_py(&funcptr, pret_single, retdata_single); + } + + /* possible there is an error in conversion */ + if (ret == NULL) { + err = -1; + } + } + } + } #ifdef DEBUG_STRING_FREE -#if 0 - if (PyList_GET_SIZE(string_free_ls)) { - printf("%.200s.%.200s(): has %d strings\n", - RNA_struct_identifier(self_ptr->type), - RNA_function_identifier(self_func), - (int)PyList_GET_SIZE(string_free_ls)); - } -#endif - Py_DECREF(string_free_ls); -#undef DEBUG_STRING_FREE +# if 0 + if (PyList_GET_SIZE(string_free_ls)) { + printf("%.200s.%.200s(): has %d strings\n", + RNA_struct_identifier(self_ptr->type), + RNA_function_identifier(self_func), + (int)PyList_GET_SIZE(string_free_ls)); + } +# endif + Py_DECREF(string_free_ls); +# undef DEBUG_STRING_FREE #endif - /* cleanup */ - RNA_parameter_list_end(&iter); - RNA_parameter_list_free(&parms); + /* cleanup */ + RNA_parameter_list_end(&iter); + RNA_parameter_list_free(&parms); - if (ret) { - return ret; - } + if (ret) { + return ret; + } - if (err == -1) { - return NULL; - } + if (err == -1) { + return NULL; + } - Py_RETURN_NONE; + Py_RETURN_NONE; } static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void *UNUSED(closure)) { - PyObject *ret; - char *args; + PyObject *ret; + char *args; - args = RNA_function_as_string_keywords(NULL, self->func, true, true, INT_MAX); + args = RNA_function_as_string_keywords(NULL, self->func, true, true, INT_MAX); - ret = PyUnicode_FromFormat("%.200s.%.200s(%.200s)\n%s", - RNA_struct_identifier(self->ptr.type), - RNA_function_identifier(self->func), - args, RNA_function_ui_description(self->func)); + ret = PyUnicode_FromFormat("%.200s.%.200s(%.200s)\n%s", + RNA_struct_identifier(self->ptr.type), + RNA_function_identifier(self->func), + args, + RNA_function_ui_description(self->func)); - MEM_freeN(args); + MEM_freeN(args); - return ret; + return ret; } /* subclasses of pyrna_struct_Type which support idprop definitions use this as a metaclass */ /* note: tp_base member is set to &PyType_Type on init */ PyTypeObject pyrna_struct_meta_idprop_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_struct_meta_idprop", /* tp_name */ - - /* NOTE! would be PyTypeObject, but subtypes of Type must be PyHeapTypeObject's */ - sizeof(PyHeapTypeObject), /* tp_basicsize */ - - 0, /* tp_itemsize */ - /* methods */ - NULL, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* deprecated in python 3.0! */ - NULL, /* tp_repr */ - - /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - NULL /*(getattrofunc) pyrna_struct_meta_idprop_getattro*/, /* getattrofunc tp_getattro; */ - (setattrofunc) pyrna_struct_meta_idprop_setattro, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ - 0, /* long tp_weaklistoffset; */ - - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - NULL, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL, /* struct PyGetSetDef *tp_getset; */ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_struct_meta_idprop", /* tp_name */ + + /* NOTE! would be PyTypeObject, but subtypes of Type must be PyHeapTypeObject's */ + sizeof(PyHeapTypeObject), /* tp_basicsize */ + + 0, /* tp_itemsize */ + /* methods */ + NULL, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* deprecated in python 3.0! */ + NULL, /* tp_repr */ + + /* Method suites for standard classes */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL /*(getattrofunc) pyrna_struct_meta_idprop_getattro*/, /* getattrofunc tp_getattro; */ + (setattrofunc)pyrna_struct_meta_idprop_setattro, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL, /* struct PyGetSetDef *tp_getset; */ #if defined(_MSC_VER) - NULL, /* defer assignment */ + NULL, /* defer assignment */ #else - &PyType_Type, /* struct _typeobject *tp_base; */ + &PyType_Type, /* struct _typeobject *tp_base; */ #endif - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; - /*-----------------------BPy_StructRNA method def------------------------------*/ PyTypeObject pyrna_struct_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_struct", /* tp_name */ - sizeof(BPy_StructRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor) pyrna_struct_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - (reprfunc) pyrna_struct_repr, /* tp_repr */ - - /* Method suites for standard classes */ - - NULL, /* PyNumberMethods *tp_as_number; */ - &pyrna_struct_as_sequence, /* PySequenceMethods *tp_as_sequence; */ - &pyrna_struct_as_mapping, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - - (hashfunc) pyrna_struct_hash, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - (reprfunc) pyrna_struct_str, /* reprfunc tp_str; */ - (getattrofunc) pyrna_struct_getattro, /* getattrofunc tp_getattro; */ - (setattrofunc) pyrna_struct_setattro, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_struct", /* tp_name */ + sizeof(BPy_StructRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_struct_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + (reprfunc)pyrna_struct_repr, /* tp_repr */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + &pyrna_struct_as_sequence, /* PySequenceMethods *tp_as_sequence; */ + &pyrna_struct_as_mapping, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + (hashfunc)pyrna_struct_hash, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + (reprfunc)pyrna_struct_str, /* reprfunc tp_str; */ + (getattrofunc)pyrna_struct_getattro, /* getattrofunc tp_getattro; */ + (setattrofunc)pyrna_struct_setattro, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ +/*** Assigned meaning in release 2.0 ***/ +/* call function for all accessible objects */ #ifdef USE_PYRNA_STRUCT_REFERENCE - (traverseproc) pyrna_struct_traverse, /* traverseproc tp_traverse; */ + (traverseproc)pyrna_struct_traverse, /* traverseproc tp_traverse; */ - /* delete references to contained objects */ - (inquiry)pyrna_struct_clear, /* inquiry tp_clear; */ + /* delete references to contained objects */ + (inquiry)pyrna_struct_clear, /* inquiry tp_clear; */ #else - NULL, /* traverseproc tp_traverse; */ + NULL, /* traverseproc tp_traverse; */ -/* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ #endif /* !USE_PYRNA_STRUCT_REFERENCE */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - (richcmpfunc)pyrna_struct_richcmp, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + (richcmpfunc)pyrna_struct_richcmp, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_StructRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_StructRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - pyrna_struct_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - pyrna_struct_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - pyrna_struct_new, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + pyrna_struct_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + pyrna_struct_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + pyrna_struct_new, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; /*-----------------------BPy_PropertyRNA method def------------------------------*/ PyTypeObject pyrna_prop_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_prop", /* tp_name */ - sizeof(BPy_PropertyRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor) pyrna_prop_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - (reprfunc) pyrna_prop_repr, /* tp_repr */ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_prop", /* tp_name */ + sizeof(BPy_PropertyRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + (reprfunc)pyrna_prop_repr, /* tp_repr */ - /* Method suites for standard classes */ + /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ - /* More standard operations (here for binary compatibility) */ + /* More standard operations (here for binary compatibility) */ - (hashfunc) pyrna_prop_hash, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - (reprfunc) pyrna_prop_str, /* reprfunc tp_str; */ + (hashfunc)pyrna_prop_hash, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + (reprfunc)pyrna_prop_str, /* reprfunc tp_str; */ - /* will only use these if this is a subtype of a py class */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ + /* will only use these if this is a subtype of a py class */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - (richcmpfunc)pyrna_prop_richcmp, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + (richcmpfunc)pyrna_prop_richcmp, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - pyrna_prop_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - pyrna_prop_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - pyrna_prop_new, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + pyrna_prop_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + pyrna_prop_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + pyrna_prop_new, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; PyTypeObject pyrna_prop_array_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_prop_array", /* tp_name */ - sizeof(BPy_PropertyArrayRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)pyrna_prop_array_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - (reprfunc)pyrna_prop_array_repr, /* tp_repr */ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_prop_array", /* tp_name */ + sizeof(BPy_PropertyArrayRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_array_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + (reprfunc)pyrna_prop_array_repr, /* tp_repr */ - /* Method suites for standard classes */ + /* Method suites for standard classes */ - &pyrna_prop_array_as_number, /* PyNumberMethods *tp_as_number; */ - &pyrna_prop_array_as_sequence, /* PySequenceMethods *tp_as_sequence; */ - &pyrna_prop_array_as_mapping, /* PyMappingMethods *tp_as_mapping; */ + &pyrna_prop_array_as_number, /* PyNumberMethods *tp_as_number; */ + &pyrna_prop_array_as_sequence, /* PySequenceMethods *tp_as_sequence; */ + &pyrna_prop_array_as_mapping, /* PyMappingMethods *tp_as_mapping; */ - /* More standard operations (here for binary compatibility) */ + /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ - /* will only use these if this is a subtype of a py class */ - (getattrofunc) pyrna_prop_array_getattro, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ + /* will only use these if this is a subtype of a py class */ + (getattrofunc)pyrna_prop_array_getattro, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons (subclassed) ***/ - NULL, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons (subclassed) ***/ + NULL, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_PropertyArrayRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_PropertyArrayRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - (getiterfunc)pyrna_prop_array_iter, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - pyrna_prop_array_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ - &pyrna_prop_Type, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + (getiterfunc)pyrna_prop_array_iter, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + pyrna_prop_array_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ + &pyrna_prop_Type, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; PyTypeObject pyrna_prop_collection_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_prop_collection", /* tp_name */ - sizeof(BPy_PropertyRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)pyrna_prop_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* subclassed */ /* tp_repr */ - - /* Method suites for standard classes */ - - &pyrna_prop_collection_as_number, /* PyNumberMethods *tp_as_number; */ - &pyrna_prop_collection_as_sequence, /* PySequenceMethods *tp_as_sequence; */ - &pyrna_prop_collection_as_mapping, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - - /* will only use these if this is a subtype of a py class */ - (getattrofunc) pyrna_prop_collection_getattro, /* getattrofunc tp_getattro; */ - (setattrofunc) pyrna_prop_collection_setattro, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons (subclassed) ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_prop_collection", /* tp_name */ + sizeof(BPy_PropertyRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + NULL, + /* subclassed */ /* tp_repr */ + + /* Method suites for standard classes */ + + &pyrna_prop_collection_as_number, /* PyNumberMethods *tp_as_number; */ + &pyrna_prop_collection_as_sequence, /* PySequenceMethods *tp_as_sequence; */ + &pyrna_prop_collection_as_mapping, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + + /* will only use these if this is a subtype of a py class */ + (getattrofunc)pyrna_prop_collection_getattro, /* getattrofunc tp_getattro; */ + (setattrofunc)pyrna_prop_collection_setattro, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons (subclassed) ***/ + NULL, /* richcmpfunc tp_richcompare; */ + +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - (getiterfunc)pyrna_prop_collection_iter, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - pyrna_prop_collection_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ - &pyrna_prop_Type, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + (getiterfunc)pyrna_prop_collection_iter, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + pyrna_prop_collection_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ + &pyrna_prop_Type, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; /* only for add/remove/move methods */ static PyTypeObject pyrna_prop_collection_idprop_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_prop_collection_idprop", /* tp_name */ - sizeof(BPy_PropertyRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)pyrna_prop_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* subclassed */ /* tp_repr */ - - /* Method suites for standard classes */ - - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - - /* will only use these if this is a subtype of a py class */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons (subclassed) ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_prop_collection_idprop", /* tp_name */ + sizeof(BPy_PropertyRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + NULL, + /* subclassed */ /* tp_repr */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + + /* will only use these if this is a subtype of a py class */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons (subclassed) ***/ + NULL, /* richcmpfunc tp_richcompare; */ + +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - pyrna_prop_collection_idprop_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ - &pyrna_prop_collection_Type, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + pyrna_prop_collection_idprop_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL /*pyrna_prop_getseters*/, /* struct PyGetSetDef *tp_getset; */ + &pyrna_prop_collection_Type, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; /*-----------------------BPy_PropertyRNA method def------------------------------*/ PyTypeObject pyrna_func_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_func", /* tp_name */ - sizeof(BPy_FunctionRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - NULL, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - (reprfunc) pyrna_func_repr, /* tp_repr */ + PyVarObject_HEAD_INIT(NULL, 0) "bpy_func", /* tp_name */ + sizeof(BPy_FunctionRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + NULL, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + (reprfunc)pyrna_func_repr, /* tp_repr */ - /* Method suites for standard classes */ + /* Method suites for standard classes */ - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ - /* More standard operations (here for binary compatibility) */ + /* More standard operations (here for binary compatibility) */ - NULL, /* hashfunc tp_hash; */ - (ternaryfunc)pyrna_func_call, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ + NULL, /* hashfunc tp_hash; */ + (ternaryfunc)pyrna_func_call, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ - /* will only use these if this is a subtype of a py class */ - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ + /* will only use these if this is a subtype of a py class */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - NULL, /* richcmpfunc tp_richcompare; */ + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ - /*** weak reference enabler ***/ +/*** weak reference enabler ***/ #ifdef USE_WEAKREFS - offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ + offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ #else - 0, + 0, #endif - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - NULL, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - pyrna_func_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + pyrna_func_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; #ifdef USE_PYRNA_ITER @@ -6643,232 +6760,232 @@ static void pyrna_prop_collection_iter_dealloc(BPy_PropertyCollectionIterRNA *se static PyObject *pyrna_prop_collection_iter_next(BPy_PropertyCollectionIterRNA *self); static PyTypeObject pyrna_prop_collection_iter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "bpy_prop_collection_iter", /* tp_name */ - sizeof(BPy_PropertyCollectionIterRNA), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)pyrna_prop_collection_iter_dealloc, /* tp_dealloc */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* subclassed */ /* tp_repr */ - - /* Method suites for standard classes */ - - NULL, /* PyNumberMethods *tp_as_number; */ - NULL, /* PySequenceMethods *tp_as_sequence; */ - NULL, /* PyMappingMethods *tp_as_mapping; */ - - /* More standard operations (here for binary compatibility) */ - - NULL, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ - NULL, /* reprfunc tp_str; */ - - /* will only use these if this is a subtype of a py class */ -#if defined(_MSC_VER) - NULL, /* defer assignment */ -#else - PyObject_GenericGetAttr, /* getattrofunc tp_getattro; */ -#endif - NULL, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT, /* long tp_flags; */ - - NULL, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - /* call function for all accessible objects */ - NULL, /* traverseproc tp_traverse; */ - - /* delete references to contained objects */ - NULL, /* inquiry tp_clear; */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons (subclassed) ***/ - NULL, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ -#ifdef USE_WEAKREFS - offsetof(BPy_PropertyCollectionIterRNA, in_weakreflist), /* long tp_weaklistoffset; */ -#else - 0, -#endif - /*** Added in release 2.2 ***/ - /* Iterators */ -#if defined(_MSC_VER) - NULL, /* defer assignment */ -#else - PyObject_SelfIter, /* getiterfunc tp_iter; */ -#endif - (iternextfunc) pyrna_prop_collection_iter_next, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - NULL, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - NULL, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - NULL, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + PyVarObject_HEAD_INIT(NULL, 0) "bpy_prop_collection_iter", /* tp_name */ + sizeof(BPy_PropertyCollectionIterRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_collection_iter_dealloc, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, + /* tp_compare */ /* DEPRECATED in python 3.0! */ + NULL, + /* subclassed */ /* tp_repr */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + +/* will only use these if this is a subtype of a py class */ +# if defined(_MSC_VER) + NULL, /* defer assignment */ +# else + PyObject_GenericGetAttr, /* getattrofunc tp_getattro; */ +# endif + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons (subclassed) ***/ + NULL, /* richcmpfunc tp_richcompare; */ + +/*** weak reference enabler ***/ +# ifdef USE_WEAKREFS + offsetof(BPy_PropertyCollectionIterRNA, in_weakreflist), /* long tp_weaklistoffset; */ +# else + 0, +# endif +/*** Added in release 2.2 ***/ +/* Iterators */ +# if defined(_MSC_VER) + NULL, /* defer assignment */ +# else + PyObject_SelfIter, /* getiterfunc tp_iter; */ +# endif + (iternextfunc)pyrna_prop_collection_iter_next, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; static PyObject *pyrna_prop_collection_iter_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop) { - BPy_PropertyCollectionIterRNA *self = PyObject_New(BPy_PropertyCollectionIterRNA, &pyrna_prop_collection_iter_Type); + BPy_PropertyCollectionIterRNA *self = PyObject_New(BPy_PropertyCollectionIterRNA, + &pyrna_prop_collection_iter_Type); -#ifdef USE_WEAKREFS - self->in_weakreflist = NULL; -#endif +# ifdef USE_WEAKREFS + self->in_weakreflist = NULL; +# endif - RNA_property_collection_begin(ptr, prop, &self->iter); + RNA_property_collection_begin(ptr, prop, &self->iter); - return (PyObject *)self; + return (PyObject *)self; } static PyObject *pyrna_prop_collection_iter(BPy_PropertyRNA *self) { - return pyrna_prop_collection_iter_CreatePyObject(&self->ptr, self->prop); + return pyrna_prop_collection_iter_CreatePyObject(&self->ptr, self->prop); } static PyObject *pyrna_prop_collection_iter_next(BPy_PropertyCollectionIterRNA *self) { - if (self->iter.valid == false) { - PyErr_SetNone(PyExc_StopIteration); - return NULL; - } - else { - BPy_StructRNA *pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&self->iter.ptr); + if (self->iter.valid == false) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + else { + BPy_StructRNA *pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&self->iter.ptr); -#ifdef USE_PYRNA_STRUCT_REFERENCE - if (pyrna) { /* unlikely but may fail */ - if ((PyObject *)pyrna != Py_None) { - /* hold a reference to the iterator since it may have - * allocated memory 'pyrna' needs. eg: introspecting dynamic enum's */ - /* TODO, we could have an api call to know if this is needed since most collections don't */ - pyrna_struct_reference_set(pyrna, (PyObject *)self); - } - } -#endif /* !USE_PYRNA_STRUCT_REFERENCE */ +# ifdef USE_PYRNA_STRUCT_REFERENCE + if (pyrna) { /* unlikely but may fail */ + if ((PyObject *)pyrna != Py_None) { + /* hold a reference to the iterator since it may have + * allocated memory 'pyrna' needs. eg: introspecting dynamic enum's */ + /* TODO, we could have an api call to know if this is needed since most collections don't */ + pyrna_struct_reference_set(pyrna, (PyObject *)self); + } + } +# endif /* !USE_PYRNA_STRUCT_REFERENCE */ - RNA_property_collection_next(&self->iter); + RNA_property_collection_next(&self->iter); - return (PyObject *)pyrna; - } + return (PyObject *)pyrna; + } } - static void pyrna_prop_collection_iter_dealloc(BPy_PropertyCollectionIterRNA *self) { -#ifdef USE_WEAKREFS - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *)self); - } -#endif +# ifdef USE_WEAKREFS + if (self->in_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject *)self); + } +# endif - RNA_property_collection_end(&self->iter); + RNA_property_collection_end(&self->iter); - PyObject_DEL(self); + PyObject_DEL(self); } /* --- collection iterator: end --- */ #endif /* !USE_PYRNA_ITER */ - static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna) { - PointerRNA ptr; - PyObject *item; + PointerRNA ptr; + PyObject *item; - Py_INCREF(newclass); + Py_INCREF(newclass); - if (RNA_struct_py_type_get(srna)) { - PyC_ObSpit("RNA WAS SET - ", RNA_struct_py_type_get(srna)); - } + if (RNA_struct_py_type_get(srna)) { + PyC_ObSpit("RNA WAS SET - ", RNA_struct_py_type_get(srna)); + } - Py_XDECREF(((PyObject *)RNA_struct_py_type_get(srna))); + Py_XDECREF(((PyObject *)RNA_struct_py_type_get(srna))); - RNA_struct_py_type_set(srna, (void *)newclass); /* Store for later use */ + RNA_struct_py_type_set(srna, (void *)newclass); /* Store for later use */ - /* Not 100% needed but useful, - * having an instance within a type looks wrong however this instance IS an rna type */ + /* Not 100% needed but useful, + * having an instance within a type looks wrong however this instance IS an rna type */ - /* python deals with the circular ref */ - RNA_pointer_create(NULL, &RNA_Struct, srna, &ptr); - item = pyrna_struct_CreatePyObject(&ptr); + /* python deals with the circular ref */ + RNA_pointer_create(NULL, &RNA_Struct, srna, &ptr); + item = pyrna_struct_CreatePyObject(&ptr); - /* note, must set the class not the __dict__ else the internal slots are not updated correctly */ - PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item); - Py_DECREF(item); + /* note, must set the class not the __dict__ else the internal slots are not updated correctly */ + PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item); + Py_DECREF(item); - /* add staticmethods and classmethods */ - { - const PointerRNA func_ptr = {{NULL}, srna, NULL}; - const ListBase *lb; - Link *link; + /* add staticmethods and classmethods */ + { + const PointerRNA func_ptr = {{NULL}, srna, NULL}; + const ListBase *lb; + Link *link; - lb = RNA_struct_type_functions(srna); - for (link = lb->first; link; link = link->next) { - FunctionRNA *func = (FunctionRNA *)link; - const int flag = RNA_function_flag(func); - if ((flag & FUNC_NO_SELF) && /* is staticmethod or classmethod */ - (flag & FUNC_REGISTER) == false) /* is not for registration */ - { - /* we may want to set the type of this later */ - PyObject *func_py = pyrna_func_to_py(&func_ptr, func); - PyObject_SetAttrString(newclass, RNA_function_identifier(func), func_py); - Py_DECREF(func_py); - } - } - } + lb = RNA_struct_type_functions(srna); + for (link = lb->first; link; link = link->next) { + FunctionRNA *func = (FunctionRNA *)link; + const int flag = RNA_function_flag(func); + if ((flag & FUNC_NO_SELF) && /* is staticmethod or classmethod */ + (flag & FUNC_REGISTER) == false) /* is not for registration */ + { + /* we may want to set the type of this later */ + PyObject *func_py = pyrna_func_to_py(&func_ptr, func); + PyObject_SetAttrString(newclass, RNA_function_identifier(func), func_py); + Py_DECREF(func_py); + } + } + } - /* done with rna instance */ + /* done with rna instance */ } static PyObject *pyrna_srna_Subtype(StructRNA *srna); /* return a borrowed reference */ -static PyObject *pyrna_srna_PyBase(StructRNA *srna) //, PyObject *bpy_types_dict) +static PyObject *pyrna_srna_PyBase(StructRNA *srna) //, PyObject *bpy_types_dict) { - /* Assume RNA_struct_py_type_get(srna) was already checked */ - StructRNA *base; + /* Assume RNA_struct_py_type_get(srna) was already checked */ + StructRNA *base; - PyObject *py_base = NULL; + PyObject *py_base = NULL; - /* get the base type */ - base = RNA_struct_base(srna); + /* get the base type */ + base = RNA_struct_base(srna); - if (base && base != srna) { - /* printf("debug subtype %s %p\n", RNA_struct_identifier(srna), srna); */ - py_base = pyrna_srna_Subtype(base); //, bpy_types_dict); - Py_DECREF(py_base); /* srna owns, this is only to pass as an arg */ - } + if (base && base != srna) { + /* printf("debug subtype %s %p\n", RNA_struct_identifier(srna), srna); */ + py_base = pyrna_srna_Subtype(base); //, bpy_types_dict); + Py_DECREF(py_base); /* srna owns, this is only to pass as an arg */ + } - if (py_base == NULL) { - py_base = (PyObject *)&pyrna_struct_Type; - } + if (py_base == NULL) { + py_base = (PyObject *)&pyrna_struct_Type; + } - return py_base; + return py_base; } /* check if we have a native python subclass, use it when it exists @@ -6877,378 +6994,379 @@ static PyObject *bpy_types_dict = NULL; static PyObject *pyrna_srna_ExternalType(StructRNA *srna) { - const char *idname = RNA_struct_identifier(srna); - PyObject *newclass; - - if (bpy_types_dict == NULL) { - PyObject *bpy_types = PyImport_ImportModuleLevel("bpy_types", NULL, NULL, NULL, 0); - - if (bpy_types == NULL) { - PyErr_Print(); - PyErr_Clear(); - CLOG_ERROR(BPY_LOG_RNA, "failed to find 'bpy_types' module"); - return NULL; - } - bpy_types_dict = PyModule_GetDict(bpy_types); /* borrow */ - Py_DECREF(bpy_types); /* fairly safe to assume the dict is kept */ - } - - newclass = PyDict_GetItemString(bpy_types_dict, idname); - - /* sanity check, could skip this unless in debug mode */ - if (newclass) { - PyObject *base_compare = pyrna_srna_PyBase(srna); - //PyObject *slots = PyObject_GetAttrString(newclass, "__slots__"); // cant do this because it gets superclasses values! - //PyObject *bases = PyObject_GetAttrString(newclass, "__bases__"); // can do this but faster not to. - PyObject *tp_bases = ((PyTypeObject *)newclass)->tp_bases; - PyObject *tp_slots = PyDict_GetItem(((PyTypeObject *)newclass)->tp_dict, bpy_intern_str___slots__); - - if (tp_slots == NULL) { - CLOG_ERROR(BPY_LOG_RNA, "expected class '%s' to have __slots__ defined, see bpy_types.py", idname); - newclass = NULL; - } - else if (PyTuple_GET_SIZE(tp_bases)) { - PyObject *base = PyTuple_GET_ITEM(tp_bases, 0); - - if (base_compare != base) { - char pyob_info[256]; - PyC_ObSpitStr(pyob_info, sizeof(pyob_info), base_compare); - CLOG_ERROR(BPY_LOG_RNA, - "incorrect subclassing of SRNA '%s', expected '%s', see bpy_types.py", - idname, pyob_info); - newclass = NULL; - } - else { - CLOG_INFO(BPY_LOG_RNA, 2, "SRNA sub-classed: '%s'", idname); - } - } - } - - return newclass; + const char *idname = RNA_struct_identifier(srna); + PyObject *newclass; + + if (bpy_types_dict == NULL) { + PyObject *bpy_types = PyImport_ImportModuleLevel("bpy_types", NULL, NULL, NULL, 0); + + if (bpy_types == NULL) { + PyErr_Print(); + PyErr_Clear(); + CLOG_ERROR(BPY_LOG_RNA, "failed to find 'bpy_types' module"); + return NULL; + } + bpy_types_dict = PyModule_GetDict(bpy_types); /* borrow */ + Py_DECREF(bpy_types); /* fairly safe to assume the dict is kept */ + } + + newclass = PyDict_GetItemString(bpy_types_dict, idname); + + /* sanity check, could skip this unless in debug mode */ + if (newclass) { + PyObject *base_compare = pyrna_srna_PyBase(srna); + //PyObject *slots = PyObject_GetAttrString(newclass, "__slots__"); // cant do this because it gets superclasses values! + //PyObject *bases = PyObject_GetAttrString(newclass, "__bases__"); // can do this but faster not to. + PyObject *tp_bases = ((PyTypeObject *)newclass)->tp_bases; + PyObject *tp_slots = PyDict_GetItem(((PyTypeObject *)newclass)->tp_dict, + bpy_intern_str___slots__); + + if (tp_slots == NULL) { + CLOG_ERROR( + BPY_LOG_RNA, "expected class '%s' to have __slots__ defined, see bpy_types.py", idname); + newclass = NULL; + } + else if (PyTuple_GET_SIZE(tp_bases)) { + PyObject *base = PyTuple_GET_ITEM(tp_bases, 0); + + if (base_compare != base) { + char pyob_info[256]; + PyC_ObSpitStr(pyob_info, sizeof(pyob_info), base_compare); + CLOG_ERROR(BPY_LOG_RNA, + "incorrect subclassing of SRNA '%s', expected '%s', see bpy_types.py", + idname, + pyob_info); + newclass = NULL; + } + else { + CLOG_INFO(BPY_LOG_RNA, 2, "SRNA sub-classed: '%s'", idname); + } + } + } + + return newclass; } static PyObject *pyrna_srna_Subtype(StructRNA *srna) { - PyObject *newclass = NULL; - - /* stupid/simple case */ - if (srna == NULL) { - newclass = NULL; /* Nothing to do */ - } /* the class may have already been declared & allocated */ - else if ((newclass = RNA_struct_py_type_get(srna))) { - Py_INCREF(newclass); - } /* check if bpy_types.py module has the class defined in it */ - else if ((newclass = pyrna_srna_ExternalType(srna))) { - pyrna_subtype_set_rna(newclass, srna); - Py_INCREF(newclass); - } /* create a new class instance with the C api - * mainly for the purposing of matching the C/rna type hierarchy */ - else { - /* subclass equivalents - * - class myClass(myBase): - * some = 'value' # or ... - * - myClass = type(name='myClass', bases=(myBase,), dict={'__module__': 'bpy.types', '__slots__': ()}) - */ - - /* Assume RNA_struct_py_type_get(srna) was already checked */ - PyObject *py_base = pyrna_srna_PyBase(srna); - PyObject *metaclass; - const char *idname = RNA_struct_identifier(srna); - - /* remove __doc__ for now */ - // const char *descr = RNA_struct_ui_description(srna); - // if (!descr) descr = "(no docs)"; - // "__doc__", descr - - if (RNA_struct_idprops_check(srna) && - !PyObject_IsSubclass(py_base, (PyObject *)&pyrna_struct_meta_idprop_Type)) - { - metaclass = (PyObject *)&pyrna_struct_meta_idprop_Type; - } - else { - metaclass = (PyObject *)&PyType_Type; - } - - /* always use O not N when calling, N causes refcount errors */ + PyObject *newclass = NULL; + + /* stupid/simple case */ + if (srna == NULL) { + newclass = NULL; /* Nothing to do */ + } /* the class may have already been declared & allocated */ + else if ((newclass = RNA_struct_py_type_get(srna))) { + Py_INCREF(newclass); + } /* check if bpy_types.py module has the class defined in it */ + else if ((newclass = pyrna_srna_ExternalType(srna))) { + pyrna_subtype_set_rna(newclass, srna); + Py_INCREF(newclass); + } /* create a new class instance with the C api + * mainly for the purposing of matching the C/rna type hierarchy */ + else { + /* subclass equivalents + * - class myClass(myBase): + * some = 'value' # or ... + * - myClass = type(name='myClass', bases=(myBase,), dict={'__module__': 'bpy.types', '__slots__': ()}) + */ + + /* Assume RNA_struct_py_type_get(srna) was already checked */ + PyObject *py_base = pyrna_srna_PyBase(srna); + PyObject *metaclass; + const char *idname = RNA_struct_identifier(srna); + + /* remove __doc__ for now */ + // const char *descr = RNA_struct_ui_description(srna); + // if (!descr) descr = "(no docs)"; + // "__doc__", descr + + if (RNA_struct_idprops_check(srna) && + !PyObject_IsSubclass(py_base, (PyObject *)&pyrna_struct_meta_idprop_Type)) { + metaclass = (PyObject *)&pyrna_struct_meta_idprop_Type; + } + else { + metaclass = (PyObject *)&PyType_Type; + } + + /* always use O not N when calling, N causes refcount errors */ #if 0 - newclass = PyObject_CallFunction(metaclass, "s(O) {sss()}", - idname, py_base, "__module__", "bpy.types", "__slots__"); + newclass = PyObject_CallFunction(metaclass, "s(O) {sss()}", + idname, py_base, "__module__", "bpy.types", "__slots__"); #else - { - /* longhand of the call above */ - PyObject *args, *item, *value; - int ok; + { + /* longhand of the call above */ + PyObject *args, *item, *value; + int ok; - args = PyTuple_New(3); + args = PyTuple_New(3); - /* arg[0] (name=...) */ - PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(idname)); + /* arg[0] (name=...) */ + PyTuple_SET_ITEM(args, 0, PyUnicode_FromString(idname)); + /* arg[1] (bases=...) */ + PyTuple_SET_ITEM(args, 1, item = PyTuple_New(1)); + PyTuple_SET_ITEM(item, 0, Py_INCREF_RET(py_base)); - /* arg[1] (bases=...) */ - PyTuple_SET_ITEM(args, 1, item = PyTuple_New(1)); - PyTuple_SET_ITEM(item, 0, Py_INCREF_RET(py_base)); + /* arg[2] (dict=...) */ + PyTuple_SET_ITEM(args, 2, item = PyDict_New()); + ok = PyDict_SetItem(item, bpy_intern_str___module__, bpy_intern_str_bpy_types); + BLI_assert(ok != -1); + ok = PyDict_SetItem(item, bpy_intern_str___slots__, value = PyTuple_New(0)); + Py_DECREF(value); + BLI_assert(ok != -1); + newclass = PyObject_CallObject(metaclass, args); + Py_DECREF(args); - /* arg[2] (dict=...) */ - PyTuple_SET_ITEM(args, 2, item = PyDict_New()); - ok = PyDict_SetItem(item, bpy_intern_str___module__, bpy_intern_str_bpy_types); - BLI_assert(ok != -1); - ok = PyDict_SetItem(item, bpy_intern_str___slots__, value = PyTuple_New(0)); Py_DECREF(value); - BLI_assert(ok != -1); - - newclass = PyObject_CallObject(metaclass, args); - Py_DECREF(args); - - (void)ok; - } + (void)ok; + } #endif - /* newclass will now have 2 ref's, ???, probably 1 is internal since decrefing here segfaults */ + /* newclass will now have 2 ref's, ???, probably 1 is internal since decrefing here segfaults */ - /* PyC_ObSpit("new class ref", newclass); */ + /* PyC_ObSpit("new class ref", newclass); */ - if (newclass) { - /* srna owns one, and the other is owned by the caller */ - pyrna_subtype_set_rna(newclass, srna); + if (newclass) { + /* srna owns one, and the other is owned by the caller */ + pyrna_subtype_set_rna(newclass, srna); - /* XXX, adding this back segfaults blender on load. */ - // Py_DECREF(newclass); /* let srna own */ - } - else { - /* this should not happen */ - CLOG_ERROR(BPY_LOG_RNA, "failed to register '%s'", idname); - PyErr_Print(); - PyErr_Clear(); - } - } + /* XXX, adding this back segfaults blender on load. */ + // Py_DECREF(newclass); /* let srna own */ + } + else { + /* this should not happen */ + CLOG_ERROR(BPY_LOG_RNA, "failed to register '%s'", idname); + PyErr_Print(); + PyErr_Clear(); + } + } - return newclass; + return newclass; } /* use for subtyping so we know which srna is used for a PointerRNA */ static StructRNA *srna_from_ptr(PointerRNA *ptr) { - if (ptr->type == &RNA_Struct) { - return ptr->data; - } - else { - return ptr->type; - } + if (ptr->type == &RNA_Struct) { + return ptr->data; + } + else { + return ptr->type; + } } /* always returns a new ref, be sure to decref when done */ static PyObject *pyrna_struct_Subtype(PointerRNA *ptr) { - return pyrna_srna_Subtype(srna_from_ptr(ptr)); + return pyrna_srna_Subtype(srna_from_ptr(ptr)); } /*-----------------------CreatePyObject---------------------------------*/ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr) { - BPy_StructRNA *pyrna = NULL; - - /* note: don't rely on this to return None since NULL data with a valid type can often crash */ - if (ptr->data == NULL && ptr->type == NULL) { /* Operator RNA has NULL data */ - Py_RETURN_NONE; - } - - /* New in 2.8x, since not many types support instancing - * we may want to use a flag to avoid looping over all classes. - campbell */ - void **instance = ptr->data ? RNA_struct_instance(ptr) : NULL; - if (instance && *instance) { - pyrna = *instance; - - /* Refine may have changed types after the first instance was created. */ - if (ptr->type == pyrna->ptr.type) { - Py_INCREF(pyrna); - return (PyObject *)pyrna; - } - else { - /* Existing users will need to use 'type_recast' method. */ - Py_DECREF(pyrna); - *instance = NULL; - /* Continue as if no instance was made */ -#if 0 /* no need to assign, will be written to next... */ - pyrna = NULL; + BPy_StructRNA *pyrna = NULL; + + /* note: don't rely on this to return None since NULL data with a valid type can often crash */ + if (ptr->data == NULL && ptr->type == NULL) { /* Operator RNA has NULL data */ + Py_RETURN_NONE; + } + + /* New in 2.8x, since not many types support instancing + * we may want to use a flag to avoid looping over all classes. - campbell */ + void **instance = ptr->data ? RNA_struct_instance(ptr) : NULL; + if (instance && *instance) { + pyrna = *instance; + + /* Refine may have changed types after the first instance was created. */ + if (ptr->type == pyrna->ptr.type) { + Py_INCREF(pyrna); + return (PyObject *)pyrna; + } + else { + /* Existing users will need to use 'type_recast' method. */ + Py_DECREF(pyrna); + *instance = NULL; + /* Continue as if no instance was made */ +#if 0 /* no need to assign, will be written to next... */ + pyrna = NULL; #endif - } - } - - { - PyTypeObject *tp = (PyTypeObject *)pyrna_struct_Subtype(ptr); - - if (tp) { - pyrna = (BPy_StructRNA *) tp->tp_alloc(tp, 0); - Py_DECREF(tp); /* srna owns, cant hold a ref */ - } - else { - CLOG_WARN(BPY_LOG_RNA, "could not make type '%s'", RNA_struct_identifier(ptr->type)); - pyrna = (BPy_StructRNA *) PyObject_GC_New(BPy_StructRNA, &pyrna_struct_Type); + } + } + + { + PyTypeObject *tp = (PyTypeObject *)pyrna_struct_Subtype(ptr); + + if (tp) { + pyrna = (BPy_StructRNA *)tp->tp_alloc(tp, 0); + Py_DECREF(tp); /* srna owns, cant hold a ref */ + } + else { + CLOG_WARN(BPY_LOG_RNA, "could not make type '%s'", RNA_struct_identifier(ptr->type)); + pyrna = (BPy_StructRNA *)PyObject_GC_New(BPy_StructRNA, &pyrna_struct_Type); #ifdef USE_WEAKREFS - pyrna->in_weakreflist = NULL; + pyrna->in_weakreflist = NULL; #endif - } - } + } + } - if (pyrna == NULL) { - PyErr_SetString(PyExc_MemoryError, "couldn't create bpy_struct object"); - return NULL; - } + if (pyrna == NULL) { + PyErr_SetString(PyExc_MemoryError, "couldn't create bpy_struct object"); + return NULL; + } - /* Blender's instance owns a reference (to avoid Python freeing it). */ - if (instance) { - *instance = pyrna; - Py_INCREF(pyrna); - } + /* Blender's instance owns a reference (to avoid Python freeing it). */ + if (instance) { + *instance = pyrna; + Py_INCREF(pyrna); + } - pyrna->ptr = *ptr; + pyrna->ptr = *ptr; #ifdef PYRNA_FREE_SUPPORT - pyrna->freeptr = false; + pyrna->freeptr = false; #endif #ifdef USE_PYRNA_STRUCT_REFERENCE - pyrna->reference = NULL; + pyrna->reference = NULL; #endif - // PyC_ObSpit("NewStructRNA: ", (PyObject *)pyrna); + // PyC_ObSpit("NewStructRNA: ", (PyObject *)pyrna); #ifdef USE_PYRNA_INVALIDATE_WEAKREF - if (ptr->id.data) { - id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna); - } + if (ptr->id.data) { + id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna); + } #endif - return (PyObject *)pyrna; + return (PyObject *)pyrna; } PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop) { - BPy_PropertyRNA *pyrna; + BPy_PropertyRNA *pyrna; - if (RNA_property_array_check(prop) == 0) { - PyTypeObject *type; + if (RNA_property_array_check(prop) == 0) { + PyTypeObject *type; - if (RNA_property_type(prop) != PROP_COLLECTION) { - type = &pyrna_prop_Type; - } - else { - if ((RNA_property_flag(prop) & PROP_IDPROPERTY) == 0) { - type = &pyrna_prop_collection_Type; - } - else { - type = &pyrna_prop_collection_idprop_Type; - } - } + if (RNA_property_type(prop) != PROP_COLLECTION) { + type = &pyrna_prop_Type; + } + else { + if ((RNA_property_flag(prop) & PROP_IDPROPERTY) == 0) { + type = &pyrna_prop_collection_Type; + } + else { + type = &pyrna_prop_collection_idprop_Type; + } + } - pyrna = (BPy_PropertyRNA *) PyObject_NEW(BPy_PropertyRNA, type); + pyrna = (BPy_PropertyRNA *)PyObject_NEW(BPy_PropertyRNA, type); #ifdef USE_WEAKREFS - pyrna->in_weakreflist = NULL; + pyrna->in_weakreflist = NULL; #endif - } - else { - pyrna = (BPy_PropertyRNA *) PyObject_NEW(BPy_PropertyArrayRNA, &pyrna_prop_array_Type); - ((BPy_PropertyArrayRNA *)pyrna)->arraydim = 0; - ((BPy_PropertyArrayRNA *)pyrna)->arrayoffset = 0; + } + else { + pyrna = (BPy_PropertyRNA *)PyObject_NEW(BPy_PropertyArrayRNA, &pyrna_prop_array_Type); + ((BPy_PropertyArrayRNA *)pyrna)->arraydim = 0; + ((BPy_PropertyArrayRNA *)pyrna)->arrayoffset = 0; #ifdef USE_WEAKREFS - ((BPy_PropertyArrayRNA *)pyrna)->in_weakreflist = NULL; + ((BPy_PropertyArrayRNA *)pyrna)->in_weakreflist = NULL; #endif - } + } - if (pyrna == NULL) { - PyErr_SetString(PyExc_MemoryError, "couldn't create BPy_rna object"); - return NULL; - } + if (pyrna == NULL) { + PyErr_SetString(PyExc_MemoryError, "couldn't create BPy_rna object"); + return NULL; + } - pyrna->ptr = *ptr; - pyrna->prop = prop; + pyrna->ptr = *ptr; + pyrna->prop = prop; #ifdef USE_PYRNA_INVALIDATE_WEAKREF - if (ptr->id.data) { - id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna); - } + if (ptr->id.data) { + id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna); + } #endif - return (PyObject *)pyrna; + return (PyObject *)pyrna; } /* utility func to be used by external modules, *sneaky!* */ PyObject *pyrna_id_CreatePyObject(ID *id) { - if (id) { - PointerRNA ptr; - RNA_id_pointer_create(id, &ptr); - return pyrna_struct_CreatePyObject(&ptr); - } - else { - Py_RETURN_NONE; - } + if (id) { + PointerRNA ptr; + RNA_id_pointer_create(id, &ptr); + return pyrna_struct_CreatePyObject(&ptr); + } + else { + Py_RETURN_NONE; + } } bool pyrna_id_FromPyObject(PyObject *obj, ID **id) { - if (pyrna_id_CheckPyObject(obj)) { - *id = ((BPy_StructRNA *)obj)->ptr.id.data; - return true; - } - else { - *id = NULL; - return false; - } + if (pyrna_id_CheckPyObject(obj)) { + *id = ((BPy_StructRNA *)obj)->ptr.id.data; + return true; + } + else { + *id = NULL; + return false; + } } bool pyrna_id_CheckPyObject(PyObject *obj) { - return BPy_StructRNA_Check(obj) && (RNA_struct_is_ID(((BPy_StructRNA *) obj)->ptr.type)); + return BPy_StructRNA_Check(obj) && (RNA_struct_is_ID(((BPy_StructRNA *)obj)->ptr.type)); } void BPY_rna_init(void) { -#ifdef USE_MATHUTILS /* register mathutils callbacks, ok to run more than once. */ - mathutils_rna_array_cb_index = Mathutils_RegisterCallback(&mathutils_rna_array_cb); - mathutils_rna_matrix_cb_index = Mathutils_RegisterCallback(&mathutils_rna_matrix_cb); +#ifdef USE_MATHUTILS /* register mathutils callbacks, ok to run more than once. */ + mathutils_rna_array_cb_index = Mathutils_RegisterCallback(&mathutils_rna_array_cb); + mathutils_rna_matrix_cb_index = Mathutils_RegisterCallback(&mathutils_rna_matrix_cb); #endif - /* for some reason MSVC complains of these */ + /* for some reason MSVC complains of these */ #if defined(_MSC_VER) - pyrna_struct_meta_idprop_Type.tp_base = &PyType_Type; + pyrna_struct_meta_idprop_Type.tp_base = &PyType_Type; - pyrna_prop_collection_iter_Type.tp_iter = PyObject_SelfIter; - pyrna_prop_collection_iter_Type.tp_getattro = PyObject_GenericGetAttr; + pyrna_prop_collection_iter_Type.tp_iter = PyObject_SelfIter; + pyrna_prop_collection_iter_Type.tp_getattro = PyObject_GenericGetAttr; #endif - /* metaclass */ - if (PyType_Ready(&pyrna_struct_meta_idprop_Type) < 0) { - return; - } + /* metaclass */ + if (PyType_Ready(&pyrna_struct_meta_idprop_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_struct_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_struct_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_prop_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_prop_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_prop_array_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_prop_array_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_prop_collection_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_prop_collection_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_prop_collection_idprop_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_prop_collection_idprop_Type) < 0) { + return; + } - if (PyType_Ready(&pyrna_func_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_func_Type) < 0) { + return; + } #ifdef USE_PYRNA_ITER - if (PyType_Ready(&pyrna_prop_collection_iter_Type) < 0) { - return; - } + if (PyType_Ready(&pyrna_prop_collection_iter_Type) < 0) { + return; + } #endif } @@ -7256,26 +7374,26 @@ void BPY_rna_init(void) static PointerRNA *rna_module_ptr = NULL; PyObject *BPY_rna_module(void) { - BPy_StructRNA *pyrna; - PointerRNA ptr; + BPy_StructRNA *pyrna; + PointerRNA ptr; - /* for now, return the base RNA type rather than a real module */ - RNA_main_pointer_create(G_MAIN, &ptr); - pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); + /* for now, return the base RNA type rather than a real module */ + RNA_main_pointer_create(G_MAIN, &ptr); + pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); - rna_module_ptr = &pyrna->ptr; - return (PyObject *)pyrna; + rna_module_ptr = &pyrna->ptr; + return (PyObject *)pyrna; } void BPY_update_rna_module(void) { - if (rna_module_ptr) { + if (rna_module_ptr) { #if 0 - RNA_main_pointer_create(G_MAIN, rna_module_ptr); + RNA_main_pointer_create(G_MAIN, rna_module_ptr); #else - rna_module_ptr->data = G_MAIN; /* just set data is enough */ + rna_module_ptr->data = G_MAIN; /* just set data is enough */ #endif - } + } } #if 0 @@ -7283,49 +7401,48 @@ void BPY_update_rna_module(void) * without having the datatypes in blender */ PyObject *BPY_rna_doc(void) { - PointerRNA ptr; + PointerRNA ptr; - /* for now, return the base RNA type rather than a real module */ - RNA_blender_rna_pointer_create(&ptr); + /* for now, return the base RNA type rather than a real module */ + RNA_blender_rna_pointer_create(&ptr); - return pyrna_struct_CreatePyObject(&ptr); + return pyrna_struct_CreatePyObject(&ptr); } #endif - /* pyrna_basetype_* - BPy_BaseTypeRNA is just a BPy_PropertyRNA struct with a different type * the self->ptr and self->prop are always set to the "structs" collection */ /* ---------------getattr-------------------------------------------- */ static PyObject *pyrna_basetype_getattro(BPy_BaseTypeRNA *self, PyObject *pyname) { - PointerRNA newptr; - PyObject *ret; - const char *name = _PyUnicode_AsString(pyname); - - if (name == NULL) { - PyErr_SetString(PyExc_AttributeError, "bpy.types: __getattr__ must be a string"); - ret = NULL; - } - else if (RNA_property_collection_lookup_string(&self->ptr, self->prop, name, &newptr)) { - ret = pyrna_struct_Subtype(&newptr); - if (ret == NULL) { - PyErr_Format(PyExc_RuntimeError, - "bpy.types.%.200s subtype could not be generated, this is a bug!", - _PyUnicode_AsString(pyname)); - } - } - else { + PointerRNA newptr; + PyObject *ret; + const char *name = _PyUnicode_AsString(pyname); + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy.types: __getattr__ must be a string"); + ret = NULL; + } + else if (RNA_property_collection_lookup_string(&self->ptr, self->prop, name, &newptr)) { + ret = pyrna_struct_Subtype(&newptr); + if (ret == NULL) { + PyErr_Format(PyExc_RuntimeError, + "bpy.types.%.200s subtype could not be generated, this is a bug!", + _PyUnicode_AsString(pyname)); + } + } + else { #if 0 - PyErr_Format(PyExc_AttributeError, - "bpy.types.%.200s RNA_Struct does not exist", - _PyUnicode_AsString(pyname)); - return NULL; + PyErr_Format(PyExc_AttributeError, + "bpy.types.%.200s RNA_Struct does not exist", + _PyUnicode_AsString(pyname)); + return NULL; #endif - /* The error raised here will be displayed */ - ret = PyObject_GenericGetAttr((PyObject *)self, pyname); - } + /* The error raised here will be displayed */ + ret = PyObject_GenericGetAttr((PyObject *)self, pyname); + } - return ret; + return ret; } static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self); @@ -7333,43 +7450,42 @@ static PyObject *pyrna_register_class(PyObject *self, PyObject *py_class); static PyObject *pyrna_unregister_class(PyObject *self, PyObject *py_class); static struct PyMethodDef pyrna_basetype_methods[] = { - {"__dir__", (PyCFunction)pyrna_basetype_dir, METH_NOARGS, ""}, - {NULL, NULL, 0, NULL}, + {"__dir__", (PyCFunction)pyrna_basetype_dir, METH_NOARGS, ""}, + {NULL, NULL, 0, NULL}, }; /* used to call ..._keys() direct, but we need to filter out operator subclasses */ #if 0 static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self) { - PyObject *list; -#if 0 - PyMethodDef *meth; -#endif + PyObject *list; +# if 0 + PyMethodDef *meth; +# endif - list = pyrna_prop_collection_keys(self); /* like calling structs.keys(), avoids looping here */ + list = pyrna_prop_collection_keys(self); /* like calling structs.keys(), avoids looping here */ -#if 0 /* for now only contains __dir__ */ - for (meth = pyrna_basetype_methods; meth->ml_name; meth++) { - PyList_APPEND(list, PyUnicode_FromString(meth->ml_name)); - } -#endif - return list; +# if 0 /* for now only contains __dir__ */ + for (meth = pyrna_basetype_methods; meth->ml_name; meth++) { + PyList_APPEND(list, PyUnicode_FromString(meth->ml_name)); + } +# endif + return list; } #else static PyObject *pyrna_basetype_dir(BPy_BaseTypeRNA *self) { - PyObject *ret = PyList_New(0); + PyObject *ret = PyList_New(0); - RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) - { - StructRNA *srna = itemptr.data; - PyList_APPEND(ret, PyUnicode_FromString(RNA_struct_identifier(srna))); - } - RNA_PROP_END; + RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { + StructRNA *srna = itemptr.data; + PyList_APPEND(ret, PyUnicode_FromString(RNA_struct_identifier(srna))); + } + RNA_PROP_END; - return ret; + return ret; } #endif @@ -7381,98 +7497,103 @@ static PyTypeObject pyrna_basetype_Type = BLANK_PYTHON_TYPE; */ PyObject *BPY_rna_types(void) { - BPy_BaseTypeRNA *self; - - if ((pyrna_basetype_Type.tp_flags & Py_TPFLAGS_READY) == 0) { - pyrna_basetype_Type.tp_name = "RNA_Types"; - pyrna_basetype_Type.tp_basicsize = sizeof(BPy_BaseTypeRNA); - pyrna_basetype_Type.tp_getattro = (getattrofunc) pyrna_basetype_getattro; - pyrna_basetype_Type.tp_flags = Py_TPFLAGS_DEFAULT; - pyrna_basetype_Type.tp_methods = pyrna_basetype_methods; - - if (PyType_Ready(&pyrna_basetype_Type) < 0) { - return NULL; - } - } - - /* static members for the base class */ - /* add __name__ since help() expects its */ - PyDict_SetItem(pyrna_basetype_Type.tp_dict, bpy_intern_str___name__, bpy_intern_str_bpy_types); - - /* internal base types we have no other accessors for */ - { - PyTypeObject *pyrna_types[] = { - &pyrna_struct_meta_idprop_Type, - &pyrna_struct_Type, - &pyrna_prop_Type, - &pyrna_prop_array_Type, - &pyrna_prop_collection_Type, - &pyrna_func_Type, - }; - - for (int i = 0; i < ARRAY_SIZE(pyrna_types); i += 1) { - PyDict_SetItemString(pyrna_basetype_Type.tp_dict, pyrna_types[i]->tp_name, (PyObject *)pyrna_types[i]); - } - } - - self = (BPy_BaseTypeRNA *)PyObject_NEW(BPy_BaseTypeRNA, &pyrna_basetype_Type); - - /* avoid doing this lookup for every getattr */ - RNA_blender_rna_pointer_create(&self->ptr); - self->prop = RNA_struct_find_property(&self->ptr, "structs"); + BPy_BaseTypeRNA *self; + + if ((pyrna_basetype_Type.tp_flags & Py_TPFLAGS_READY) == 0) { + pyrna_basetype_Type.tp_name = "RNA_Types"; + pyrna_basetype_Type.tp_basicsize = sizeof(BPy_BaseTypeRNA); + pyrna_basetype_Type.tp_getattro = (getattrofunc)pyrna_basetype_getattro; + pyrna_basetype_Type.tp_flags = Py_TPFLAGS_DEFAULT; + pyrna_basetype_Type.tp_methods = pyrna_basetype_methods; + + if (PyType_Ready(&pyrna_basetype_Type) < 0) { + return NULL; + } + } + + /* static members for the base class */ + /* add __name__ since help() expects its */ + PyDict_SetItem(pyrna_basetype_Type.tp_dict, bpy_intern_str___name__, bpy_intern_str_bpy_types); + + /* internal base types we have no other accessors for */ + { + PyTypeObject *pyrna_types[] = { + &pyrna_struct_meta_idprop_Type, + &pyrna_struct_Type, + &pyrna_prop_Type, + &pyrna_prop_array_Type, + &pyrna_prop_collection_Type, + &pyrna_func_Type, + }; + + for (int i = 0; i < ARRAY_SIZE(pyrna_types); i += 1) { + PyDict_SetItemString( + pyrna_basetype_Type.tp_dict, pyrna_types[i]->tp_name, (PyObject *)pyrna_types[i]); + } + } + + self = (BPy_BaseTypeRNA *)PyObject_NEW(BPy_BaseTypeRNA, &pyrna_basetype_Type); + + /* avoid doing this lookup for every getattr */ + RNA_blender_rna_pointer_create(&self->ptr); + self->prop = RNA_struct_find_property(&self->ptr, "structs"); #ifdef USE_WEAKREFS - self->in_weakreflist = NULL; + self->in_weakreflist = NULL; #endif - return (PyObject *)self; + return (PyObject *)self; } StructRNA *pyrna_struct_as_srna(PyObject *self, const bool parent, const char *error_prefix) { - BPy_StructRNA *py_srna = NULL; - StructRNA *srna; - - /* ack, PyObject_GetAttrString wont look up this types tp_dict first :/ */ - if (PyType_Check(self)) { - py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna); - Py_XINCREF(py_srna); - } - - if (parent) { - /* be very careful with this since it will return a parent classes srna. - * modifying this will do confusing stuff! */ - if (py_srna == NULL) { - py_srna = (BPy_StructRNA *)PyObject_GetAttr(self, bpy_intern_str_bl_rna); - } - } - - if (py_srna == NULL) { - PyErr_Format(PyExc_RuntimeError, - "%.200s, missing bl_rna attribute from '%.200s' instance (may not be registered)", - error_prefix, Py_TYPE(self)->tp_name); - return NULL; - } - - if (!BPy_StructRNA_Check(py_srna)) { - PyErr_Format(PyExc_TypeError, - "%.200s, bl_rna attribute wrong type '%.200s' on '%.200s'' instance", - error_prefix, Py_TYPE(py_srna)->tp_name, - Py_TYPE(self)->tp_name); - Py_DECREF(py_srna); - return NULL; - } - - if (py_srna->ptr.type != &RNA_Struct) { - PyErr_Format(PyExc_TypeError, - "%.200s, bl_rna attribute not a RNA_Struct, on '%.200s'' instance", - error_prefix, Py_TYPE(self)->tp_name); - Py_DECREF(py_srna); - return NULL; - } - - srna = py_srna->ptr.data; - Py_DECREF(py_srna); - - return srna; + BPy_StructRNA *py_srna = NULL; + StructRNA *srna; + + /* ack, PyObject_GetAttrString wont look up this types tp_dict first :/ */ + if (PyType_Check(self)) { + py_srna = (BPy_StructRNA *)PyDict_GetItem(((PyTypeObject *)self)->tp_dict, + bpy_intern_str_bl_rna); + Py_XINCREF(py_srna); + } + + if (parent) { + /* be very careful with this since it will return a parent classes srna. + * modifying this will do confusing stuff! */ + if (py_srna == NULL) { + py_srna = (BPy_StructRNA *)PyObject_GetAttr(self, bpy_intern_str_bl_rna); + } + } + + if (py_srna == NULL) { + PyErr_Format(PyExc_RuntimeError, + "%.200s, missing bl_rna attribute from '%.200s' instance (may not be registered)", + error_prefix, + Py_TYPE(self)->tp_name); + return NULL; + } + + if (!BPy_StructRNA_Check(py_srna)) { + PyErr_Format(PyExc_TypeError, + "%.200s, bl_rna attribute wrong type '%.200s' on '%.200s'' instance", + error_prefix, + Py_TYPE(py_srna)->tp_name, + Py_TYPE(self)->tp_name); + Py_DECREF(py_srna); + return NULL; + } + + if (py_srna->ptr.type != &RNA_Struct) { + PyErr_Format(PyExc_TypeError, + "%.200s, bl_rna attribute not a RNA_Struct, on '%.200s'' instance", + error_prefix, + Py_TYPE(self)->tp_name); + Py_DECREF(py_srna); + return NULL; + } + + srna = py_srna->ptr.data; + Py_DECREF(py_srna); + + return srna; } /* Orphan functions, not sure where they should go */ @@ -7482,755 +7603,791 @@ StructRNA *pyrna_struct_as_srna(PyObject *self, const bool parent, const char *e StructRNA *srna_from_self(PyObject *self, const char *error_prefix) { - if (self == NULL) { - return NULL; - } - else if (PyCapsule_CheckExact(self)) { - return PyCapsule_GetPointer(self, NULL); - } - else if (PyType_Check(self) == 0) { - return NULL; - } - else { - /* These cases above not errors, they just mean the type was not compatible - * After this any errors will be raised in the script */ + if (self == NULL) { + return NULL; + } + else if (PyCapsule_CheckExact(self)) { + return PyCapsule_GetPointer(self, NULL); + } + else if (PyType_Check(self) == 0) { + return NULL; + } + else { + /* These cases above not errors, they just mean the type was not compatible + * After this any errors will be raised in the script */ - PyObject *error_type, *error_value, *error_traceback; - StructRNA *srna; + PyObject *error_type, *error_value, *error_traceback; + StructRNA *srna; - PyErr_Fetch(&error_type, &error_value, &error_traceback); - PyErr_Clear(); + PyErr_Fetch(&error_type, &error_value, &error_traceback); + PyErr_Clear(); - srna = pyrna_struct_as_srna(self, false, error_prefix); + srna = pyrna_struct_as_srna(self, false, error_prefix); - if (!PyErr_Occurred()) { - PyErr_Restore(error_type, error_value, error_traceback); - } + if (!PyErr_Occurred()) { + PyErr_Restore(error_type, error_value, error_traceback); + } - return srna; - } + return srna; + } } static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item) { - /* We only care about results from C which - * are for sure types, save some time with error */ - if (pyrna_is_deferred_prop(item)) { - - PyObject *py_func, *py_kw, *py_srna_cobject, *py_ret; - - if (PyArg_ParseTuple(item, "OO!", &py_func, &PyDict_Type, &py_kw)) { - PyObject *args_fake; - - if (*_PyUnicode_AsString(key) == '_') { - PyErr_Format(PyExc_ValueError, - "bpy_struct \"%.200s\" registration error: " - "%.200s could not register because the property starts with an '_'\n", - RNA_struct_identifier(srna), _PyUnicode_AsString(key)); - return -1; - } - py_srna_cobject = PyCapsule_New(srna, NULL, NULL); - - /* not 100% nice :/, modifies the dict passed, should be ok */ - PyDict_SetItem(py_kw, bpy_intern_str_attr, key); - - args_fake = PyTuple_New(1); - PyTuple_SET_ITEM(args_fake, 0, py_srna_cobject); - - PyObject *type = PyDict_GetItemString(py_kw, "type"); - StructRNA *type_srna = srna_from_self(type, ""); - if (type_srna) { - if (!RNA_struct_idprops_datablock_allowed(srna) && - (*(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == BPy_PointerProperty || - *(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == BPy_CollectionProperty) && - RNA_struct_idprops_contains_datablock(type_srna)) - { - PyErr_Format(PyExc_ValueError, - "bpy_struct \"%.200s\" doesn't support datablock properties\n", - RNA_struct_identifier(srna)); - return -1; - } - } - - py_ret = PyObject_Call(py_func, args_fake, py_kw); - - if (py_ret) { - Py_DECREF(py_ret); - Py_DECREF(args_fake); /* free's py_srna_cobject too */ - } - else { - /* _must_ print before decreffing args_fake */ - PyErr_Print(); - PyErr_Clear(); - - Py_DECREF(args_fake); /* free's py_srna_cobject too */ - - // PyC_LineSpit(); - PyErr_Format(PyExc_ValueError, - "bpy_struct \"%.200s\" registration error: " - "%.200s could not register\n", - RNA_struct_identifier(srna), _PyUnicode_AsString(key)); - return -1; - } - } - else { - /* Since this is a class dict, ignore args that can't be passed */ - - /* for testing only */ + /* We only care about results from C which + * are for sure types, save some time with error */ + if (pyrna_is_deferred_prop(item)) { + + PyObject *py_func, *py_kw, *py_srna_cobject, *py_ret; + + if (PyArg_ParseTuple(item, "OO!", &py_func, &PyDict_Type, &py_kw)) { + PyObject *args_fake; + + if (*_PyUnicode_AsString(key) == '_') { + PyErr_Format(PyExc_ValueError, + "bpy_struct \"%.200s\" registration error: " + "%.200s could not register because the property starts with an '_'\n", + RNA_struct_identifier(srna), + _PyUnicode_AsString(key)); + return -1; + } + py_srna_cobject = PyCapsule_New(srna, NULL, NULL); + + /* not 100% nice :/, modifies the dict passed, should be ok */ + PyDict_SetItem(py_kw, bpy_intern_str_attr, key); + + args_fake = PyTuple_New(1); + PyTuple_SET_ITEM(args_fake, 0, py_srna_cobject); + + PyObject *type = PyDict_GetItemString(py_kw, "type"); + StructRNA *type_srna = srna_from_self(type, ""); + if (type_srna) { + if (!RNA_struct_idprops_datablock_allowed(srna) && + (*(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == BPy_PointerProperty || + *(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == + BPy_CollectionProperty) && + RNA_struct_idprops_contains_datablock(type_srna)) { + PyErr_Format(PyExc_ValueError, + "bpy_struct \"%.200s\" doesn't support datablock properties\n", + RNA_struct_identifier(srna)); + return -1; + } + } + + py_ret = PyObject_Call(py_func, args_fake, py_kw); + + if (py_ret) { + Py_DECREF(py_ret); + Py_DECREF(args_fake); /* free's py_srna_cobject too */ + } + else { + /* _must_ print before decreffing args_fake */ + PyErr_Print(); + PyErr_Clear(); + + Py_DECREF(args_fake); /* free's py_srna_cobject too */ + + // PyC_LineSpit(); + PyErr_Format(PyExc_ValueError, + "bpy_struct \"%.200s\" registration error: " + "%.200s could not register\n", + RNA_struct_identifier(srna), + _PyUnicode_AsString(key)); + return -1; + } + } + else { + /* Since this is a class dict, ignore args that can't be passed */ + + /* for testing only */ #if 0 - PyC_ObSpit("Why doesn't this work??", item); - PyErr_Print(); + PyC_ObSpit("Why doesn't this work??", item); + PyErr_Print(); #endif - PyErr_Clear(); - } - } + PyErr_Clear(); + } + } - return 0; + return 0; } static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict) { - PyObject *annotations_dict; - PyObject *item, *key; - Py_ssize_t pos = 0; - int ret = 0; - - /* in both cases PyDict_CheckExact(class_dict) will be true even - * though Operators have a metaclass dict namespace */ - if ((annotations_dict = PyDict_GetItem(class_dict, bpy_intern_str___annotations__)) && - PyDict_CheckExact(annotations_dict)) - { - while (PyDict_Next(annotations_dict, &pos, &key, &item)) { - ret = deferred_register_prop(srna, key, item); - - if (ret != 0) { - break; - } - } - } - - { - /* This block can be removed once 2.8x is released and annotations are in use. */ - bool has_warning = false; - while (PyDict_Next(class_dict, &pos, &key, &item)) { - if (pyrna_is_deferred_prop(item)) { - if (!has_warning) { - printf("Warning: class %.200s " - "contains a properties which should be an annotation!\n", - RNA_struct_identifier(srna)); - PyC_LineSpit(); - has_warning = true; - } - printf(" make annotation: %.200s.%.200s\n", - RNA_struct_identifier(srna), _PyUnicode_AsString(key)); - } - ret = deferred_register_prop(srna, key, item); - - if (ret != 0) { - break; - } - } - } - - return ret; + PyObject *annotations_dict; + PyObject *item, *key; + Py_ssize_t pos = 0; + int ret = 0; + + /* in both cases PyDict_CheckExact(class_dict) will be true even + * though Operators have a metaclass dict namespace */ + if ((annotations_dict = PyDict_GetItem(class_dict, bpy_intern_str___annotations__)) && + PyDict_CheckExact(annotations_dict)) { + while (PyDict_Next(annotations_dict, &pos, &key, &item)) { + ret = deferred_register_prop(srna, key, item); + + if (ret != 0) { + break; + } + } + } + + { + /* This block can be removed once 2.8x is released and annotations are in use. */ + bool has_warning = false; + while (PyDict_Next(class_dict, &pos, &key, &item)) { + if (pyrna_is_deferred_prop(item)) { + if (!has_warning) { + printf( + "Warning: class %.200s " + "contains a properties which should be an annotation!\n", + RNA_struct_identifier(srna)); + PyC_LineSpit(); + has_warning = true; + } + printf(" make annotation: %.200s.%.200s\n", + RNA_struct_identifier(srna), + _PyUnicode_AsString(key)); + } + ret = deferred_register_prop(srna, key, item); + + if (ret != 0) { + break; + } + } + } + + return ret; } static int pyrna_deferred_register_class_recursive(StructRNA *srna, PyTypeObject *py_class) { - const int len = PyTuple_GET_SIZE(py_class->tp_bases); - int i, ret; - - /* first scan base classes for registerable properties */ - for (i = 0; i < len; i++) { - PyTypeObject *py_superclass = (PyTypeObject *)PyTuple_GET_ITEM(py_class->tp_bases, i); - - /* the rules for using these base classes are not clear, - * 'object' is of course not worth looking into and - * existing subclasses of RNA would cause a lot more dictionary - * looping then is needed (SomeOperator would scan Operator.__dict__) - * which is harmless but not at all useful. - * - * So only scan base classes which are not subclasses if blender types. - * This best fits having 'mix-in' classes for operators and render engines. - */ - if (py_superclass != &PyBaseObject_Type && - !PyObject_IsSubclass((PyObject *)py_superclass, (PyObject *)&pyrna_struct_Type)) - { - ret = pyrna_deferred_register_class_recursive(srna, py_superclass); - - if (ret != 0) { - return ret; - } - } - } - - /* not register out own properties */ - return pyrna_deferred_register_props(srna, py_class->tp_dict); /* getattr(..., "__dict__") returns a proxy */ + const int len = PyTuple_GET_SIZE(py_class->tp_bases); + int i, ret; + + /* first scan base classes for registerable properties */ + for (i = 0; i < len; i++) { + PyTypeObject *py_superclass = (PyTypeObject *)PyTuple_GET_ITEM(py_class->tp_bases, i); + + /* the rules for using these base classes are not clear, + * 'object' is of course not worth looking into and + * existing subclasses of RNA would cause a lot more dictionary + * looping then is needed (SomeOperator would scan Operator.__dict__) + * which is harmless but not at all useful. + * + * So only scan base classes which are not subclasses if blender types. + * This best fits having 'mix-in' classes for operators and render engines. + */ + if (py_superclass != &PyBaseObject_Type && + !PyObject_IsSubclass((PyObject *)py_superclass, (PyObject *)&pyrna_struct_Type)) { + ret = pyrna_deferred_register_class_recursive(srna, py_superclass); + + if (ret != 0) { + return ret; + } + } + } + + /* not register out own properties */ + return pyrna_deferred_register_props( + srna, py_class->tp_dict); /* getattr(..., "__dict__") returns a proxy */ } int pyrna_deferred_register_class(StructRNA *srna, PyTypeObject *py_class) { - /* Panels and Menus don't need this - * save some time and skip the checks here */ - if (!RNA_struct_idprops_register_check(srna)) { - return 0; - } + /* Panels and Menus don't need this + * save some time and skip the checks here */ + if (!RNA_struct_idprops_register_check(srna)) { + return 0; + } - return pyrna_deferred_register_class_recursive(srna, py_class); + return pyrna_deferred_register_class_recursive(srna, py_class); } /*-------------------- Type Registration ------------------------*/ static int rna_function_arg_count(FunctionRNA *func, int *min_count) { - const ListBase *lb = RNA_function_defined_parameters(func); - PropertyRNA *parm; - Link *link; - int flag = RNA_function_flag(func); - const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); - int count = is_staticmethod ? 0 : 1; - bool done_min_count = false; - - for (link = lb->first; link; link = link->next) { - parm = (PropertyRNA *)link; - if (!(RNA_parameter_flag(parm) & PARM_OUTPUT)) { - if (!done_min_count && (RNA_parameter_flag(parm) & PARM_PYFUNC_OPTIONAL)) { - /* From now on, following parameters are optional in py func */ - if (min_count) { - *min_count = count; - } - done_min_count = true; - } - count++; - } - } - - if (!done_min_count && min_count) { - *min_count = count; - } - return count; -} - -static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, void *py_data, int *have_function) -{ - const ListBase *lb; - Link *link; - const char *class_type = RNA_struct_identifier(srna); - StructRNA *srna_base = RNA_struct_base(srna); - PyObject *py_class = (PyObject *)py_data; - PyObject *base_class = RNA_struct_py_type_get(srna); - PyObject *item; - int i, arg_count, func_arg_count, func_arg_min_count = 0; - const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */ - - if (srna_base) { - if (bpy_class_validate_recursive(dummyptr, srna_base, py_data, have_function) != 0) { - return -1; - } - } - - if (base_class) { - if (!PyObject_IsSubclass(py_class, base_class)) { - PyErr_Format(PyExc_TypeError, - "expected %.200s subclass of class \"%.200s\"", - class_type, py_class_name); - return -1; - } - } - - /* verify callback functions */ - lb = RNA_struct_type_functions(srna); - i = 0; - for (link = lb->first; link; link = link->next) { - FunctionRNA *func = (FunctionRNA *)link; - const int flag = RNA_function_flag(func); - /* TODO(campbell): this is used for classmethod's too, - * even though class methods should have 'FUNC_USE_SELF_TYPE' set, see Operator.poll for eg. - * Keep this as-is since its working but we should be using 'FUNC_USE_SELF_TYPE' for many functions. */ - const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); - - if (!(flag & FUNC_REGISTER)) { - continue; - } - - item = PyObject_GetAttrString(py_class, RNA_function_identifier(func)); - - have_function[i] = (item != NULL); - i++; - - if (item == NULL) { - if ((flag & (FUNC_REGISTER_OPTIONAL & ~FUNC_REGISTER)) == 0) { - PyErr_Format(PyExc_AttributeError, - "expected %.200s, %.200s class to have an \"%.200s\" attribute", - class_type, py_class_name, - RNA_function_identifier(func)); - return -1; - } - - PyErr_Clear(); - } - else { - Py_DECREF(item); /* no need to keep a ref, the class owns it (technically we should keep a ref but...) */ - if (is_staticmethod) { - if (PyMethod_Check(item) == 0) { - PyErr_Format(PyExc_TypeError, - "expected %.200s, %.200s class \"%.200s\" " - "attribute to be a static/class method, not a %.200s", - class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name); - return -1; - } - item = ((PyMethodObject *)item)->im_func; - } - else { - if (PyFunction_Check(item) == 0) { - PyErr_Format(PyExc_TypeError, - "expected %.200s, %.200s class \"%.200s\" " - "attribute to be a function, not a %.200s", - class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name); - return -1; - } - } - - func_arg_count = rna_function_arg_count(func, &func_arg_min_count); - - if (func_arg_count >= 0) { /* -1 if we don't care*/ - arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; - - /* note, the number of args we check for and the number of args we give to - * '@staticmethods' are different (quirk of python), - * this is why rna_function_arg_count() doesn't return the value -1*/ - if (is_staticmethod) { - func_arg_count++; - func_arg_min_count++; - } - - if (arg_count < func_arg_min_count || arg_count > func_arg_count) { - if (func_arg_min_count != func_arg_count) { - PyErr_Format(PyExc_ValueError, - "expected %.200s, %.200s class \"%.200s\" function to have between %d and %d " - "args, found %d", - class_type, py_class_name, RNA_function_identifier(func), - func_arg_count, func_arg_min_count, arg_count); - } - else { - PyErr_Format(PyExc_ValueError, - "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d", - class_type, py_class_name, RNA_function_identifier(func), - func_arg_count, arg_count); - } - return -1; - } - } - } - } - - /* verify properties */ - lb = RNA_struct_type_properties(srna); - for (link = lb->first; link; link = link->next) { - const char *identifier; - PropertyRNA *prop = (PropertyRNA *)link; - const int flag = RNA_property_flag(prop); - - if (!(flag & PROP_REGISTER)) { - continue; - } - - /* TODO(campbell): Use Python3.7x _PyObject_LookupAttr(), also in the macro below. */ - identifier = RNA_property_identifier(prop); - item = PyObject_GetAttrString(py_class, identifier); - - if (item == NULL) { - PyErr_Clear(); - /* Sneaky workaround to use the class name as the bl_idname */ - -#define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \ - else if (STREQ(identifier, rna_attr)) { \ - if ((item = PyObject_GetAttr(py_class, py_attr))) { \ - if (item != Py_None) { \ - if (pyrna_py_to_prop(dummyptr, prop, NULL, \ - item, "validating class:") != 0) \ - { \ - Py_DECREF(item); \ - return -1; \ - } \ - } \ - Py_DECREF(item); \ - } \ - else { \ - PyErr_Clear(); \ - } \ - } /* intentionally allow else here */ - - if (false) {} /* needed for macro */ - BPY_REPLACEMENT_STRING("bl_idname", bpy_intern_str___name__) - BPY_REPLACEMENT_STRING("bl_description", bpy_intern_str___doc__) - -#undef BPY_REPLACEMENT_STRING - - if (item == NULL && (((flag & PROP_REGISTER_OPTIONAL) != PROP_REGISTER_OPTIONAL))) { - PyErr_Format(PyExc_AttributeError, - "expected %.200s, %.200s class to have an \"%.200s\" attribute", - class_type, py_class_name, identifier); - return -1; - } - - PyErr_Clear(); - } - else { - if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) { - Py_DECREF(item); - return -1; - } - Py_DECREF(item); - } - } - - return 0; + const ListBase *lb = RNA_function_defined_parameters(func); + PropertyRNA *parm; + Link *link; + int flag = RNA_function_flag(func); + const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); + int count = is_staticmethod ? 0 : 1; + bool done_min_count = false; + + for (link = lb->first; link; link = link->next) { + parm = (PropertyRNA *)link; + if (!(RNA_parameter_flag(parm) & PARM_OUTPUT)) { + if (!done_min_count && (RNA_parameter_flag(parm) & PARM_PYFUNC_OPTIONAL)) { + /* From now on, following parameters are optional in py func */ + if (min_count) { + *min_count = count; + } + done_min_count = true; + } + count++; + } + } + + if (!done_min_count && min_count) { + *min_count = count; + } + return count; +} + +static int bpy_class_validate_recursive(PointerRNA *dummyptr, + StructRNA *srna, + void *py_data, + int *have_function) +{ + const ListBase *lb; + Link *link; + const char *class_type = RNA_struct_identifier(srna); + StructRNA *srna_base = RNA_struct_base(srna); + PyObject *py_class = (PyObject *)py_data; + PyObject *base_class = RNA_struct_py_type_get(srna); + PyObject *item; + int i, arg_count, func_arg_count, func_arg_min_count = 0; + const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */ + + if (srna_base) { + if (bpy_class_validate_recursive(dummyptr, srna_base, py_data, have_function) != 0) { + return -1; + } + } + + if (base_class) { + if (!PyObject_IsSubclass(py_class, base_class)) { + PyErr_Format(PyExc_TypeError, + "expected %.200s subclass of class \"%.200s\"", + class_type, + py_class_name); + return -1; + } + } + + /* verify callback functions */ + lb = RNA_struct_type_functions(srna); + i = 0; + for (link = lb->first; link; link = link->next) { + FunctionRNA *func = (FunctionRNA *)link; + const int flag = RNA_function_flag(func); + /* TODO(campbell): this is used for classmethod's too, + * even though class methods should have 'FUNC_USE_SELF_TYPE' set, see Operator.poll for eg. + * Keep this as-is since its working but we should be using 'FUNC_USE_SELF_TYPE' for many functions. */ + const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); + + if (!(flag & FUNC_REGISTER)) { + continue; + } + + item = PyObject_GetAttrString(py_class, RNA_function_identifier(func)); + + have_function[i] = (item != NULL); + i++; + + if (item == NULL) { + if ((flag & (FUNC_REGISTER_OPTIONAL & ~FUNC_REGISTER)) == 0) { + PyErr_Format(PyExc_AttributeError, + "expected %.200s, %.200s class to have an \"%.200s\" attribute", + class_type, + py_class_name, + RNA_function_identifier(func)); + return -1; + } + + PyErr_Clear(); + } + else { + Py_DECREF( + item); /* no need to keep a ref, the class owns it (technically we should keep a ref but...) */ + if (is_staticmethod) { + if (PyMethod_Check(item) == 0) { + PyErr_Format(PyExc_TypeError, + "expected %.200s, %.200s class \"%.200s\" " + "attribute to be a static/class method, not a %.200s", + class_type, + py_class_name, + RNA_function_identifier(func), + Py_TYPE(item)->tp_name); + return -1; + } + item = ((PyMethodObject *)item)->im_func; + } + else { + if (PyFunction_Check(item) == 0) { + PyErr_Format(PyExc_TypeError, + "expected %.200s, %.200s class \"%.200s\" " + "attribute to be a function, not a %.200s", + class_type, + py_class_name, + RNA_function_identifier(func), + Py_TYPE(item)->tp_name); + return -1; + } + } + + func_arg_count = rna_function_arg_count(func, &func_arg_min_count); + + if (func_arg_count >= 0) { /* -1 if we don't care*/ + arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; + + /* note, the number of args we check for and the number of args we give to + * '@staticmethods' are different (quirk of python), + * this is why rna_function_arg_count() doesn't return the value -1*/ + if (is_staticmethod) { + func_arg_count++; + func_arg_min_count++; + } + + if (arg_count < func_arg_min_count || arg_count > func_arg_count) { + if (func_arg_min_count != func_arg_count) { + PyErr_Format( + PyExc_ValueError, + "expected %.200s, %.200s class \"%.200s\" function to have between %d and %d " + "args, found %d", + class_type, + py_class_name, + RNA_function_identifier(func), + func_arg_count, + func_arg_min_count, + arg_count); + } + else { + PyErr_Format( + PyExc_ValueError, + "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d", + class_type, + py_class_name, + RNA_function_identifier(func), + func_arg_count, + arg_count); + } + return -1; + } + } + } + } + + /* verify properties */ + lb = RNA_struct_type_properties(srna); + for (link = lb->first; link; link = link->next) { + const char *identifier; + PropertyRNA *prop = (PropertyRNA *)link; + const int flag = RNA_property_flag(prop); + + if (!(flag & PROP_REGISTER)) { + continue; + } + + /* TODO(campbell): Use Python3.7x _PyObject_LookupAttr(), also in the macro below. */ + identifier = RNA_property_identifier(prop); + item = PyObject_GetAttrString(py_class, identifier); + + if (item == NULL) { + PyErr_Clear(); + /* Sneaky workaround to use the class name as the bl_idname */ + +#define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \ + else if (STREQ(identifier, rna_attr)) \ + { \ + if ((item = PyObject_GetAttr(py_class, py_attr))) { \ + if (item != Py_None) { \ + if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) { \ + Py_DECREF(item); \ + return -1; \ + } \ + } \ + Py_DECREF(item); \ + } \ + else { \ + PyErr_Clear(); \ + } \ + } /* intentionally allow else here */ + + if (false) { + } /* needed for macro */ + BPY_REPLACEMENT_STRING("bl_idname", bpy_intern_str___name__) + BPY_REPLACEMENT_STRING("bl_description", bpy_intern_str___doc__) + +#undef BPY_REPLACEMENT_STRING + + if (item == NULL && (((flag & PROP_REGISTER_OPTIONAL) != PROP_REGISTER_OPTIONAL))) { + PyErr_Format(PyExc_AttributeError, + "expected %.200s, %.200s class to have an \"%.200s\" attribute", + class_type, + py_class_name, + identifier); + return -1; + } + + PyErr_Clear(); + } + else { + if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) { + Py_DECREF(item); + return -1; + } + Py_DECREF(item); + } + } + + return 0; } static int bpy_class_validate(PointerRNA *dummyptr, void *py_data, int *have_function) { - return bpy_class_validate_recursive(dummyptr, dummyptr->type, py_data, have_function); + return bpy_class_validate_recursive(dummyptr, dummyptr->type, py_data, have_function); } /* TODO - multiple return values like with rna functions */ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms) { - PyObject *args; - PyObject *ret = NULL, *py_srna = NULL, *py_class_instance = NULL, *parmitem; - PyTypeObject *py_class; - PropertyRNA *parm; - ParameterIterator iter; - PointerRNA funcptr; - int err = 0, i, ret_len = 0, arg_count; - int flag = RNA_function_flag(func); - const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); - const bool is_classmethod = (flag & FUNC_NO_SELF) && (flag & FUNC_USE_SELF_TYPE); + PyObject *args; + PyObject *ret = NULL, *py_srna = NULL, *py_class_instance = NULL, *parmitem; + PyTypeObject *py_class; + PropertyRNA *parm; + ParameterIterator iter; + PointerRNA funcptr; + int err = 0, i, ret_len = 0, arg_count; + int flag = RNA_function_flag(func); + const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); + const bool is_classmethod = (flag & FUNC_NO_SELF) && (flag & FUNC_USE_SELF_TYPE); - PropertyRNA *pret_single = NULL; - void *retdata_single = NULL; + PropertyRNA *pret_single = NULL; + void *retdata_single = NULL; - PyGILState_STATE gilstate; + PyGILState_STATE gilstate; #ifdef USE_PEDANTIC_WRITE - const bool is_readonly_init = !(RNA_struct_is_a(ptr->type, &RNA_Operator) || - RNA_struct_is_a(ptr->type, &RNA_Gizmo)); - // const char *func_id = RNA_function_identifier(func); /* UNUSED */ - /* testing, for correctness, not operator and not draw function */ - const bool is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE); + const bool is_readonly_init = !(RNA_struct_is_a(ptr->type, &RNA_Operator) || + RNA_struct_is_a(ptr->type, &RNA_Gizmo)); + // const char *func_id = RNA_function_identifier(func); /* UNUSED */ + /* testing, for correctness, not operator and not draw function */ + const bool is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE); #endif - py_class = RNA_struct_py_type_get(ptr->type); - /* rare case. can happen when registering subclasses */ - if (py_class == NULL) { - CLOG_WARN(BPY_LOG_RNA, "unable to get Python class for rna struct '%.200s'", RNA_struct_identifier(ptr->type)); - return -1; - } - - /* XXX, this is needed because render engine calls without a context - * this should be supported at some point but at the moment its not! */ - if (C == NULL) { - C = BPy_GetContext(); - } - - /* annoying!, need to check if the screen gets set to NULL which is a - * hint that the file was actually re-loaded. */ - const bool is_valid_wm = (CTX_wm_manager(C) != NULL); - - bpy_context_set(C, &gilstate); - - if (!(is_staticmethod || is_classmethod)) { - /* some datatypes (operator, render engine) can store PyObjects for re-use */ - if (ptr->data) { - void **instance = RNA_struct_instance(ptr); - - if (instance) { - if (*instance) { - py_class_instance = *instance; - Py_INCREF(py_class_instance); - } - } - } - /* end exception */ - - if (py_class_instance == NULL) { - py_srna = pyrna_struct_CreatePyObject(ptr); - } - - if (py_class_instance) { - /* special case, instance is cached */ - } - else if (py_srna == NULL) { - py_class_instance = NULL; - } - else if (py_srna == Py_None) { /* probably wont ever happen but possible */ - Py_DECREF(py_srna); - py_class_instance = NULL; - } - else { + py_class = RNA_struct_py_type_get(ptr->type); + /* rare case. can happen when registering subclasses */ + if (py_class == NULL) { + CLOG_WARN(BPY_LOG_RNA, + "unable to get Python class for rna struct '%.200s'", + RNA_struct_identifier(ptr->type)); + return -1; + } + + /* XXX, this is needed because render engine calls without a context + * this should be supported at some point but at the moment its not! */ + if (C == NULL) { + C = BPy_GetContext(); + } + + /* annoying!, need to check if the screen gets set to NULL which is a + * hint that the file was actually re-loaded. */ + const bool is_valid_wm = (CTX_wm_manager(C) != NULL); + + bpy_context_set(C, &gilstate); + + if (!(is_staticmethod || is_classmethod)) { + /* some datatypes (operator, render engine) can store PyObjects for re-use */ + if (ptr->data) { + void **instance = RNA_struct_instance(ptr); + + if (instance) { + if (*instance) { + py_class_instance = *instance; + Py_INCREF(py_class_instance); + } + } + } + /* end exception */ + + if (py_class_instance == NULL) { + py_srna = pyrna_struct_CreatePyObject(ptr); + } + + if (py_class_instance) { + /* special case, instance is cached */ + } + else if (py_srna == NULL) { + py_class_instance = NULL; + } + else if (py_srna == Py_None) { /* probably wont ever happen but possible */ + Py_DECREF(py_srna); + py_class_instance = NULL; + } + else { #if 1 - /* Skip the code below and call init directly on the allocated 'py_srna' - * otherwise __init__() always needs to take a second self argument, see pyrna_struct_new(). - * Although this is annoying to have to implement a part of pythons typeobject.c:type_call(). - */ - if (py_class->tp_init) { -#ifdef USE_PEDANTIC_WRITE - const int prev_write = rna_disallow_writes; - rna_disallow_writes = is_readonly_init ? false : true; /* only operators can write on __init__ */ -#endif - - /* true in most cases even when the class its self doesn't define an __init__ function. */ - args = PyTuple_New(0); - if (py_class->tp_init(py_srna, args, NULL) < 0) { - Py_DECREF(py_srna); - py_srna = NULL; - /* err set below */ - } - Py_DECREF(args); -#ifdef USE_PEDANTIC_WRITE - rna_disallow_writes = prev_write; -#endif - } - py_class_instance = py_srna; + /* Skip the code below and call init directly on the allocated 'py_srna' + * otherwise __init__() always needs to take a second self argument, see pyrna_struct_new(). + * Although this is annoying to have to implement a part of pythons typeobject.c:type_call(). + */ + if (py_class->tp_init) { +# ifdef USE_PEDANTIC_WRITE + const int prev_write = rna_disallow_writes; + rna_disallow_writes = is_readonly_init ? false : + true; /* only operators can write on __init__ */ +# endif + + /* true in most cases even when the class its self doesn't define an __init__ function. */ + args = PyTuple_New(0); + if (py_class->tp_init(py_srna, args, NULL) < 0) { + Py_DECREF(py_srna); + py_srna = NULL; + /* err set below */ + } + Py_DECREF(args); +# ifdef USE_PEDANTIC_WRITE + rna_disallow_writes = prev_write; +# endif + } + py_class_instance = py_srna; #else - const int prev_write = rna_disallow_writes; - rna_disallow_writes = true; - - /* 'almost' all the time calling the class isn't needed. - * We could just do... */ -#if 0 - py_class_instance = py_srna; - Py_INCREF(py_class_instance); -#endif - /* - * This would work fine but means __init__ functions wouldn't run. - * none of blenders default scripts use __init__ but its nice to call it - * for general correctness. just to note why this is here when it could be safely removed. - */ - args = PyTuple_New(1); - PyTuple_SET_ITEM(args, 0, py_srna); - py_class_instance = PyObject_Call(py_class, args, NULL); - Py_DECREF(args); - - rna_disallow_writes = prev_write; + const int prev_write = rna_disallow_writes; + rna_disallow_writes = true; + + /* 'almost' all the time calling the class isn't needed. + * We could just do... */ +# if 0 + py_class_instance = py_srna; + Py_INCREF(py_class_instance); +# endif + /* + * This would work fine but means __init__ functions wouldn't run. + * none of blenders default scripts use __init__ but its nice to call it + * for general correctness. just to note why this is here when it could be safely removed. + */ + args = PyTuple_New(1); + PyTuple_SET_ITEM(args, 0, py_srna); + py_class_instance = PyObject_Call(py_class, args, NULL); + Py_DECREF(args); + + rna_disallow_writes = prev_write; #endif - if (py_class_instance == NULL) { - err = -1; /* so the error is not overridden below */ - } - } - } - - /* Initializing the class worked, now run its invoke function */ - if (err != -1 && (is_staticmethod || is_classmethod || py_class_instance)) { - PyObject *item = PyObject_GetAttrString((PyObject *)py_class, RNA_function_identifier(func)); - - if (item) { - RNA_pointer_create(NULL, &RNA_Function, func, &funcptr); - - if (is_staticmethod) { - arg_count = ((PyCodeObject *)PyFunction_GET_CODE(((PyMethodObject *)item)->im_func))->co_argcount - 1; - } - else { - arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; - } -// args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */ - args = PyTuple_New(arg_count); /* first arg is included in 'item' */ - - - if (is_staticmethod) { - i = 0; - } - else if (is_classmethod) { - PyTuple_SET_ITEM(args, 0, (PyObject *)py_class); - i = 1; - } - else { - PyTuple_SET_ITEM(args, 0, py_class_instance); - i = 1; - } - - RNA_parameter_list_begin(parms, &iter); - - /* parse function parameters */ - for (; iter.valid; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - - /* only useful for single argument returns, we'll need another list loop for multiple */ - if (RNA_parameter_flag(parm) & PARM_OUTPUT) { - ret_len++; - if (pret_single == NULL) { - pret_single = parm; - retdata_single = iter.data; - } - - continue; - } - - if (i < arg_count) { - parmitem = pyrna_param_to_py(&funcptr, parm, iter.data); - PyTuple_SET_ITEM(args, i, parmitem); - i++; - } - } + if (py_class_instance == NULL) { + err = -1; /* so the error is not overridden below */ + } + } + } + + /* Initializing the class worked, now run its invoke function */ + if (err != -1 && (is_staticmethod || is_classmethod || py_class_instance)) { + PyObject *item = PyObject_GetAttrString((PyObject *)py_class, RNA_function_identifier(func)); + + if (item) { + RNA_pointer_create(NULL, &RNA_Function, func, &funcptr); + + if (is_staticmethod) { + arg_count = + ((PyCodeObject *)PyFunction_GET_CODE(((PyMethodObject *)item)->im_func))->co_argcount - + 1; + } + else { + arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; + } + // args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */ + args = PyTuple_New(arg_count); /* first arg is included in 'item' */ + + if (is_staticmethod) { + i = 0; + } + else if (is_classmethod) { + PyTuple_SET_ITEM(args, 0, (PyObject *)py_class); + i = 1; + } + else { + PyTuple_SET_ITEM(args, 0, py_class_instance); + i = 1; + } + + RNA_parameter_list_begin(parms, &iter); + + /* parse function parameters */ + for (; iter.valid; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + + /* only useful for single argument returns, we'll need another list loop for multiple */ + if (RNA_parameter_flag(parm) & PARM_OUTPUT) { + ret_len++; + if (pret_single == NULL) { + pret_single = parm; + retdata_single = iter.data; + } + + continue; + } + + if (i < arg_count) { + parmitem = pyrna_param_to_py(&funcptr, parm, iter.data); + PyTuple_SET_ITEM(args, i, parmitem); + i++; + } + } #ifdef USE_PEDANTIC_WRITE - rna_disallow_writes = is_readonly ? true : false; + rna_disallow_writes = is_readonly ? true : false; #endif - /* *** Main Caller *** */ + /* *** Main Caller *** */ - ret = PyObject_Call(item, args, NULL); + ret = PyObject_Call(item, args, NULL); - /* *** Done Calling *** */ + /* *** Done Calling *** */ #ifdef USE_PEDANTIC_WRITE - rna_disallow_writes = false; + rna_disallow_writes = false; #endif - RNA_parameter_list_end(&iter); - Py_DECREF(item); - Py_DECREF(args); - } - else { - PyErr_Print(); - PyErr_Clear(); - 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 { - /* the error may be already set if the class instance couldn't be created */ - if (err != -1) { - 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; - } - } - - if (ret == NULL) { /* covers py_class_instance failing too */ - err = -1; - } - else { - if (ret_len == 0 && ret != Py_None) { - PyErr_Format(PyExc_RuntimeError, - "expected class %.200s, function %.200s to return None, not %.200s", - RNA_struct_identifier(ptr->type), RNA_function_identifier(func), - Py_TYPE(ret)->tp_name); - err = -1; - } - else if (ret_len == 1) { - err = pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, ""); - - /* when calling operator funcs only gives Function.result with - * no line number since the func has finished calling on error, - * re-raise the exception with more info since it would be slow to - * create prefix on every call (when there are no errors) */ - if (err == -1) { - PyC_Err_Format_Prefix(PyExc_RuntimeError, - "class %.200s, function %.200s: incompatible return value ", - RNA_struct_identifier(ptr->type), RNA_function_identifier(func)); - } - } - else if (ret_len > 1) { - - if (PyTuple_Check(ret) == 0) { - PyErr_Format(PyExc_RuntimeError, - "expected class %.200s, function %.200s to return a tuple of size %d, not %.200s", - RNA_struct_identifier(ptr->type), RNA_function_identifier(func), - ret_len, Py_TYPE(ret)->tp_name); - err = -1; - } - else if (PyTuple_GET_SIZE(ret) != ret_len) { - PyErr_Format(PyExc_RuntimeError, - "class %.200s, function %.200s to returned %d items, expected %d", - RNA_struct_identifier(ptr->type), RNA_function_identifier(func), - PyTuple_GET_SIZE(ret), ret_len); - err = -1; - } - else { - - RNA_parameter_list_begin(parms, &iter); - - /* parse function parameters */ - for (i = 0; iter.valid; RNA_parameter_list_next(&iter)) { - parm = iter.parm; - - /* only useful for single argument returns, we'll need another list loop for multiple */ - if (RNA_parameter_flag(parm) & PARM_OUTPUT) { - err = pyrna_py_to_prop(&funcptr, parm, iter.data, - PyTuple_GET_ITEM(ret, i++), - "calling class function:"); - if (err) { - break; - } - } - } - - RNA_parameter_list_end(&iter); - } - } - Py_DECREF(ret); - } - - if (err != 0) { - ReportList *reports; - /* alert the user, else they wont know unless they see the console. */ - if ((!is_staticmethod) && (!is_classmethod) && - (ptr->data) && - (RNA_struct_is_a(ptr->type, &RNA_Operator)) && - (is_valid_wm == (CTX_wm_manager(C) != NULL))) - { - wmOperator *op = ptr->data; - reports = op->reports; - } - else { - /* wont alert users but they can view in 'info' space */ - reports = CTX_wm_reports(C); - } - - BPy_errors_to_report(reports); - - /* also print in the console for py */ - PyErr_Print(); - PyErr_Clear(); - } - - bpy_context_clear(C, &gilstate); - - return err; + RNA_parameter_list_end(&iter); + Py_DECREF(item); + Py_DECREF(args); + } + else { + PyErr_Print(); + PyErr_Clear(); + 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 { + /* the error may be already set if the class instance couldn't be created */ + if (err != -1) { + 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; + } + } + + if (ret == NULL) { /* covers py_class_instance failing too */ + err = -1; + } + else { + if (ret_len == 0 && ret != Py_None) { + PyErr_Format(PyExc_RuntimeError, + "expected class %.200s, function %.200s to return None, not %.200s", + RNA_struct_identifier(ptr->type), + RNA_function_identifier(func), + Py_TYPE(ret)->tp_name); + err = -1; + } + else if (ret_len == 1) { + err = pyrna_py_to_prop(&funcptr, pret_single, retdata_single, ret, ""); + + /* when calling operator funcs only gives Function.result with + * no line number since the func has finished calling on error, + * re-raise the exception with more info since it would be slow to + * create prefix on every call (when there are no errors) */ + if (err == -1) { + PyC_Err_Format_Prefix(PyExc_RuntimeError, + "class %.200s, function %.200s: incompatible return value ", + RNA_struct_identifier(ptr->type), + RNA_function_identifier(func)); + } + } + else if (ret_len > 1) { + + if (PyTuple_Check(ret) == 0) { + PyErr_Format( + PyExc_RuntimeError, + "expected class %.200s, function %.200s to return a tuple of size %d, not %.200s", + RNA_struct_identifier(ptr->type), + RNA_function_identifier(func), + ret_len, + Py_TYPE(ret)->tp_name); + err = -1; + } + else if (PyTuple_GET_SIZE(ret) != ret_len) { + PyErr_Format(PyExc_RuntimeError, + "class %.200s, function %.200s to returned %d items, expected %d", + RNA_struct_identifier(ptr->type), + RNA_function_identifier(func), + PyTuple_GET_SIZE(ret), + ret_len); + err = -1; + } + else { + + RNA_parameter_list_begin(parms, &iter); + + /* parse function parameters */ + for (i = 0; iter.valid; RNA_parameter_list_next(&iter)) { + parm = iter.parm; + + /* only useful for single argument returns, we'll need another list loop for multiple */ + if (RNA_parameter_flag(parm) & PARM_OUTPUT) { + err = pyrna_py_to_prop( + &funcptr, parm, iter.data, PyTuple_GET_ITEM(ret, i++), "calling class function:"); + if (err) { + break; + } + } + } + + RNA_parameter_list_end(&iter); + } + } + Py_DECREF(ret); + } + + if (err != 0) { + ReportList *reports; + /* alert the user, else they wont know unless they see the console. */ + if ((!is_staticmethod) && (!is_classmethod) && (ptr->data) && + (RNA_struct_is_a(ptr->type, &RNA_Operator)) && + (is_valid_wm == (CTX_wm_manager(C) != NULL))) { + wmOperator *op = ptr->data; + reports = op->reports; + } + else { + /* wont alert users but they can view in 'info' space */ + reports = CTX_wm_reports(C); + } + + BPy_errors_to_report(reports); + + /* also print in the console for py */ + PyErr_Print(); + PyErr_Clear(); + } + + bpy_context_clear(C, &gilstate); + + return err; } static void bpy_class_free(void *pyob_ptr) { - PyObject *self = (PyObject *)pyob_ptr; - PyGILState_STATE gilstate; + PyObject *self = (PyObject *)pyob_ptr; + PyGILState_STATE gilstate; - gilstate = PyGILState_Ensure(); + gilstate = PyGILState_Ensure(); - /* breaks re-registering classes */ - // PyDict_Clear(((PyTypeObject *)self)->tp_dict); + /* breaks re-registering classes */ + // PyDict_Clear(((PyTypeObject *)self)->tp_dict); - /* remove the rna attribute instead. */ - PyDict_DelItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna); - if (PyErr_Occurred()) { - PyErr_Clear(); - } + /* remove the rna attribute instead. */ + PyDict_DelItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna); + if (PyErr_Occurred()) { + PyErr_Clear(); + } #if 0 /* needs further investigation, too annoying so quiet for now */ - if (G.debug & G_DEBUG_PYTHON) { - if (self->ob_refcnt > 1) { - PyC_ObSpit("zombie class - ref should be 1", self); - } - } + if (G.debug & G_DEBUG_PYTHON) { + if (self->ob_refcnt > 1) { + PyC_ObSpit("zombie class - ref should be 1", self); + } + } #endif - Py_DECREF((PyObject *)pyob_ptr); + Py_DECREF((PyObject *)pyob_ptr); - PyGILState_Release(gilstate); + PyGILState_Release(gilstate); } /** @@ -8241,61 +8398,56 @@ static void bpy_class_free(void *pyob_ptr) void pyrna_alloc_types(void) { #ifdef DEBUG - PyGILState_STATE gilstate; + PyGILState_STATE gilstate; - PointerRNA ptr; - PropertyRNA *prop; + PointerRNA ptr; + PropertyRNA *prop; - gilstate = PyGILState_Ensure(); + gilstate = PyGILState_Ensure(); - /* avoid doing this lookup for every getattr */ - RNA_blender_rna_pointer_create(&ptr); - prop = RNA_struct_find_property(&ptr, "structs"); + /* avoid doing this lookup for every getattr */ + RNA_blender_rna_pointer_create(&ptr); + prop = RNA_struct_find_property(&ptr, "structs"); - RNA_PROP_BEGIN (&ptr, itemptr, prop) - { - PyObject *item = pyrna_struct_Subtype(&itemptr); - if (item == NULL) { - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } - } - else { - Py_DECREF(item); - } - } - RNA_PROP_END; + RNA_PROP_BEGIN (&ptr, itemptr, prop) { + PyObject *item = pyrna_struct_Subtype(&itemptr); + if (item == NULL) { + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + } + } + else { + Py_DECREF(item); + } + } + RNA_PROP_END; - PyGILState_Release(gilstate); -#endif /* DEBUG */ + PyGILState_Release(gilstate); +#endif /* DEBUG */ } - void pyrna_free_types(void) { - PointerRNA ptr; - PropertyRNA *prop; - - /* avoid doing this lookup for every getattr */ - RNA_blender_rna_pointer_create(&ptr); - prop = RNA_struct_find_property(&ptr, "structs"); + PointerRNA ptr; + PropertyRNA *prop; + /* avoid doing this lookup for every getattr */ + RNA_blender_rna_pointer_create(&ptr); + prop = RNA_struct_find_property(&ptr, "structs"); - RNA_PROP_BEGIN (&ptr, itemptr, prop) - { - StructRNA *srna = srna_from_ptr(&itemptr); - void *py_ptr = RNA_struct_py_type_get(srna); + RNA_PROP_BEGIN (&ptr, itemptr, prop) { + StructRNA *srna = srna_from_ptr(&itemptr); + void *py_ptr = RNA_struct_py_type_get(srna); - if (py_ptr) { -#if 0 /* XXX - should be able to do this but makes python crash on exit */ - bpy_class_free(py_ptr); + if (py_ptr) { +#if 0 /* XXX - should be able to do this but makes python crash on exit */ + bpy_class_free(py_ptr); #endif - RNA_struct_py_type_set(srna, NULL); - } - } - RNA_PROP_END; - + RNA_struct_py_type_set(srna, NULL); + } + } + RNA_PROP_END; } /* Note! MemLeak XXX @@ -8308,401 +8460,429 @@ void pyrna_free_types(void) * - Should still be fixed - Campbell * */ PyDoc_STRVAR(pyrna_register_class_doc, -".. method:: register_class(cls)\n" -"\n" -" Register a subclass of a blender type in (:class:`bpy.types.Panel`,\n" -" :class:`bpy.types.UIList`, :class:`bpy.types.Menu`, :class:`bpy.types.Header`,\n" -" :class:`bpy.types.Operator`, :class:`bpy.types.KeyingSetInfo`,\n" -" :class:`bpy.types.RenderEngine`).\n" -"\n" -" If the class has a *register* class method it will be called\n" -" before registration.\n" -"\n" -" .. note::\n" -"\n" -" :exc:`ValueError` exception is raised if the class is not a\n" -" subclass of a registerable blender class.\n" -"\n" -); -PyMethodDef meth_bpy_register_class = {"register_class", pyrna_register_class, METH_O, pyrna_register_class_doc}; + ".. method:: register_class(cls)\n" + "\n" + " Register a subclass of a blender type in (:class:`bpy.types.Panel`,\n" + " :class:`bpy.types.UIList`, :class:`bpy.types.Menu`, :class:`bpy.types.Header`,\n" + " :class:`bpy.types.Operator`, :class:`bpy.types.KeyingSetInfo`,\n" + " :class:`bpy.types.RenderEngine`).\n" + "\n" + " If the class has a *register* class method it will be called\n" + " before registration.\n" + "\n" + " .. note::\n" + "\n" + " :exc:`ValueError` exception is raised if the class is not a\n" + " subclass of a registerable blender class.\n" + "\n"); +PyMethodDef meth_bpy_register_class = { + "register_class", pyrna_register_class, METH_O, pyrna_register_class_doc}; static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class) { - bContext *C = NULL; - ReportList reports; - StructRegisterFunc reg; - StructRNA *srna; - StructRNA *srna_new; - const char *identifier; - PyObject *py_cls_meth; - const char *error_prefix = "register_class(...):"; - - if (!PyType_Check(py_class)) { - PyErr_Format(PyExc_ValueError, - "register_class(...): " - "expected a class argument, not '%.200s'", Py_TYPE(py_class)->tp_name); - return NULL; - } - - if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna)) { - PyErr_SetString(PyExc_ValueError, - "register_class(...): " - "already registered as a subclass"); - return NULL; - } - - if (!pyrna_write_check()) { - PyErr_Format(PyExc_RuntimeError, - "register_class(...): " - "can't run in readonly state '%.200s'", - ((PyTypeObject *)py_class)->tp_name); - return NULL; - } - - /* warning: gets parent classes srna, only for the register function */ - srna = pyrna_struct_as_srna(py_class, true, "register_class(...):"); - if (srna == NULL) { - return NULL; - } - - /* fails in cases, cant use this check but would like to :| */ + bContext *C = NULL; + ReportList reports; + StructRegisterFunc reg; + StructRNA *srna; + StructRNA *srna_new; + const char *identifier; + PyObject *py_cls_meth; + const char *error_prefix = "register_class(...):"; + + if (!PyType_Check(py_class)) { + PyErr_Format(PyExc_ValueError, + "register_class(...): " + "expected a class argument, not '%.200s'", + Py_TYPE(py_class)->tp_name); + return NULL; + } + + if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna)) { + PyErr_SetString(PyExc_ValueError, + "register_class(...): " + "already registered as a subclass"); + return NULL; + } + + if (!pyrna_write_check()) { + PyErr_Format(PyExc_RuntimeError, + "register_class(...): " + "can't run in readonly state '%.200s'", + ((PyTypeObject *)py_class)->tp_name); + return NULL; + } + + /* warning: gets parent classes srna, only for the register function */ + srna = pyrna_struct_as_srna(py_class, true, "register_class(...):"); + if (srna == NULL) { + return NULL; + } + + /* fails in cases, cant use this check but would like to :| */ #if 0 - if (RNA_struct_py_type_get(srna)) { - PyErr_Format(PyExc_ValueError, - "register_class(...): %.200s's parent class %.200s is already registered, this is not allowed", - ((PyTypeObject *)py_class)->tp_name, RNA_struct_identifier(srna)); - return NULL; - } + if (RNA_struct_py_type_get(srna)) { + PyErr_Format(PyExc_ValueError, + "register_class(...): %.200s's parent class %.200s is already registered, this is not allowed", + ((PyTypeObject *)py_class)->tp_name, RNA_struct_identifier(srna)); + return NULL; + } #endif - /* check that we have a register callback for this type */ - reg = RNA_struct_register(srna); - - if (!reg) { - PyErr_Format(PyExc_ValueError, - "register_class(...): expected a subclass of a registerable " - "rna type (%.200s does not support registration)", - RNA_struct_identifier(srna)); - return NULL; - } - - /* get the context, so register callback can do necessary refreshes */ - C = BPy_GetContext(); - - /* call the register callback with reports & identifier */ - BKE_reports_init(&reports, RPT_STORE); - - identifier = ((PyTypeObject *)py_class)->tp_name; - - srna_new = reg(CTX_data_main(C), &reports, py_class, identifier, - bpy_class_validate, bpy_class_call, bpy_class_free); - - if (!BLI_listbase_is_empty(&reports.list)) { - const bool has_error = BPy_reports_to_error(&reports, PyExc_RuntimeError, false); - if (!has_error) { - BPy_reports_write_stdout(&reports, error_prefix); - } - BKE_reports_clear(&reports); - if (has_error) { - return NULL; - } - } - - /* python errors validating are not converted into reports so the check above will fail. - * the cause for returning NULL will be printed as an error */ - if (srna_new == NULL) { - return NULL; - } - - pyrna_subtype_set_rna(py_class, srna_new); /* takes a ref to py_class */ - - /* old srna still references us, keep the check in case registering somehow can free it */ - if (RNA_struct_py_type_get(srna)) { - RNA_struct_py_type_set(srna, NULL); - // Py_DECREF(py_class); // should be able to do this XXX since the old rna adds a new ref. - } - - /* Can't use this because it returns a dict proxy - * - * item = PyObject_GetAttrString(py_class, "__dict__"); - */ - if (pyrna_deferred_register_class(srna_new, (PyTypeObject *)py_class) != 0) { - return NULL; - } - - /* call classed register method () */ - switch (_PyObject_LookupAttr(py_class, bpy_intern_str_register, &py_cls_meth)) { - case 1: - { - PyObject *ret = PyObject_CallObject(py_cls_meth, NULL); - if (ret) { - Py_DECREF(ret); - } - else { - return NULL; - } - break; - } - case -1: - { - return NULL; - } - } - - Py_RETURN_NONE; -} - - -static int pyrna_srna_contains_pointer_prop_srna( - StructRNA *srna_props, StructRNA *srna, - const char **r_prop_identifier) -{ - PropertyRNA *prop; - LinkData *link; - - /* verify properties */ - const ListBase *lb = RNA_struct_type_properties(srna); - - for (link = lb->first; link; link = link->next) { - prop = (PropertyRNA *)link; - if (RNA_property_type(prop) == PROP_POINTER && !RNA_property_builtin(prop)) { - PointerRNA tptr; - RNA_pointer_create(NULL, &RNA_Struct, srna_props, &tptr); - - if (RNA_property_pointer_type(&tptr, prop) == srna) { - *r_prop_identifier = RNA_property_identifier(prop); - return 1; - } - } - } - - return 0; + /* check that we have a register callback for this type */ + reg = RNA_struct_register(srna); + + if (!reg) { + PyErr_Format(PyExc_ValueError, + "register_class(...): expected a subclass of a registerable " + "rna type (%.200s does not support registration)", + RNA_struct_identifier(srna)); + return NULL; + } + + /* get the context, so register callback can do necessary refreshes */ + C = BPy_GetContext(); + + /* call the register callback with reports & identifier */ + BKE_reports_init(&reports, RPT_STORE); + + identifier = ((PyTypeObject *)py_class)->tp_name; + + srna_new = reg(CTX_data_main(C), + &reports, + py_class, + identifier, + bpy_class_validate, + bpy_class_call, + bpy_class_free); + + if (!BLI_listbase_is_empty(&reports.list)) { + const bool has_error = BPy_reports_to_error(&reports, PyExc_RuntimeError, false); + if (!has_error) { + BPy_reports_write_stdout(&reports, error_prefix); + } + BKE_reports_clear(&reports); + if (has_error) { + return NULL; + } + } + + /* python errors validating are not converted into reports so the check above will fail. + * the cause for returning NULL will be printed as an error */ + if (srna_new == NULL) { + return NULL; + } + + pyrna_subtype_set_rna(py_class, srna_new); /* takes a ref to py_class */ + + /* old srna still references us, keep the check in case registering somehow can free it */ + if (RNA_struct_py_type_get(srna)) { + RNA_struct_py_type_set(srna, NULL); + // Py_DECREF(py_class); // should be able to do this XXX since the old rna adds a new ref. + } + + /* Can't use this because it returns a dict proxy + * + * item = PyObject_GetAttrString(py_class, "__dict__"); + */ + if (pyrna_deferred_register_class(srna_new, (PyTypeObject *)py_class) != 0) { + return NULL; + } + + /* call classed register method () */ + switch (_PyObject_LookupAttr(py_class, bpy_intern_str_register, &py_cls_meth)) { + case 1: { + PyObject *ret = PyObject_CallObject(py_cls_meth, NULL); + if (ret) { + Py_DECREF(ret); + } + else { + return NULL; + } + break; + } + case -1: { + return NULL; + } + } + + Py_RETURN_NONE; +} + +static int pyrna_srna_contains_pointer_prop_srna(StructRNA *srna_props, + StructRNA *srna, + const char **r_prop_identifier) +{ + PropertyRNA *prop; + LinkData *link; + + /* verify properties */ + const ListBase *lb = RNA_struct_type_properties(srna); + + for (link = lb->first; link; link = link->next) { + prop = (PropertyRNA *)link; + if (RNA_property_type(prop) == PROP_POINTER && !RNA_property_builtin(prop)) { + PointerRNA tptr; + RNA_pointer_create(NULL, &RNA_Struct, srna_props, &tptr); + + if (RNA_property_pointer_type(&tptr, prop) == srna) { + *r_prop_identifier = RNA_property_identifier(prop); + return 1; + } + } + } + + return 0; } PyDoc_STRVAR(pyrna_unregister_class_doc, -".. method:: unregister_class(cls)\n" -"\n" -" Unload the python class from blender.\n" -"\n" -" If the class has an *unregister* class method it will be called\n" -" before unregistering.\n" -); + ".. method:: unregister_class(cls)\n" + "\n" + " Unload the python class from blender.\n" + "\n" + " If the class has an *unregister* class method it will be called\n" + " before unregistering.\n"); PyMethodDef meth_bpy_unregister_class = { - "unregister_class", pyrna_unregister_class, METH_O, pyrna_unregister_class_doc, + "unregister_class", + pyrna_unregister_class, + METH_O, + pyrna_unregister_class_doc, }; static PyObject *pyrna_unregister_class(PyObject *UNUSED(self), PyObject *py_class) { - bContext *C = NULL; - StructUnregisterFunc unreg; - StructRNA *srna; - PyObject *py_cls_meth; + bContext *C = NULL; + StructUnregisterFunc unreg; + StructRNA *srna; + PyObject *py_cls_meth; - if (!PyType_Check(py_class)) { - PyErr_Format(PyExc_ValueError, - "register_class(...): " - "expected a class argument, not '%.200s'", Py_TYPE(py_class)->tp_name); - return NULL; - } + if (!PyType_Check(py_class)) { + PyErr_Format(PyExc_ValueError, + "register_class(...): " + "expected a class argument, not '%.200s'", + Py_TYPE(py_class)->tp_name); + return NULL; + } #if 0 - if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna) == NULL) { - PWM_cursor_wait(0); - PyErr_SetString(PyExc_ValueError, "unregister_class(): not a registered as a subclass"); - return NULL; - } + if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna) == NULL) { + PWM_cursor_wait(0); + PyErr_SetString(PyExc_ValueError, "unregister_class(): not a registered as a subclass"); + return NULL; + } #endif - if (!pyrna_write_check()) { - PyErr_Format(PyExc_RuntimeError, - "unregister_class(...): " - "can't run in readonly state '%.200s'", - ((PyTypeObject *)py_class)->tp_name); - return NULL; - } - - srna = pyrna_struct_as_srna(py_class, false, "unregister_class(...):"); - if (srna == NULL) { - return NULL; - } - - /* check that we have a unregister callback for this type */ - unreg = RNA_struct_unregister(srna); - - if (!unreg) { - PyErr_SetString(PyExc_ValueError, - "unregister_class(...): " - "expected a Type subclassed from a registerable rna type (no unregister supported)"); - return NULL; - } - - /* call classed unregister method */ - switch (_PyObject_LookupAttr(py_class, bpy_intern_str_unregister, &py_cls_meth)) { - case 1: - { - PyObject *ret = PyObject_CallObject(py_cls_meth, NULL); - if (ret) { - Py_DECREF(ret); - } - else { - return NULL; - } - break; - } - case -1: - { - return NULL; - } - } - - /* should happen all the time but very slow */ - if (G.debug & G_DEBUG_PYTHON) { - /* remove all properties using this class */ - StructRNA *srna_iter; - PointerRNA ptr_rna; - PropertyRNA *prop_rna; - const char *prop_identifier = NULL; - - RNA_blender_rna_pointer_create(&ptr_rna); - prop_rna = RNA_struct_find_property(&ptr_rna, "structs"); - - - /* loop over all structs */ - RNA_PROP_BEGIN (&ptr_rna, itemptr, prop_rna) - { - srna_iter = itemptr.data; - if (pyrna_srna_contains_pointer_prop_srna(srna_iter, srna, &prop_identifier)) { - break; - } - } - RNA_PROP_END; - - if (prop_identifier) { - PyErr_Format(PyExc_RuntimeError, - "unregister_class(...): can't unregister %s because %s.%s pointer property is using this", - RNA_struct_identifier(srna), RNA_struct_identifier(srna_iter), prop_identifier); - return NULL; - } - } - - /* get the context, so register callback can do necessary refreshes */ - C = BPy_GetContext(); - - /* call unregister */ - unreg(CTX_data_main(C), srna); /* calls bpy_class_free, this decref's py_class */ - - PyDict_DelItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna); - if (PyErr_Occurred()) { - PyErr_Clear(); //return NULL; - } - - Py_RETURN_NONE; + if (!pyrna_write_check()) { + PyErr_Format(PyExc_RuntimeError, + "unregister_class(...): " + "can't run in readonly state '%.200s'", + ((PyTypeObject *)py_class)->tp_name); + return NULL; + } + + srna = pyrna_struct_as_srna(py_class, false, "unregister_class(...):"); + if (srna == NULL) { + return NULL; + } + + /* check that we have a unregister callback for this type */ + unreg = RNA_struct_unregister(srna); + + if (!unreg) { + PyErr_SetString( + PyExc_ValueError, + "unregister_class(...): " + "expected a Type subclassed from a registerable rna type (no unregister supported)"); + return NULL; + } + + /* call classed unregister method */ + switch (_PyObject_LookupAttr(py_class, bpy_intern_str_unregister, &py_cls_meth)) { + case 1: { + PyObject *ret = PyObject_CallObject(py_cls_meth, NULL); + if (ret) { + Py_DECREF(ret); + } + else { + return NULL; + } + break; + } + case -1: { + return NULL; + } + } + + /* should happen all the time but very slow */ + if (G.debug & G_DEBUG_PYTHON) { + /* remove all properties using this class */ + StructRNA *srna_iter; + PointerRNA ptr_rna; + PropertyRNA *prop_rna; + const char *prop_identifier = NULL; + + RNA_blender_rna_pointer_create(&ptr_rna); + prop_rna = RNA_struct_find_property(&ptr_rna, "structs"); + + /* loop over all structs */ + RNA_PROP_BEGIN (&ptr_rna, itemptr, prop_rna) { + srna_iter = itemptr.data; + if (pyrna_srna_contains_pointer_prop_srna(srna_iter, srna, &prop_identifier)) { + break; + } + } + RNA_PROP_END; + + if (prop_identifier) { + PyErr_Format(PyExc_RuntimeError, + "unregister_class(...): can't unregister %s because %s.%s pointer property is " + "using this", + RNA_struct_identifier(srna), + RNA_struct_identifier(srna_iter), + prop_identifier); + return NULL; + } + } + + /* get the context, so register callback can do necessary refreshes */ + C = BPy_GetContext(); + + /* call unregister */ + unreg(CTX_data_main(C), srna); /* calls bpy_class_free, this decref's py_class */ + + PyDict_DelItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna); + if (PyErr_Occurred()) { + PyErr_Clear(); //return NULL; + } + + Py_RETURN_NONE; } /* Access to 'owner_id' internal global. */ static PyObject *pyrna_bl_owner_id_get(PyObject *UNUSED(self)) { - const char *name = RNA_struct_state_owner_get(); - if (name) { - return PyUnicode_FromString(name); - } - Py_RETURN_NONE; + const char *name = RNA_struct_state_owner_get(); + if (name) { + return PyUnicode_FromString(name); + } + Py_RETURN_NONE; } static PyObject *pyrna_bl_owner_id_set(PyObject *UNUSED(self), PyObject *value) { - const char *name; - if (value == Py_None) { - name = NULL; - } - else if (PyUnicode_Check(value)) { - name = _PyUnicode_AsString(value); - } - else { - PyErr_Format(PyExc_ValueError, - "owner_set(...): " - "expected None or a string, not '%.200s'", Py_TYPE(value)->tp_name); - return NULL; - } - RNA_struct_state_owner_set(name); - Py_RETURN_NONE; + const char *name; + if (value == Py_None) { + name = NULL; + } + else if (PyUnicode_Check(value)) { + name = _PyUnicode_AsString(value); + } + else { + PyErr_Format(PyExc_ValueError, + "owner_set(...): " + "expected None or a string, not '%.200s'", + Py_TYPE(value)->tp_name); + return NULL; + } + RNA_struct_state_owner_set(name); + Py_RETURN_NONE; } PyMethodDef meth_bpy_owner_id_get = { - "_bl_owner_id_get", (PyCFunction)pyrna_bl_owner_id_get, METH_NOARGS, NULL, + "_bl_owner_id_get", + (PyCFunction)pyrna_bl_owner_id_get, + METH_NOARGS, + NULL, }; PyMethodDef meth_bpy_owner_id_set = { - "_bl_owner_id_set", (PyCFunction)pyrna_bl_owner_id_set, METH_O, NULL, + "_bl_owner_id_set", + (PyCFunction)pyrna_bl_owner_id_set, + METH_O, + NULL, }; /* currently this is fairly limited, we would need to make some way to split up * pyrna_callback_classmethod_... if we want more than one callback per type */ typedef struct BPyRNA_CallBack { - PyMethodDef py_method; - StructRNA *bpy_srna; + PyMethodDef py_method; + StructRNA *bpy_srna; } PyRNA_CallBack; -PyDoc_STRVAR(pyrna_draw_handler_add_doc, -".. method:: draw_handler_add(callback, args, region_type, draw_type)\n" -"\n" -" Add a new draw handler to this space type.\n" -" It will be called every time the specified region in the space type will be drawn.\n" -" Note: All arguments are positional only for now.\n" -"\n" -" :param callback:\n" -" A function that will be called when the region is drawn.\n" -" It gets the specified arguments as input.\n" -" :type callback: function\n" -" :param args: Arguments that will be passed to the callback.\n" -" :type args: tuple\n" -" :param region_type: The region type the callback draws in; usually `'WINDOW'`. (:class:`bpy.types.Region.type`)\n" -" :type region_type: str\n" -" :param draw_type: Usually `POST_PIXEL` for 2D drawing and `POST_VIEW` for 3D drawing. In some cases `PRE_VIEW` can be used.\n" -" :type draw_type: str\n" -" :return: Handler that can be removed later on.\n" -" :rtype: object" -); +PyDoc_STRVAR( + pyrna_draw_handler_add_doc, + ".. method:: draw_handler_add(callback, args, region_type, draw_type)\n" + "\n" + " Add a new draw handler to this space type.\n" + " It will be called every time the specified region in the space type will be drawn.\n" + " Note: All arguments are positional only for now.\n" + "\n" + " :param callback:\n" + " A function that will be called when the region is drawn.\n" + " It gets the specified arguments as input.\n" + " :type callback: function\n" + " :param args: Arguments that will be passed to the callback.\n" + " :type args: tuple\n" + " :param region_type: The region type the callback draws in; usually `'WINDOW'`. " + "(:class:`bpy.types.Region.type`)\n" + " :type region_type: str\n" + " :param draw_type: Usually `POST_PIXEL` for 2D drawing and `POST_VIEW` for 3D drawing. In " + "some cases `PRE_VIEW` can be used.\n" + " :type draw_type: str\n" + " :return: Handler that can be removed later on.\n" + " :rtype: object"); PyDoc_STRVAR(pyrna_draw_handler_remove_doc, -".. method:: draw_handler_remove(handler, region_type)\n" -"\n" -" Remove a draw handler that was added previously.\n" -"\n" -" :param handler: The draw handler that should be removed.\n" -" :type handler: object\n" -" :param region_type: Region type the callback was added to.\n" -" :type region_type: str\n" -); + ".. method:: draw_handler_remove(handler, region_type)\n" + "\n" + " Remove a draw handler that was added previously.\n" + "\n" + " :param handler: The draw handler that should be removed.\n" + " :type handler: object\n" + " :param region_type: Region type the callback was added to.\n" + " :type region_type: str\n"); static struct BPyRNA_CallBack pyrna_cb_methods[] = { - {{"draw_handler_add", (PyCFunction)pyrna_callback_classmethod_add, - METH_VARARGS | METH_STATIC, pyrna_draw_handler_add_doc}, &RNA_Space}, - {{"draw_handler_remove", (PyCFunction)pyrna_callback_classmethod_remove, - METH_VARARGS | METH_STATIC, pyrna_draw_handler_remove_doc}, &RNA_Space}, - - {{"draw_cursor_add", (PyCFunction)pyrna_callback_classmethod_add, METH_VARARGS | METH_STATIC, ""}, &RNA_WindowManager}, - {{"draw_cursor_remove", (PyCFunction)pyrna_callback_classmethod_remove, METH_VARARGS | METH_STATIC, ""}, &RNA_WindowManager}, - {{NULL, NULL, 0, NULL}, NULL}, + {{"draw_handler_add", + (PyCFunction)pyrna_callback_classmethod_add, + METH_VARARGS | METH_STATIC, + pyrna_draw_handler_add_doc}, + &RNA_Space}, + {{"draw_handler_remove", + (PyCFunction)pyrna_callback_classmethod_remove, + METH_VARARGS | METH_STATIC, + pyrna_draw_handler_remove_doc}, + &RNA_Space}, + + {{"draw_cursor_add", + (PyCFunction)pyrna_callback_classmethod_add, + METH_VARARGS | METH_STATIC, + ""}, + &RNA_WindowManager}, + {{"draw_cursor_remove", + (PyCFunction)pyrna_callback_classmethod_remove, + METH_VARARGS | METH_STATIC, + ""}, + &RNA_WindowManager}, + {{NULL, NULL, 0, NULL}, NULL}, }; void BPY_rna_register_cb(void) { - int i; + int i; - for (i = 0; pyrna_cb_methods[i].bpy_srna; i++) { - PyObject *cls; - PyObject *func; - PyObject *classmethod; - PyObject *args = PyTuple_New(1); + for (i = 0; pyrna_cb_methods[i].bpy_srna; i++) { + PyObject *cls; + PyObject *func; + PyObject *classmethod; + PyObject *args = PyTuple_New(1); - cls = pyrna_srna_Subtype(pyrna_cb_methods[i].bpy_srna); - func = PyCFunction_New(&pyrna_cb_methods[i].py_method, NULL); - PyTuple_SET_ITEM(args, 0, func); - classmethod = PyObject_CallObject((PyObject *)&PyClassMethod_Type, args); + cls = pyrna_srna_Subtype(pyrna_cb_methods[i].bpy_srna); + func = PyCFunction_New(&pyrna_cb_methods[i].py_method, NULL); + PyTuple_SET_ITEM(args, 0, func); + classmethod = PyObject_CallObject((PyObject *)&PyClassMethod_Type, args); - PyObject_SetAttrString(cls, pyrna_cb_methods[i].py_method.ml_name, classmethod); + PyObject_SetAttrString(cls, pyrna_cb_methods[i].py_method.ml_name, classmethod); - Py_DECREF(classmethod); - Py_DECREF(args); /* clears 'func' too */ - Py_DECREF(cls); - } + Py_DECREF(classmethod); + Py_DECREF(args); /* clears 'func' too */ + Py_DECREF(cls); + } } |