Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/python/intern/bpy_rna_id_collection.c')
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c577
1 files changed, 289 insertions, 288 deletions
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index 7a5849f818d..bb7604aea97 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -54,336 +54,337 @@
#include "bpy_rna.h"
typedef struct IDUserMapData {
- /* place-holder key only used for lookups to avoid creating new data only for lookups
- * (never return its contents) */
- PyObject *py_id_key_lookup_only;
+ /* place-holder key only used for lookups to avoid creating new data only for lookups
+ * (never return its contents) */
+ PyObject *py_id_key_lookup_only;
- /* we loop over data-blocks that this ID points to (do build a reverse lookup table) */
- PyObject *py_id_curr;
- ID *id_curr;
+ /* we loop over data-blocks that this ID points to (do build a reverse lookup table) */
+ PyObject *py_id_curr;
+ ID *id_curr;
- /* filter the values we add into the set */
- BLI_bitmap *types_bitmap;
+ /* filter the values we add into the set */
+ BLI_bitmap *types_bitmap;
- PyObject *user_map; /* set to fill in as we iterate */
- bool is_subset; /* true when we're only mapping a subset of all the ID's (subset arg is passed) */
+ PyObject *user_map; /* set to fill in as we iterate */
+ bool
+ is_subset; /* true when we're only mapping a subset of all the ID's (subset arg is passed) */
} IDUserMapData;
-
static int id_code_as_index(const short idcode)
{
- return (int)*((unsigned short *)&idcode);
+ return (int)*((unsigned short *)&idcode);
}
static bool id_check_type(const ID *id, const BLI_bitmap *types_bitmap)
{
- return BLI_BITMAP_TEST_BOOL(types_bitmap, id_code_as_index(GS(id->name)));
+ return BLI_BITMAP_TEST_BOOL(types_bitmap, id_code_as_index(GS(id->name)));
}
-static int foreach_libblock_id_user_map_callback(
- void *user_data, ID *self_id, ID **id_p, int UNUSED(cb_flag))
+static int foreach_libblock_id_user_map_callback(void *user_data,
+ ID *self_id,
+ ID **id_p,
+ int UNUSED(cb_flag))
{
- IDUserMapData *data = user_data;
-
- if (*id_p) {
-
- if (data->types_bitmap) {
- if (!id_check_type(*id_p, data->types_bitmap)) {
- return IDWALK_RET_NOP;
- }
- }
-
- if ((GS(self_id->name) == ID_OB) && (id_p == (ID **)&((Object *)self_id)->proxy_from)) {
- /* We skip proxy_from here, since it's some internal pointer which is not relevant info for py/API level. */
- return IDWALK_RET_NOP;
- }
- else if ((GS(self_id->name) == ID_KE) && (id_p == (ID **)&((Key *)self_id)->from)) {
- /* We skip from here, since it's some internal pointer which is not relevant info for py/API level. */
- return IDWALK_RET_NOP;
- }
-
- /* pyrna_struct_hash() uses ptr.data only,
- * but pyrna_struct_richcmp() uses also ptr.type,
- * so we need to create a valid PointerRNA here...
- */
- PyObject *key = data->py_id_key_lookup_only;
- RNA_id_pointer_create(*id_p, &((BPy_StructRNA *)key)->ptr);
-
- PyObject *set;
- if ((set = PyDict_GetItem(data->user_map, key)) == NULL) {
-
- /* limit to key's added already */
- if (data->is_subset) {
- return IDWALK_RET_NOP;
- }
-
- /* Cannot use our placeholder key here! */
- key = pyrna_id_CreatePyObject(*id_p);
- set = PySet_New(NULL);
- PyDict_SetItem(data->user_map, key, set);
- Py_DECREF(set);
- Py_DECREF(key);
- }
-
- if (data->py_id_curr == NULL) {
- data->py_id_curr = pyrna_id_CreatePyObject(data->id_curr);
- }
-
- PySet_Add(set, data->py_id_curr);
- }
-
- return IDWALK_RET_NOP;
+ IDUserMapData *data = user_data;
+
+ if (*id_p) {
+
+ if (data->types_bitmap) {
+ if (!id_check_type(*id_p, data->types_bitmap)) {
+ return IDWALK_RET_NOP;
+ }
+ }
+
+ if ((GS(self_id->name) == ID_OB) && (id_p == (ID **)&((Object *)self_id)->proxy_from)) {
+ /* We skip proxy_from here, since it's some internal pointer which is not relevant info for py/API level. */
+ return IDWALK_RET_NOP;
+ }
+ else if ((GS(self_id->name) == ID_KE) && (id_p == (ID **)&((Key *)self_id)->from)) {
+ /* We skip from here, since it's some internal pointer which is not relevant info for py/API level. */
+ return IDWALK_RET_NOP;
+ }
+
+ /* pyrna_struct_hash() uses ptr.data only,
+ * but pyrna_struct_richcmp() uses also ptr.type,
+ * so we need to create a valid PointerRNA here...
+ */
+ PyObject *key = data->py_id_key_lookup_only;
+ RNA_id_pointer_create(*id_p, &((BPy_StructRNA *)key)->ptr);
+
+ PyObject *set;
+ if ((set = PyDict_GetItem(data->user_map, key)) == NULL) {
+
+ /* limit to key's added already */
+ if (data->is_subset) {
+ return IDWALK_RET_NOP;
+ }
+
+ /* Cannot use our placeholder key here! */
+ key = pyrna_id_CreatePyObject(*id_p);
+ set = PySet_New(NULL);
+ PyDict_SetItem(data->user_map, key, set);
+ Py_DECREF(set);
+ Py_DECREF(key);
+ }
+
+ if (data->py_id_curr == NULL) {
+ data->py_id_curr = pyrna_id_CreatePyObject(data->id_curr);
+ }
+
+ PySet_Add(set, data->py_id_curr);
+ }
+
+ return IDWALK_RET_NOP;
}
PyDoc_STRVAR(bpy_user_map_doc,
-".. method:: user_map([subset=(id1, id2, ...)], key_types={..}, value_types={..})\n"
-"\n"
-" Returns a mapping of all ID datablocks in current ``bpy.data`` to a set of all datablocks using them.\n"
-"\n"
-" For list of valid set members for key_types & value_types, see: :class:`bpy.types.KeyingSetPath.id_type`.\n"
-"\n"
-" :arg subset: When passed, only these data-blocks and their users will be included as keys/values in the map.\n"
-" :type subset: sequence\n"
-" :arg key_types: Filter the keys mapped by ID types.\n"
-" :type key_types: set of strings\n"
-" :arg value_types: Filter the values in the set by ID types.\n"
-" :type value_types: set of strings\n"
-" :return: dictionary of :class:`bpy.types.ID` instances, with sets of ID's as their values.\n"
-" :rtype: dict\n"
-);
+ ".. method:: user_map([subset=(id1, id2, ...)], key_types={..}, value_types={..})\n"
+ "\n"
+ " Returns a mapping of all ID datablocks in current ``bpy.data`` to a set of all "
+ "datablocks using them.\n"
+ "\n"
+ " For list of valid set members for key_types & value_types, see: "
+ ":class:`bpy.types.KeyingSetPath.id_type`.\n"
+ "\n"
+ " :arg subset: When passed, only these data-blocks and their users will be "
+ "included as keys/values in the map.\n"
+ " :type subset: sequence\n"
+ " :arg key_types: Filter the keys mapped by ID types.\n"
+ " :type key_types: set of strings\n"
+ " :arg value_types: Filter the values in the set by ID types.\n"
+ " :type value_types: set of strings\n"
+ " :return: dictionary of :class:`bpy.types.ID` instances, with sets of ID's as "
+ "their values.\n"
+ " :rtype: dict\n");
static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
{
-#if 0 /* If someone knows how to get a proper 'self' in that case... */
- BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
- Main *bmain = pyrna->ptr.data;
+#if 0 /* If someone knows how to get a proper 'self' in that case... */
+ BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
+ Main *bmain = pyrna->ptr.data;
#else
- Main *bmain = G_MAIN; /* XXX Ugly, but should work! */
+ Main *bmain = G_MAIN; /* XXX Ugly, but should work! */
#endif
- ListBase *lb;
- ID *id;
-
- PyObject *subset = NULL;
-
- PyObject *key_types = NULL;
- PyObject *val_types = NULL;
- BLI_bitmap *key_types_bitmap = NULL;
- BLI_bitmap *val_types_bitmap = NULL;
-
- PyObject *ret = NULL;
-
- IDUserMapData data_cb = {NULL};
-
- static const char *_keywords[] = {"subset", "key_types", "value_types", NULL};
- static _PyArg_Parser _parser = {"|O$O!O!:user_map", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(
- args, kwds, &_parser,
- &subset,
- &PySet_Type, &key_types,
- &PySet_Type, &val_types))
- {
- return NULL;
- }
-
- if (key_types) {
- key_types_bitmap = pyrna_set_to_enum_bitmap(
- rna_enum_id_type_items, key_types, sizeof(short), true, USHRT_MAX, "key types");
- if (key_types_bitmap == NULL) {
- goto error;
- }
- }
-
- if (val_types) {
- val_types_bitmap = pyrna_set_to_enum_bitmap(
- rna_enum_id_type_items, val_types, sizeof(short), true, USHRT_MAX, "value types");
- if (val_types_bitmap == NULL) {
- goto error;
- }
- }
-
- if (subset) {
- PyObject *subset_fast = PySequence_Fast(subset, "user_map");
- if (subset_fast == NULL) {
- goto error;
- }
-
- PyObject **subset_array = PySequence_Fast_ITEMS(subset_fast);
- Py_ssize_t subset_len = PySequence_Fast_GET_SIZE(subset_fast);
-
- data_cb.user_map = _PyDict_NewPresized(subset_len);
- data_cb.is_subset = true;
- for (; subset_len; subset_array++, subset_len--) {
- PyObject *set = PySet_New(NULL);
- PyDict_SetItem(data_cb.user_map, *subset_array, set);
- Py_DECREF(set);
- }
- Py_DECREF(subset_fast);
- }
- else {
- data_cb.user_map = PyDict_New();
- }
-
- data_cb.types_bitmap = key_types_bitmap;
-
- FOREACH_MAIN_LISTBASE_BEGIN(bmain, lb)
- {
- FOREACH_MAIN_LISTBASE_ID_BEGIN(lb, id)
- {
- /* We cannot skip here in case we have some filter on key types... */
- if (key_types_bitmap == NULL && val_types_bitmap != NULL) {
- if (!id_check_type(id, val_types_bitmap)) {
- break;
- }
- }
-
- /* One-time init, ID is just used as placeholder here, we abuse this in iterator callback
- * to avoid having to rebuild a complete bpyrna object each time for the key searching
- * (where only ID pointer value is used). */
- if (data_cb.py_id_key_lookup_only == NULL) {
- data_cb.py_id_key_lookup_only = pyrna_id_CreatePyObject(id);
- }
-
- if (!data_cb.is_subset &&
- /* We do not want to pre-add keys of flitered out types. */
- (key_types_bitmap == NULL || id_check_type(id, key_types_bitmap)) &&
- /* We do not want to pre-add keys when we have filter on value types, but not on key types. */
- (val_types_bitmap == NULL || key_types_bitmap != NULL))
- {
- PyObject *key = data_cb.py_id_key_lookup_only;
- PyObject *set;
-
- RNA_id_pointer_create(id, &((BPy_StructRNA *)key)->ptr);
-
- /* We have to insert the key now, otherwise ID unused would be missing from final dict... */
- if ((set = PyDict_GetItem(data_cb.user_map, key)) == NULL) {
- /* Cannot use our placeholder key here! */
- key = pyrna_id_CreatePyObject(id);
- set = PySet_New(NULL);
- PyDict_SetItem(data_cb.user_map, key, set);
- Py_DECREF(set);
- Py_DECREF(key);
- }
- }
-
- if (val_types_bitmap != NULL && !id_check_type(id, val_types_bitmap)) {
- continue;
- }
-
- data_cb.id_curr = id;
- BKE_library_foreach_ID_link(NULL, id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_CB_NOP);
-
- if (data_cb.py_id_curr) {
- Py_DECREF(data_cb.py_id_curr);
- data_cb.py_id_curr = NULL;
- }
- }
- FOREACH_MAIN_LISTBASE_ID_END;
- }
- FOREACH_MAIN_LISTBASE_ID_END;
-
- ret = data_cb.user_map;
+ ListBase *lb;
+ ID *id;
+
+ PyObject *subset = NULL;
+
+ PyObject *key_types = NULL;
+ PyObject *val_types = NULL;
+ BLI_bitmap *key_types_bitmap = NULL;
+ BLI_bitmap *val_types_bitmap = NULL;
+
+ PyObject *ret = NULL;
+
+ IDUserMapData data_cb = {NULL};
+
+ static const char *_keywords[] = {"subset", "key_types", "value_types", NULL};
+ static _PyArg_Parser _parser = {"|O$O!O!:user_map", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kwds, &_parser, &subset, &PySet_Type, &key_types, &PySet_Type, &val_types)) {
+ return NULL;
+ }
+
+ if (key_types) {
+ key_types_bitmap = pyrna_set_to_enum_bitmap(
+ rna_enum_id_type_items, key_types, sizeof(short), true, USHRT_MAX, "key types");
+ if (key_types_bitmap == NULL) {
+ goto error;
+ }
+ }
+
+ if (val_types) {
+ val_types_bitmap = pyrna_set_to_enum_bitmap(
+ rna_enum_id_type_items, val_types, sizeof(short), true, USHRT_MAX, "value types");
+ if (val_types_bitmap == NULL) {
+ goto error;
+ }
+ }
+
+ if (subset) {
+ PyObject *subset_fast = PySequence_Fast(subset, "user_map");
+ if (subset_fast == NULL) {
+ goto error;
+ }
+
+ PyObject **subset_array = PySequence_Fast_ITEMS(subset_fast);
+ Py_ssize_t subset_len = PySequence_Fast_GET_SIZE(subset_fast);
+
+ data_cb.user_map = _PyDict_NewPresized(subset_len);
+ data_cb.is_subset = true;
+ for (; subset_len; subset_array++, subset_len--) {
+ PyObject *set = PySet_New(NULL);
+ PyDict_SetItem(data_cb.user_map, *subset_array, set);
+ Py_DECREF(set);
+ }
+ Py_DECREF(subset_fast);
+ }
+ else {
+ data_cb.user_map = PyDict_New();
+ }
+
+ data_cb.types_bitmap = key_types_bitmap;
+
+ FOREACH_MAIN_LISTBASE_BEGIN(bmain, lb)
+ {
+ FOREACH_MAIN_LISTBASE_ID_BEGIN(lb, id)
+ {
+ /* We cannot skip here in case we have some filter on key types... */
+ if (key_types_bitmap == NULL && val_types_bitmap != NULL) {
+ if (!id_check_type(id, val_types_bitmap)) {
+ break;
+ }
+ }
+
+ /* One-time init, ID is just used as placeholder here, we abuse this in iterator callback
+ * to avoid having to rebuild a complete bpyrna object each time for the key searching
+ * (where only ID pointer value is used). */
+ if (data_cb.py_id_key_lookup_only == NULL) {
+ data_cb.py_id_key_lookup_only = pyrna_id_CreatePyObject(id);
+ }
+
+ if (!data_cb.is_subset &&
+ /* We do not want to pre-add keys of flitered out types. */
+ (key_types_bitmap == NULL || id_check_type(id, key_types_bitmap)) &&
+ /* We do not want to pre-add keys when we have filter on value types, but not on key types. */
+ (val_types_bitmap == NULL || key_types_bitmap != NULL)) {
+ PyObject *key = data_cb.py_id_key_lookup_only;
+ PyObject *set;
+
+ RNA_id_pointer_create(id, &((BPy_StructRNA *)key)->ptr);
+
+ /* We have to insert the key now, otherwise ID unused would be missing from final dict... */
+ if ((set = PyDict_GetItem(data_cb.user_map, key)) == NULL) {
+ /* Cannot use our placeholder key here! */
+ key = pyrna_id_CreatePyObject(id);
+ set = PySet_New(NULL);
+ PyDict_SetItem(data_cb.user_map, key, set);
+ Py_DECREF(set);
+ Py_DECREF(key);
+ }
+ }
+
+ if (val_types_bitmap != NULL && !id_check_type(id, val_types_bitmap)) {
+ continue;
+ }
+
+ data_cb.id_curr = id;
+ BKE_library_foreach_ID_link(
+ NULL, id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_CB_NOP);
+
+ if (data_cb.py_id_curr) {
+ Py_DECREF(data_cb.py_id_curr);
+ data_cb.py_id_curr = NULL;
+ }
+ }
+ FOREACH_MAIN_LISTBASE_ID_END;
+ }
+ FOREACH_MAIN_LISTBASE_ID_END;
+
+ ret = data_cb.user_map;
error:
- if (data_cb.py_id_key_lookup_only != NULL) {
- Py_XDECREF(data_cb.py_id_key_lookup_only);
- }
+ if (data_cb.py_id_key_lookup_only != NULL) {
+ Py_XDECREF(data_cb.py_id_key_lookup_only);
+ }
- if (key_types_bitmap != NULL) {
- MEM_freeN(key_types_bitmap);
- }
+ if (key_types_bitmap != NULL) {
+ MEM_freeN(key_types_bitmap);
+ }
- if (val_types_bitmap != NULL) {
- MEM_freeN(val_types_bitmap);
- }
+ if (val_types_bitmap != NULL) {
+ MEM_freeN(val_types_bitmap);
+ }
- return ret;
+ return ret;
}
PyDoc_STRVAR(bpy_batch_remove_doc,
-".. method:: batch_remove(ids=(id1, id2, ...))\n"
-"\n"
-" Remove (delete) several IDs at once.\n"
-"\n"
-" WARNING: Considered experimental feature currently.\n"
-"\n"
-" Note that this function is quicker than individual calls to :func:`remove()` (from :class:`bpy.types.BlendData`\n"
-" ID collections), but less safe/versatile (it can break Blender, e.g. by removing all scenes...).\n"
-"\n"
-" :arg ids: Iterables of IDs (types can be mixed).\n"
-" :type subset: sequence\n"
-);
+ ".. method:: batch_remove(ids=(id1, id2, ...))\n"
+ "\n"
+ " Remove (delete) several IDs at once.\n"
+ "\n"
+ " WARNING: Considered experimental feature currently.\n"
+ "\n"
+ " Note that this function is quicker than individual calls to :func:`remove()` "
+ "(from :class:`bpy.types.BlendData`\n"
+ " ID collections), but less safe/versatile (it can break Blender, e.g. by removing "
+ "all scenes...).\n"
+ "\n"
+ " :arg ids: Iterables of IDs (types can be mixed).\n"
+ " :type subset: sequence\n");
static PyObject *bpy_batch_remove(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
{
-#if 0 /* If someone knows how to get a proper 'self' in that case... */
- BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
- Main *bmain = pyrna->ptr.data;
+#if 0 /* If someone knows how to get a proper 'self' in that case... */
+ BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
+ Main *bmain = pyrna->ptr.data;
#else
- Main *bmain = G_MAIN; /* XXX Ugly, but should work! */
+ Main *bmain = G_MAIN; /* XXX Ugly, but should work! */
#endif
- PyObject *ids = NULL;
-
- PyObject *ret = NULL;
-
- static const char *_keywords[] = {"ids", NULL};
- static _PyArg_Parser _parser = {"O:user_map", _keywords, 0};
- if (!_PyArg_ParseTupleAndKeywordsFast(
- args, kwds, &_parser,
- &ids))
- {
- return ret;
- }
-
- if (ids) {
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-
- PyObject *ids_fast = PySequence_Fast(ids, "batch_remove");
- if (ids_fast == NULL) {
- goto error;
- }
-
- PyObject **ids_array = PySequence_Fast_ITEMS(ids_fast);
- Py_ssize_t ids_len = PySequence_Fast_GET_SIZE(ids_fast);
-
- for (; ids_len; ids_array++, ids_len--) {
- ID *id;
- if (!pyrna_id_FromPyObject(*ids_array, &id)) {
- PyErr_Format(PyExc_TypeError,
- "Expected an ID type, not %.200s",
- Py_TYPE(*ids_array)->tp_name);
- Py_DECREF(ids_fast);
- goto error;
- }
-
- id->tag |= LIB_TAG_DOIT;
- }
- Py_DECREF(ids_fast);
-
- BKE_id_multi_tagged_delete(bmain);
- /* Force full redraw, mandatory to avoid crashes when running this from UI... */
- WM_main_add_notifier(NC_WINDOW, NULL);
- }
- else {
- goto error;
- }
-
- Py_INCREF(Py_None);
- ret = Py_None;
+ PyObject *ids = NULL;
+
+ PyObject *ret = NULL;
+
+ static const char *_keywords[] = {"ids", NULL};
+ static _PyArg_Parser _parser = {"O:user_map", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &ids)) {
+ return ret;
+ }
+
+ if (ids) {
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
+ PyObject *ids_fast = PySequence_Fast(ids, "batch_remove");
+ if (ids_fast == NULL) {
+ goto error;
+ }
+
+ PyObject **ids_array = PySequence_Fast_ITEMS(ids_fast);
+ Py_ssize_t ids_len = PySequence_Fast_GET_SIZE(ids_fast);
+
+ for (; ids_len; ids_array++, ids_len--) {
+ ID *id;
+ if (!pyrna_id_FromPyObject(*ids_array, &id)) {
+ PyErr_Format(
+ PyExc_TypeError, "Expected an ID type, not %.200s", Py_TYPE(*ids_array)->tp_name);
+ Py_DECREF(ids_fast);
+ goto error;
+ }
+
+ id->tag |= LIB_TAG_DOIT;
+ }
+ Py_DECREF(ids_fast);
+
+ BKE_id_multi_tagged_delete(bmain);
+ /* Force full redraw, mandatory to avoid crashes when running this from UI... */
+ WM_main_add_notifier(NC_WINDOW, NULL);
+ }
+ else {
+ goto error;
+ }
+
+ Py_INCREF(Py_None);
+ ret = Py_None;
error:
- return ret;
+ return ret;
}
int BPY_rna_id_collection_module(PyObject *mod_par)
{
- static PyMethodDef user_map = {
- "user_map", (PyCFunction)bpy_user_map, METH_VARARGS | METH_KEYWORDS, bpy_user_map_doc};
+ static PyMethodDef user_map = {
+ "user_map", (PyCFunction)bpy_user_map, METH_VARARGS | METH_KEYWORDS, bpy_user_map_doc};
- PyModule_AddObject(mod_par, "_rna_id_collection_user_map", PyCFunction_New(&user_map, NULL));
+ PyModule_AddObject(mod_par, "_rna_id_collection_user_map", PyCFunction_New(&user_map, NULL));
- static PyMethodDef batch_remove = {
- "batch_remove", (PyCFunction)bpy_batch_remove, METH_VARARGS | METH_KEYWORDS, bpy_batch_remove_doc};
+ static PyMethodDef batch_remove = {"batch_remove",
+ (PyCFunction)bpy_batch_remove,
+ METH_VARARGS | METH_KEYWORDS,
+ bpy_batch_remove_doc};
- PyModule_AddObject(mod_par, "_rna_id_collection_batch_remove", PyCFunction_New(&batch_remove, NULL));
+ PyModule_AddObject(
+ mod_par, "_rna_id_collection_batch_remove", PyCFunction_New(&batch_remove, NULL));
- return 0;
+ return 0;
}