gh-134004: Added the reorganize() methods to dbm.sqlite, dbm.dumb and shelve (GH-134028)

They are similar to the same named method in dbm.gnu.
This commit is contained in:
Andrea-Oliveri 2025-06-01 14:30:04 +02:00 committed by GitHub
parent b595237166
commit f806463e16
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 172 additions and 6 deletions

View file

@ -135,6 +135,67 @@ class AnyDBMTestCase:
assert(f[key] == b"Python:")
f.close()
def test_anydbm_readonly_reorganize(self):
self.init_db()
with dbm.open(_fname, 'r') as d:
# Early stopping.
if not hasattr(d, 'reorganize'):
self.skipTest("method reorganize not available this dbm submodule")
self.assertRaises(dbm.error, lambda: d.reorganize())
def test_anydbm_reorganize_not_changed_content(self):
self.init_db()
with dbm.open(_fname, 'c') as d:
# Early stopping.
if not hasattr(d, 'reorganize'):
self.skipTest("method reorganize not available this dbm submodule")
keys_before = sorted(d.keys())
values_before = [d[k] for k in keys_before]
d.reorganize()
keys_after = sorted(d.keys())
values_after = [d[k] for k in keys_before]
self.assertEqual(keys_before, keys_after)
self.assertEqual(values_before, values_after)
def test_anydbm_reorganize_decreased_size(self):
def _calculate_db_size(db_path):
if os.path.isfile(db_path):
return os.path.getsize(db_path)
total_size = 0
for root, _, filenames in os.walk(db_path):
for filename in filenames:
file_path = os.path.join(root, filename)
total_size += os.path.getsize(file_path)
return total_size
# This test requires relatively large databases to reliably show difference in size before and after reorganizing.
with dbm.open(_fname, 'n') as f:
# Early stopping.
if not hasattr(f, 'reorganize'):
self.skipTest("method reorganize not available this dbm submodule")
for k in self._dict:
f[k.encode('ascii')] = self._dict[k] * 100000
db_keys = list(f.keys())
# Make sure to calculate size of database only after file is closed to ensure file content are flushed to disk.
size_before = _calculate_db_size(os.path.dirname(_fname))
# Delete some elements from the start of the database.
keys_to_delete = db_keys[:len(db_keys) // 2]
with dbm.open(_fname, 'c') as f:
for k in keys_to_delete:
del f[k]
f.reorganize()
# Make sure to calculate size of database only after file is closed to ensure file content are flushed to disk.
size_after = _calculate_db_size(os.path.dirname(_fname))
self.assertLess(size_after, size_before)
def test_open_with_bytes(self):
dbm.open(os.fsencode(_fname), "c").close()