|
|
|
|
@@ -42,6 +42,18 @@ extern bool pyrna_id_FromPyObject(PyObject *obj, ID **id);
|
|
|
|
|
extern PyObject *pyrna_id_CreatePyObject(ID *id);
|
|
|
|
|
extern bool pyrna_id_CheckPyObject(PyObject *obj);
|
|
|
|
|
|
|
|
|
|
/* Currently there is no need to expose this publicly. */
|
|
|
|
|
static PyObject *BPy_IDGroup_IterKeys_CreatePyObject(BPy_IDProperty *group, const bool reversed);
|
|
|
|
|
static PyObject *BPy_IDGroup_IterValues_CreatePyObject(BPy_IDProperty *group, const bool reversed);
|
|
|
|
|
static PyObject *BPy_IDGroup_IterItems_CreatePyObject(BPy_IDProperty *group, const bool reversed);
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_ViewKeys_CreatePyObject(BPy_IDProperty *group);
|
|
|
|
|
static PyObject *BPy_IDGroup_ViewValues_CreatePyObject(BPy_IDProperty *group);
|
|
|
|
|
static PyObject *BPy_IDGroup_ViewItems_CreatePyObject(BPy_IDProperty *group);
|
|
|
|
|
|
|
|
|
|
static BPy_IDGroup_View *IDGroup_View_New_WithType(BPy_IDProperty *group, PyTypeObject *type);
|
|
|
|
|
static int BPy_IDGroup_Contains(BPy_IDProperty *self, PyObject *value);
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Python from ID-Property (Internal Conversions)
|
|
|
|
|
*
|
|
|
|
|
@@ -756,13 +768,7 @@ static int BPy_IDGroup_Map_SetItem(BPy_IDProperty *self, PyObject *key, PyObject
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_iter(BPy_IDProperty *self)
|
|
|
|
|
{
|
|
|
|
|
BPy_IDGroup_Iter *iter = PyObject_GC_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type);
|
|
|
|
|
iter->group = self;
|
|
|
|
|
Py_INCREF(self);
|
|
|
|
|
iter->mode = IDPROP_ITER_KEYS;
|
|
|
|
|
iter->cur = self->prop->data.group.first;
|
|
|
|
|
PyObject_GC_Track(iter);
|
|
|
|
|
return (PyObject *)iter;
|
|
|
|
|
return BPy_IDGroup_ViewKeys_CreatePyObject(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* for simple, non nested types this is the same as BPy_IDGroup_WrapData */
|
|
|
|
|
@@ -874,6 +880,370 @@ PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name ID-Property Group Iterator Type
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_Iter_repr(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->group == NULL) {
|
|
|
|
|
return PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
|
|
|
|
|
}
|
|
|
|
|
return PyUnicode_FromFormat("<%s \"%s\">", Py_TYPE(self)->tp_name, self->group->prop->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void BPy_IDGroup_Iter_dealloc(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->group != NULL) {
|
|
|
|
|
PyObject_GC_UnTrack(self);
|
|
|
|
|
}
|
|
|
|
|
Py_CLEAR(self->group);
|
|
|
|
|
PyObject_GC_Del(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int BPy_IDGroup_Iter_traverse(BPy_IDGroup_Iter *self, visitproc visit, void *arg)
|
|
|
|
|
{
|
|
|
|
|
Py_VISIT(self->group);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int BPy_IDGroup_Iter_clear(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
Py_CLEAR(self->group);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool BPy_Group_Iter_same_size_or_raise_error(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->len_init == self->group->prop->len) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
PyErr_SetString(PyExc_RuntimeError, "IDPropertyGroup changed size during iteration");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_Group_IterKeys_next(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->cur != NULL) {
|
|
|
|
|
/* When `cur` is set, `group` cannot be NULL. */
|
|
|
|
|
if (!BPy_Group_Iter_same_size_or_raise_error(self)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
IDProperty *cur = self->cur;
|
|
|
|
|
self->cur = self->reversed ? self->cur->prev : self->cur->next;
|
|
|
|
|
return PyUnicode_FromString(cur->name);
|
|
|
|
|
}
|
|
|
|
|
PyErr_SetNone(PyExc_StopIteration);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_Group_IterValues_next(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->cur != NULL) {
|
|
|
|
|
/* When `cur` is set, `group` cannot be NULL. */
|
|
|
|
|
if (!BPy_Group_Iter_same_size_or_raise_error(self)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
IDProperty *cur = self->cur;
|
|
|
|
|
self->cur = self->reversed ? self->cur->prev : self->cur->next;
|
|
|
|
|
return BPy_IDGroup_WrapData(self->group->id, cur, self->group->prop);
|
|
|
|
|
}
|
|
|
|
|
PyErr_SetNone(PyExc_StopIteration);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_Group_IterItems_next(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->cur != NULL) {
|
|
|
|
|
/* When `cur` is set, `group` cannot be NULL. */
|
|
|
|
|
if (!BPy_Group_Iter_same_size_or_raise_error(self)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
IDProperty *cur = self->cur;
|
|
|
|
|
self->cur = self->reversed ? self->cur->prev : self->cur->next;
|
|
|
|
|
PyObject *ret = PyTuple_New(2);
|
|
|
|
|
PyTuple_SET_ITEMS(ret,
|
|
|
|
|
PyUnicode_FromString(cur->name),
|
|
|
|
|
BPy_IDGroup_WrapData(self->group->id, cur, self->group->prop));
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
PyErr_SetNone(PyExc_StopIteration);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyTypeObject BPy_IDGroup_IterKeys_Type = {PyVarObject_HEAD_INIT(NULL, 0)};
|
|
|
|
|
PyTypeObject BPy_IDGroup_IterValues_Type = {PyVarObject_HEAD_INIT(NULL, 0)};
|
|
|
|
|
PyTypeObject BPy_IDGroup_IterItems_Type = {PyVarObject_HEAD_INIT(NULL, 0)};
|
|
|
|
|
|
|
|
|
|
/* ID Property Group Iterator. */
|
|
|
|
|
static void IDGroup_Iter_init_type(void)
|
|
|
|
|
{
|
|
|
|
|
#define SHARED_MEMBER_SET(member, value) \
|
|
|
|
|
{ \
|
|
|
|
|
k_ty->member = v_ty->member = i_ty->member = value; \
|
|
|
|
|
} \
|
|
|
|
|
((void)0)
|
|
|
|
|
|
|
|
|
|
PyTypeObject *k_ty = &BPy_IDGroup_IterKeys_Type;
|
|
|
|
|
PyTypeObject *v_ty = &BPy_IDGroup_IterValues_Type;
|
|
|
|
|
PyTypeObject *i_ty = &BPy_IDGroup_IterItems_Type;
|
|
|
|
|
|
|
|
|
|
/* Unique members. */
|
|
|
|
|
k_ty->tp_name = "IDPropertyGroupIterKeys";
|
|
|
|
|
v_ty->tp_name = "IDPropertyGroupIterValues";
|
|
|
|
|
i_ty->tp_name = "IDPropertyGroupIterItems";
|
|
|
|
|
|
|
|
|
|
k_ty->tp_iternext = (iternextfunc)BPy_Group_IterKeys_next;
|
|
|
|
|
v_ty->tp_iternext = (iternextfunc)BPy_Group_IterValues_next;
|
|
|
|
|
i_ty->tp_iternext = (iternextfunc)BPy_Group_IterItems_next;
|
|
|
|
|
|
|
|
|
|
/* Shared members. */
|
|
|
|
|
SHARED_MEMBER_SET(tp_basicsize, sizeof(BPy_IDGroup_Iter));
|
|
|
|
|
SHARED_MEMBER_SET(tp_dealloc, (destructor)BPy_IDGroup_Iter_dealloc);
|
|
|
|
|
SHARED_MEMBER_SET(tp_repr, (reprfunc)BPy_IDGroup_Iter_repr);
|
|
|
|
|
SHARED_MEMBER_SET(tp_flags, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC);
|
|
|
|
|
SHARED_MEMBER_SET(tp_traverse, (traverseproc)BPy_IDGroup_Iter_traverse);
|
|
|
|
|
SHARED_MEMBER_SET(tp_clear, (inquiry)BPy_IDGroup_Iter_clear);
|
|
|
|
|
SHARED_MEMBER_SET(tp_iter, PyObject_SelfIter);
|
|
|
|
|
|
|
|
|
|
#undef SHARED_MEMBER_SET
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *IDGroup_Iter_New_WithType(BPy_IDProperty *group,
|
|
|
|
|
const bool reversed,
|
|
|
|
|
PyTypeObject *type)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(group ? group->prop->type == IDP_GROUP : true);
|
|
|
|
|
BPy_IDGroup_Iter *iter = PyObject_GC_New(BPy_IDGroup_Iter, type);
|
|
|
|
|
iter->reversed = reversed;
|
|
|
|
|
iter->group = group;
|
|
|
|
|
if (group != NULL) {
|
|
|
|
|
Py_INCREF(group);
|
|
|
|
|
PyObject_GC_Track(iter);
|
|
|
|
|
iter->cur = (reversed ? group->prop->data.group.last : group->prop->data.group.first);
|
|
|
|
|
iter->len_init = group->prop->len;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
iter->cur = NULL;
|
|
|
|
|
iter->len_init = 0;
|
|
|
|
|
}
|
|
|
|
|
return (PyObject *)iter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_IterKeys_CreatePyObject(BPy_IDProperty *group, const bool reversed)
|
|
|
|
|
{
|
|
|
|
|
return IDGroup_Iter_New_WithType(group, reversed, &BPy_IDGroup_IterKeys_Type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_IterValues_CreatePyObject(BPy_IDProperty *group, const bool reversed)
|
|
|
|
|
{
|
|
|
|
|
return IDGroup_Iter_New_WithType(group, reversed, &BPy_IDGroup_IterValues_Type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_IterItems_CreatePyObject(BPy_IDProperty *group, const bool reversed)
|
|
|
|
|
{
|
|
|
|
|
return IDGroup_Iter_New_WithType(group, reversed, &BPy_IDGroup_IterItems_Type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name ID-Property Group View Types (Keys/Values/Items)
|
|
|
|
|
*
|
|
|
|
|
* This view types is a thin wrapper on keys/values/items, this matches Python's `dict_view` type.
|
|
|
|
|
* The is returned by `property.keys()` and is separate from the iterator that loops over keys.
|
|
|
|
|
*
|
|
|
|
|
* There are some less common features this type could support (matching Python's `dict_view`)
|
|
|
|
|
*
|
|
|
|
|
* TODO:
|
|
|
|
|
* - Efficient contains checks for values and items which currently convert to a list first.
|
|
|
|
|
* - Missing `dict_views.isdisjoint`.
|
|
|
|
|
* - Missing `tp_as_number` (`nb_subtract`, `nb_and`, `nb_xor`, `nb_or`).
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_View_repr(BPy_IDGroup_View *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->group == NULL) {
|
|
|
|
|
return PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name);
|
|
|
|
|
}
|
|
|
|
|
return PyUnicode_FromFormat("<%s \"%s\">", Py_TYPE(self)->tp_name, self->group->prop->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void BPy_IDGroup_View_dealloc(BPy_IDGroup_View *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->group != NULL) {
|
|
|
|
|
PyObject_GC_UnTrack(self);
|
|
|
|
|
}
|
|
|
|
|
Py_CLEAR(self->group);
|
|
|
|
|
PyObject_GC_Del(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int BPy_IDGroup_View_traverse(BPy_IDGroup_View *self, visitproc visit, void *arg)
|
|
|
|
|
{
|
|
|
|
|
Py_VISIT(self->group);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int BPy_IDGroup_View_clear(BPy_IDGroup_View *self)
|
|
|
|
|
{
|
|
|
|
|
Py_CLEAR(self->group);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* View Specific API's (Key/Value/Items). */
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_Group_ViewKeys_iter(BPy_IDGroup_View *self)
|
|
|
|
|
{
|
|
|
|
|
return BPy_IDGroup_IterKeys_CreatePyObject(self->group, self->reversed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_Group_ViewValues_iter(BPy_IDGroup_View *self)
|
|
|
|
|
{
|
|
|
|
|
return BPy_IDGroup_IterValues_CreatePyObject(self->group, self->reversed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_Group_ViewItems_iter(BPy_IDGroup_View *self)
|
|
|
|
|
{
|
|
|
|
|
return BPy_IDGroup_IterItems_CreatePyObject(self->group, self->reversed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Py_ssize_t BPy_Group_View_len(BPy_IDGroup_View *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->group == NULL) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return self->group->prop->len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int BPy_Group_ViewKeys_Contains(BPy_IDGroup_View *self, PyObject *value)
|
|
|
|
|
{
|
|
|
|
|
if (self->group == NULL) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return BPy_IDGroup_Contains(self->group, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int BPy_Group_ViewValues_Contains(BPy_IDGroup_View *self, PyObject *value)
|
|
|
|
|
{
|
|
|
|
|
if (self->group == NULL) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* TODO: implement this without first converting to a list. */
|
|
|
|
|
PyObject *list = PySequence_List((PyObject *)self);
|
|
|
|
|
const int result = PySequence_Contains(list, value);
|
|
|
|
|
Py_DECREF(list);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int BPy_Group_ViewItems_Contains(BPy_IDGroup_View *self, PyObject *value)
|
|
|
|
|
{
|
|
|
|
|
if (self->group == NULL) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* TODO: implement this without first converting to a list. */
|
|
|
|
|
PyObject *list = PySequence_List((PyObject *)self);
|
|
|
|
|
const int result = PySequence_Contains(list, value);
|
|
|
|
|
Py_DECREF(list);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PySequenceMethods BPy_IDGroup_ViewKeys_as_sequence = {
|
|
|
|
|
(lenfunc)BPy_Group_View_len, /* sq_length */
|
|
|
|
|
0, /* sq_concat */
|
|
|
|
|
0, /* sq_repeat */
|
|
|
|
|
0, /* sq_item */
|
|
|
|
|
0, /* sq_slice */
|
|
|
|
|
0, /* sq_ass_item */
|
|
|
|
|
0, /* sq_ass_slice */
|
|
|
|
|
(objobjproc)BPy_Group_ViewKeys_Contains, /* sq_contains */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static PySequenceMethods BPy_IDGroup_ViewValues_as_sequence = {
|
|
|
|
|
(lenfunc)BPy_Group_View_len, /* sq_length */
|
|
|
|
|
0, /* sq_concat */
|
|
|
|
|
0, /* sq_repeat */
|
|
|
|
|
0, /* sq_item */
|
|
|
|
|
0, /* sq_slice */
|
|
|
|
|
0, /* sq_ass_item */
|
|
|
|
|
0, /* sq_ass_slice */
|
|
|
|
|
(objobjproc)BPy_Group_ViewValues_Contains, /* sq_contains */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static PySequenceMethods BPy_IDGroup_ViewItems_as_sequence = {
|
|
|
|
|
(lenfunc)BPy_Group_View_len, /* sq_length */
|
|
|
|
|
0, /* sq_concat */
|
|
|
|
|
0, /* sq_repeat */
|
|
|
|
|
0, /* sq_item */
|
|
|
|
|
0, /* sq_slice */
|
|
|
|
|
0, /* sq_ass_item */
|
|
|
|
|
0, /* sq_ass_slice */
|
|
|
|
|
(objobjproc)BPy_Group_ViewItems_Contains, /* sq_contains */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Methods. */
|
|
|
|
|
|
|
|
|
|
PyDoc_STRVAR(BPy_IDGroup_View_reversed_doc,
|
|
|
|
|
"Return a reverse iterator over the ID Property keys values or items.");
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_View_reversed(BPy_IDGroup_View *self, PyObject *UNUSED(ignored))
|
|
|
|
|
{
|
|
|
|
|
BPy_IDGroup_View *result = IDGroup_View_New_WithType(self->group, Py_TYPE(self));
|
|
|
|
|
result->reversed = !self->reversed;
|
|
|
|
|
return (PyObject *)result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyMethodDef BPy_IDGroup_View_methods[] = {
|
|
|
|
|
{"__reversed__",
|
|
|
|
|
(PyCFunction)(void (*)(void))BPy_IDGroup_View_reversed,
|
|
|
|
|
METH_NOARGS,
|
|
|
|
|
BPy_IDGroup_View_reversed_doc},
|
|
|
|
|
{NULL, NULL},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
PyTypeObject BPy_IDGroup_ViewKeys_Type = {PyVarObject_HEAD_INIT(NULL, 0)};
|
|
|
|
|
PyTypeObject BPy_IDGroup_ViewValues_Type = {PyVarObject_HEAD_INIT(NULL, 0)};
|
|
|
|
|
PyTypeObject BPy_IDGroup_ViewItems_Type = {PyVarObject_HEAD_INIT(NULL, 0)};
|
|
|
|
|
|
|
|
|
|
/* ID Property Group View. */
|
|
|
|
|
static void IDGroup_View_init_type(void)
|
|
|
|
|
{
|
|
|
|
|
PyTypeObject *k_ty = &BPy_IDGroup_ViewKeys_Type;
|
|
|
|
|
PyTypeObject *v_ty = &BPy_IDGroup_ViewValues_Type;
|
|
|
|
|
PyTypeObject *i_ty = &BPy_IDGroup_ViewItems_Type;
|
|
|
|
|
|
|
|
|
|
/* Unique members. */
|
|
|
|
|
k_ty->tp_name = "IDPropertyGroupViewKeys";
|
|
|
|
|
v_ty->tp_name = "IDPropertyGroupViewValues";
|
|
|
|
|
i_ty->tp_name = "IDPropertyGroupViewItems";
|
|
|
|
|
|
|
|
|
|
k_ty->tp_iter = (getiterfunc)BPy_Group_ViewKeys_iter;
|
|
|
|
|
v_ty->tp_iter = (getiterfunc)BPy_Group_ViewValues_iter;
|
|
|
|
|
i_ty->tp_iter = (getiterfunc)BPy_Group_ViewItems_iter;
|
|
|
|
|
|
|
|
|
|
k_ty->tp_as_sequence = &BPy_IDGroup_ViewKeys_as_sequence;
|
|
|
|
|
v_ty->tp_as_sequence = &BPy_IDGroup_ViewValues_as_sequence;
|
|
|
|
|
i_ty->tp_as_sequence = &BPy_IDGroup_ViewItems_as_sequence;
|
|
|
|
|
|
|
|
|
|
/* Shared members. */
|
|
|
|
|
#define SHARED_MEMBER_SET(member, value) \
|
|
|
|
|
{ \
|
|
|
|
|
k_ty->member = v_ty->member = i_ty->member = value; \
|
|
|
|
|
} \
|
|
|
|
|
((void)0)
|
|
|
|
|
|
|
|
|
|
SHARED_MEMBER_SET(tp_basicsize, sizeof(BPy_IDGroup_View));
|
|
|
|
|
SHARED_MEMBER_SET(tp_dealloc, (destructor)BPy_IDGroup_View_dealloc);
|
|
|
|
|
SHARED_MEMBER_SET(tp_repr, (reprfunc)BPy_IDGroup_View_repr);
|
|
|
|
|
SHARED_MEMBER_SET(tp_flags, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC);
|
|
|
|
|
SHARED_MEMBER_SET(tp_traverse, (traverseproc)BPy_IDGroup_View_traverse);
|
|
|
|
|
SHARED_MEMBER_SET(tp_clear, (inquiry)BPy_IDGroup_View_clear);
|
|
|
|
|
SHARED_MEMBER_SET(tp_methods, BPy_IDGroup_View_methods);
|
|
|
|
|
|
|
|
|
|
#undef SHARED_MEMBER_SET
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name ID-Property Group Methods
|
|
|
|
|
* \{ */
|
|
|
|
|
@@ -923,22 +1293,6 @@ static PyObject *BPy_IDGroup_pop(BPy_IDProperty *self, PyObject *args)
|
|
|
|
|
return pyform;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyDoc_STRVAR(
|
|
|
|
|
BPy_IDGroup_iter_items_doc,
|
|
|
|
|
".. method:: iteritems()\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" Iterate through the items in the dict; behaves like dictionary method iteritems.\n");
|
|
|
|
|
static PyObject *BPy_IDGroup_iter_items(BPy_IDProperty *self)
|
|
|
|
|
{
|
|
|
|
|
BPy_IDGroup_Iter *iter = PyObject_GC_New(BPy_IDGroup_Iter, &BPy_IDGroup_Iter_Type);
|
|
|
|
|
iter->group = self;
|
|
|
|
|
Py_INCREF(self);
|
|
|
|
|
iter->mode = IDPROP_ITER_ITEMS;
|
|
|
|
|
iter->cur = self->prop->data.group.first;
|
|
|
|
|
PyObject_GC_Track(iter);
|
|
|
|
|
return (PyObject *)iter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* utility function */
|
|
|
|
|
static void BPy_IDGroup_CorrectListLen(IDProperty *prop, PyObject *seq, int len, const char *func)
|
|
|
|
|
{
|
|
|
|
|
@@ -1023,13 +1377,37 @@ PyObject *BPy_Wrap_GetItems(ID *id, IDProperty *prop)
|
|
|
|
|
return seq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyObject *BPy_Wrap_GetKeys_View_WithID(ID *id, IDProperty *prop)
|
|
|
|
|
{
|
|
|
|
|
PyObject *self = prop ? idprop_py_from_idp_group(id, prop, NULL) : NULL;
|
|
|
|
|
PyObject *ret = BPy_IDGroup_ViewKeys_CreatePyObject((BPy_IDProperty *)self);
|
|
|
|
|
Py_XDECREF(self); /* Owned by `ret`. */
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyObject *BPy_Wrap_GetValues_View_WithID(ID *id, IDProperty *prop)
|
|
|
|
|
{
|
|
|
|
|
PyObject *self = prop ? idprop_py_from_idp_group(id, prop, NULL) : NULL;
|
|
|
|
|
PyObject *ret = BPy_IDGroup_ViewValues_CreatePyObject((BPy_IDProperty *)self);
|
|
|
|
|
Py_XDECREF(self); /* Owned by `ret`. */
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyObject *BPy_Wrap_GetItems_View_WithID(ID *id, IDProperty *prop)
|
|
|
|
|
{
|
|
|
|
|
PyObject *self = prop ? idprop_py_from_idp_group(id, prop, NULL) : NULL;
|
|
|
|
|
PyObject *ret = BPy_IDGroup_ViewItems_CreatePyObject((BPy_IDProperty *)self);
|
|
|
|
|
Py_XDECREF(self); /* Owned by `ret`. */
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyDoc_STRVAR(BPy_IDGroup_keys_doc,
|
|
|
|
|
".. method:: keys()\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" Return the keys associated with this group as a list of strings.\n");
|
|
|
|
|
static PyObject *BPy_IDGroup_keys(BPy_IDProperty *self)
|
|
|
|
|
{
|
|
|
|
|
return BPy_Wrap_GetKeys(self->prop);
|
|
|
|
|
return BPy_IDGroup_ViewKeys_CreatePyObject(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyDoc_STRVAR(BPy_IDGroup_values_doc,
|
|
|
|
|
@@ -1038,16 +1416,16 @@ PyDoc_STRVAR(BPy_IDGroup_values_doc,
|
|
|
|
|
" Return the values associated with this group.\n");
|
|
|
|
|
static PyObject *BPy_IDGroup_values(BPy_IDProperty *self)
|
|
|
|
|
{
|
|
|
|
|
return BPy_Wrap_GetValues(self->id, self->prop);
|
|
|
|
|
return BPy_IDGroup_ViewValues_CreatePyObject(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyDoc_STRVAR(BPy_IDGroup_items_doc,
|
|
|
|
|
".. method:: items()\n"
|
|
|
|
|
"\n"
|
|
|
|
|
" Return the items associated with this group.\n");
|
|
|
|
|
" Iterate through the items in the dict; behaves like dictionary method items.\n");
|
|
|
|
|
static PyObject *BPy_IDGroup_items(BPy_IDProperty *self)
|
|
|
|
|
{
|
|
|
|
|
return BPy_Wrap_GetItems(self->id, self->prop);
|
|
|
|
|
return BPy_IDGroup_ViewItems_CreatePyObject(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int BPy_IDGroup_Contains(BPy_IDProperty *self, PyObject *value)
|
|
|
|
|
@@ -1148,7 +1526,6 @@ static PyObject *BPy_IDGroup_get(BPy_IDProperty *self, PyObject *args)
|
|
|
|
|
|
|
|
|
|
static struct PyMethodDef BPy_IDGroup_methods[] = {
|
|
|
|
|
{"pop", (PyCFunction)BPy_IDGroup_pop, METH_VARARGS, BPy_IDGroup_pop_doc},
|
|
|
|
|
{"iteritems", (PyCFunction)BPy_IDGroup_iter_items, METH_NOARGS, BPy_IDGroup_iter_items_doc},
|
|
|
|
|
{"keys", (PyCFunction)BPy_IDGroup_keys, METH_NOARGS, BPy_IDGroup_keys_doc},
|
|
|
|
|
{"values", (PyCFunction)BPy_IDGroup_values, METH_NOARGS, BPy_IDGroup_values_doc},
|
|
|
|
|
{"items", (PyCFunction)BPy_IDGroup_items, METH_NOARGS, BPy_IDGroup_items_doc},
|
|
|
|
|
@@ -1678,120 +2055,59 @@ PyTypeObject BPy_IDArray_Type = {
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name ID-Property Group Iterator Type
|
|
|
|
|
/** \name Initialize Types
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
static PyObject *IDGroup_Iter_repr(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
return PyUnicode_FromFormat("(ID Property Group Iter \"%s\")", self->group->prop->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void BPy_IDGroup_Iter_dealloc(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
PyObject_GC_UnTrack(self);
|
|
|
|
|
Py_CLEAR(self->group);
|
|
|
|
|
PyObject_GC_Del(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int BPy_IDGroup_Iter_traverse(BPy_IDGroup_Iter *self, visitproc visit, void *arg)
|
|
|
|
|
{
|
|
|
|
|
Py_VISIT(self->group);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int BPy_IDGroup_Iter_clear(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
Py_CLEAR(self->group);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_Group_Iter_Next(BPy_IDGroup_Iter *self)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (self->cur) {
|
|
|
|
|
PyObject *ret;
|
|
|
|
|
IDProperty *cur;
|
|
|
|
|
|
|
|
|
|
cur = self->cur;
|
|
|
|
|
self->cur = self->cur->next;
|
|
|
|
|
|
|
|
|
|
if (self->mode == IDPROP_ITER_ITEMS) {
|
|
|
|
|
ret = PyTuple_New(2);
|
|
|
|
|
PyTuple_SET_ITEMS(ret,
|
|
|
|
|
PyUnicode_FromString(cur->name),
|
|
|
|
|
BPy_IDGroup_WrapData(self->group->id, cur, self->group->prop));
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return PyUnicode_FromString(cur->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyErr_SetNone(PyExc_StopIteration);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyTypeObject BPy_IDGroup_Iter_Type = {
|
|
|
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
|
|
|
/* For printing, in format "<module>.<name>" */
|
|
|
|
|
"IDPropertyGroupIter", /* char *tp_name; */
|
|
|
|
|
sizeof(BPy_IDGroup_Iter), /* int tp_basicsize; */
|
|
|
|
|
0, /* tp_itemsize; For allocation */
|
|
|
|
|
|
|
|
|
|
/* Methods to implement standard operations */
|
|
|
|
|
|
|
|
|
|
(destructor)BPy_IDGroup_Iter_dealloc, /* tp_dealloc */
|
|
|
|
|
0, /* tp_vectorcall_offset */
|
|
|
|
|
NULL, /* getattrfunc tp_getattr; */
|
|
|
|
|
NULL, /* setattrfunc tp_setattr; */
|
|
|
|
|
NULL, /* cmpfunc tp_compare; */
|
|
|
|
|
(reprfunc)IDGroup_Iter_repr, /* reprfunc 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 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_HAVE_GC, /* long tp_flags; */
|
|
|
|
|
|
|
|
|
|
NULL, /* char *tp_doc; Documentation string */
|
|
|
|
|
/*** Assigned meaning in release 2.0 ***/
|
|
|
|
|
/* call function for all accessible objects */
|
|
|
|
|
(traverseproc)BPy_IDGroup_Iter_traverse, /* traverseproc tp_traverse; */
|
|
|
|
|
|
|
|
|
|
/* delete references to contained objects */
|
|
|
|
|
(inquiry)BPy_IDGroup_Iter_clear, /* 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 */
|
|
|
|
|
PyObject_SelfIter, /* getiterfunc tp_iter; */
|
|
|
|
|
(iternextfunc)BPy_Group_Iter_Next, /* iternextfunc tp_iternext; */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void IDProp_Init_Types(void)
|
|
|
|
|
{
|
|
|
|
|
IDGroup_Iter_init_type();
|
|
|
|
|
IDGroup_View_init_type();
|
|
|
|
|
|
|
|
|
|
PyType_Ready(&BPy_IDGroup_Type);
|
|
|
|
|
PyType_Ready(&BPy_IDGroup_Iter_Type);
|
|
|
|
|
PyType_Ready(&BPy_IDArray_Type);
|
|
|
|
|
|
|
|
|
|
PyType_Ready(&BPy_IDGroup_IterKeys_Type);
|
|
|
|
|
PyType_Ready(&BPy_IDGroup_IterValues_Type);
|
|
|
|
|
PyType_Ready(&BPy_IDGroup_IterItems_Type);
|
|
|
|
|
|
|
|
|
|
PyType_Ready(&BPy_IDGroup_ViewKeys_Type);
|
|
|
|
|
PyType_Ready(&BPy_IDGroup_ViewValues_Type);
|
|
|
|
|
PyType_Ready(&BPy_IDGroup_ViewItems_Type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \note `group` may be NULL, unlike most other uses of this argument.
|
|
|
|
|
* This is supported so RNA keys/values/items methods returns an iterator with the expected type:
|
|
|
|
|
* - Without having ID-properties.
|
|
|
|
|
* - Without supporting #BPy_IDProperty.prop being NULL, which would incur many more checks.
|
|
|
|
|
* Python's own dictionary-views also works this way too.
|
|
|
|
|
*/
|
|
|
|
|
static BPy_IDGroup_View *IDGroup_View_New_WithType(BPy_IDProperty *group, PyTypeObject *type)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(group ? group->prop->type == IDP_GROUP : true);
|
|
|
|
|
BPy_IDGroup_View *iter = PyObject_GC_New(BPy_IDGroup_View, type);
|
|
|
|
|
iter->reversed = false;
|
|
|
|
|
iter->group = group;
|
|
|
|
|
if (group != NULL) {
|
|
|
|
|
Py_INCREF(group);
|
|
|
|
|
PyObject_GC_Track(iter);
|
|
|
|
|
}
|
|
|
|
|
return iter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_ViewKeys_CreatePyObject(BPy_IDProperty *group)
|
|
|
|
|
{
|
|
|
|
|
return (PyObject *)IDGroup_View_New_WithType(group, &BPy_IDGroup_ViewKeys_Type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_ViewValues_CreatePyObject(BPy_IDProperty *group)
|
|
|
|
|
{
|
|
|
|
|
return (PyObject *)IDGroup_View_New_WithType(group, &BPy_IDGroup_ViewValues_Type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PyObject *BPy_IDGroup_ViewItems_CreatePyObject(BPy_IDProperty *group)
|
|
|
|
|
{
|
|
|
|
|
return (PyObject *)IDGroup_View_New_WithType(group, &BPy_IDGroup_ViewItems_Type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
@@ -1822,7 +2138,15 @@ static PyObject *BPyInit_idprop_types(void)
|
|
|
|
|
|
|
|
|
|
/* bmesh_py_types.c */
|
|
|
|
|
PyModule_AddType(submodule, &BPy_IDGroup_Type);
|
|
|
|
|
PyModule_AddType(submodule, &BPy_IDGroup_Iter_Type);
|
|
|
|
|
|
|
|
|
|
PyModule_AddType(submodule, &BPy_IDGroup_ViewKeys_Type);
|
|
|
|
|
PyModule_AddType(submodule, &BPy_IDGroup_ViewValues_Type);
|
|
|
|
|
PyModule_AddType(submodule, &BPy_IDGroup_ViewItems_Type);
|
|
|
|
|
|
|
|
|
|
PyModule_AddType(submodule, &BPy_IDGroup_IterKeys_Type);
|
|
|
|
|
PyModule_AddType(submodule, &BPy_IDGroup_IterValues_Type);
|
|
|
|
|
PyModule_AddType(submodule, &BPy_IDGroup_IterItems_Type);
|
|
|
|
|
|
|
|
|
|
PyModule_AddType(submodule, &BPy_IDArray_Type);
|
|
|
|
|
|
|
|
|
|
return submodule;
|
|
|
|
|
|