From a14eecba4dc377cb34b5c2eab7f52765938122e0 Mon Sep 17 00:00:00 2001 From: Tomasz Wejroch Date: Thu, 8 Jan 2026 16:14:22 +0100 Subject: [PATCH] issue-694 Added support for del operator in a dbzero.list --- python_tests/test_list.py | 21 ++++++++++++ .../python/collections/CollectionMethods.hpp | 3 ++ src/dbzero/object_model/list/List.cpp | 33 ++++++++++--------- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/python_tests/test_list.py b/python_tests/test_list.py index a41cb7b1..cf240043 100644 --- a/python_tests/test_list.py +++ b/python_tests/test_list.py @@ -546,3 +546,24 @@ def test_append_to_random_lists(db0_autocommit_fixture): def test_list_tuple_indexed_access(db0_fixture): db0_list = db0.list([1, 2, 3, 5, 6, 7, 8]) assert db0_list[(1, 3, 4)] == [2, 5, 6] + + +def test_list_delitem(db0_fixture): + l = db0.list(range(10)) + del l[0] + assert l == [1, 2, 3, 4, 5, 6, 7, 8, 9] + del l[-1] + assert l == [1, 2, 3, 4, 5, 6, 7, 8] + del l[2] + assert l == [1, 2, 4, 5, 6, 7, 8] + + # Check del unrefs objects + obj = MemoTestClass(123) + obj_uuid = db0.uuid(obj) + l[0] = obj + del l[0] + del obj + db0.commit() + with pytest.raises(Exception): + obj = db0.fetch(obj_uuid) + diff --git a/src/dbzero/bindings/python/collections/CollectionMethods.hpp b/src/dbzero/bindings/python/collections/CollectionMethods.hpp index 743dcb56..37ece7f1 100644 --- a/src/dbzero/bindings/python/collections/CollectionMethods.hpp +++ b/src/dbzero/bindings/python/collections/CollectionMethods.hpp @@ -146,6 +146,9 @@ namespace db0::python index = py_obj->ext().size() -1; } else if (nargs == 1) { index = PyLong_AsLong(args[0]); + if (PyErr_Occurred()) { + return nullptr; + } } else { PyErr_SetString(PyExc_TypeError, "pop() takes zero or one argument."); return NULL; diff --git a/src/dbzero/object_model/list/List.cpp b/src/dbzero/object_model/list/List.cpp index ddc31ddb..0dabc1a9 100644 --- a/src/dbzero/object_model/list/List.cpp +++ b/src/dbzero/object_model/list/List.cpp @@ -81,9 +81,6 @@ namespace db0::object_model List::ObjectSharedPtr List::pop(FixtureLock &fixture, std::size_t i) { - if (size() == 0) { - THROWF(db0::InputException) << "Cannot pop from empty container "; - } if (i >= size()) { THROWF(db0::IndexException) << "Index out of range: " << i; } @@ -100,19 +97,25 @@ namespace db0::object_model THROWF(db0::IndexException) << "Index out of range: " << i; } - // recognize type ID from language specific object - auto type_id = LangToolkit::getTypeManager().getTypeId(lang_value); - // NOTE: packed storage not supported for list items - auto pre_storage_class = TypeUtils::m_storage_class_mapper.getPreStorageClass(type_id, false); - StorageClass storage_class; - if (pre_storage_class == PreStorageClass::OBJECT_WEAK_REF) { - storage_class = db0::getStorageClass(pre_storage_class, *fixture, lang_value); - } else { - storage_class = db0::getStorageClass(pre_storage_class); - } - auto [storage_class_value, value] = (*this)[i]; - v_bvector::setItem(i, createListItem(*fixture, type_id, lang_value, storage_class, getMemberFlags())); + if (lang_value) { + // recognize type ID from language specific object + auto type_id = LangToolkit::getTypeManager().getTypeId(lang_value); + // NOTE: packed storage not supported for list items + auto pre_storage_class = TypeUtils::m_storage_class_mapper.getPreStorageClass(type_id, false); + StorageClass storage_class; + if (pre_storage_class == PreStorageClass::OBJECT_WEAK_REF) { + storage_class = db0::getStorageClass(pre_storage_class, *fixture, lang_value); + } else { + storage_class = db0::getStorageClass(pre_storage_class); + } + + v_bvector::setItem(i, createListItem(*fixture, type_id, lang_value, storage_class, getMemberFlags())); + } + else { + // del operator used + this->erase(i); + } unrefMember(*fixture, storage_class_value, value); }