8000 gh-83383: Always mark the dbm.dumb database as unmodified after open(… · python/cpython@fc06096 · GitHub
[go: up one dir, main page]

Skip to content

Commit fc06096

Browse files
gh-83383: Always mark the dbm.dumb database as unmodified after open() and sync() (GH-114560)
The directory file for a newly created database is now created immediately after opening instead of deferring this until synchronizing or closing.
1 parent ff7588b commit fc06096

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

Lib/dbm/dumb.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ def _update(self, flag):
9898
except OSError:
9999
if flag not in ('c', 'n'):
100100
raise
101-
self._modified = True
101+
with self._io.open(self._dirfile, 'w', encoding="Latin-1") as f:
102+
self._chmod(self._dirfile)
102103
else:
103104
with f:
104105
for line in f:
@@ -134,6 +135,7 @@ def _commit(self):
134135
# position; UTF-8, though, does care sometimes.
135136
entry = "%r, %r\n" % (key.decode('Latin-1'), pos_and_siz_pair)
136137
f.write(entry)
138+
self._modified = False
137139

138140
sync = _commit
139141

Lib/test/test_dbm_dumb.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,27 @@ def test_missing_data(self):
246246
_delete_files()
247247
with self.assertRaises(FileNotFoundError):
248248
dumbdbm.open(_fname, value)
249+
self.assertFalse(os.path.exists(_fname + '.dat'))
249250
self.assertFalse(os.path.exists(_fname + '.dir'))
250251
self.assertFalse(os.path.exists(_fname + '.bak'))
251252

253+
for value in ('c', 'n'):
254+
_delete_files()
255+
with dumbdbm.open(_fname, value) as f:
256+
self.assertTrue(os.path.exists(_fname + '.dat'))
257+
self.assertTrue(os.path.exists(_fname + '.dir'))
258+
self.assertFalse(os.path.exists(_fname + '.bak'))
259+
self.assertFalse(os.path.exists(_fname + '.bak'))
260+
261+
for value in ('c', 'n'):
262+
_delete_files()
263+
with dumbdbm.open(_fname, value) as f:
264+
f['key'] = 'value'
265+
self.assertTrue(os.path.exists(_fname + '.dat'))
266+
self.assertTrue(os.path.exists(_fname + '.dir'))
267+
self.assertFalse(os.path.exists(_fname + '.bak'))
268+
self.assertTrue(os.path.exists(_fname + '.bak'))
269+
252270
def test_missing_index(self):
253271
with dumbdbm.open(_fname, 'n') as f:
254272
pass
@@ -259,6 +277,60 @@ def test_missing_index(self):
259277
self.assertFalse(os.path.exists(_fname + '.dir'))
260278
self.assertFalse(os.path.exists(_fname + '.bak'))
261279

280+
for value in ('c', 'n'):
281+
with dumbdbm.open(_fname, value) as f:
282+
self.assertTrue(os.path.exists(_fname + '.dir'))
283+
self.assertFalse(os.path.exists(_fname + '.bak'))
284+
self.assertFalse(os.path.exists(_fname + '.bak'))
285+
os.unlink(_fname + '.dir')
286+
287+
for value in ('c', 'n'):
288+
with dumbdbm.open(_fname, value) as f:
289+
f['key'] = 'value'
290+
self.assertTrue(os.path.exists(_fname + '.dir'))
291+
self.assertFalse(os.path.exists(_fname + '.bak'))
292+
self.assertTrue(os.path.exists(_fname + '.bak'))
293+
os.unlink(_fname + '.dir')
294+
os.unlink(_fname + '.bak')
295+
296+
def test_sync_empty_unmodified(self):
297+
with dumbdbm.open(_fname, 'n') as f:
298+
pass
299+
os.unlink(_fname + '.dir')
300+
for value in ('c', 'n'):
301+
with dumbdbm.open(_fname, value) as f:
302+
self.assertTrue(os.path.exists(_fname + '.dir'))
303+
self.assertFalse(os.path.exists(_fname + '.bak'))
304+
f.sync()
305+
self.assertTrue(os.path.exists(_fname + '.dir'))
306+
self.assertFalse(os.path.exists(_fname + '.bak'))
307+
os.unlink(_fname + '.dir')
308+
f.sync()
309+
self.assertFalse(os.path.exists(_fname + '.dir'))
310+
self.assertFalse(os.path.exists(_fname + '.bak'))
311+
self.assertFalse(os.path.exists(_fname + '.dir'))
312+
self.assertFalse(os.path.exists(_fname + '.bak'))
313+
314+
def test_sync_nonempty_unmodified(self):
315+
with dumbdbm.open(_fname, 'n') as f:
316+
pass
317+
os.unlink(_fname + '.dir')
318+
for value in ('c', 'n'):
319+
with dumbdbm.open(_fname, value) as f:
320+
f['key'] = 'value'
321+
self.assertTrue(os.path.exists(_fname + '.dir'))
322+
self.assertFalse(os.path.exists(_fname + '.bak'))
323+
f.sync()
324+
self.assertTrue(os.path.exists(_fname + '.dir'))
325+
self.assertTrue(os.path.exists(_fname + '.bak'))
326+
os.unlink(_fname + '.dir')
327+
os.unlink(_fname + '.bak')
328+
f.sync()
329+
self.assertFalse(os.path.exists(_fname + '.dir'))
330+
self.assertFalse(os.path.exists(_fname + '.bak'))
331+
self.assertFalse(os.path.exists(_fname + '.dir'))
332+
self.assertFalse(os.path.exists(_fname + '.bak'))
333+
262334
def test_invalid_flag(self):
263335
for flag in ('x', 'rf', None):
264336
with self.assertRaisesRegex(ValueError,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Synchronization of the :mod:`dbm.dumb` database is now no-op if there was no
2+
modification since opening or last synchronization.
3+
The directory file for a newly created empty :mod:`dbm.dumb` database is now
4+
created immediately after opening instead of deferring this until
5+
synchronizing or closing.

0 commit comments

Comments
 (0)
0