mirror of https://github.com/python/cpython
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.
This commit is contained in:
parent
ff7588b729
commit
fc06096911
|
@ -98,7 +98,8 @@ class _Database(collections.abc.MutableMapping):
|
||||||
except OSError:
|
except OSError:
|
||||||
if flag not in ('c', 'n'):
|
if flag not in ('c', 'n'):
|
||||||
raise
|
raise
|
||||||
self._modified = True
|
with self._io.open(self._dirfile, 'w', encoding="Latin-1") as f:
|
||||||
|
self._chmod(self._dirfile)
|
||||||
else:
|
else:
|
||||||
with f:
|
with f:
|
||||||
for line in f:
|
for line in f:
|
||||||
|
@ -134,6 +135,7 @@ class _Database(collections.abc.MutableMapping):
|
||||||
# position; UTF-8, though, does care sometimes.
|
# position; UTF-8, though, does care sometimes.
|
||||||
entry = "%r, %r\n" % (key.decode('Latin-1'), pos_and_siz_pair)
|
entry = "%r, %r\n" % (key.decode('Latin-1'), pos_and_siz_pair)
|
||||||
f.write(entry)
|
f.write(entry)
|
||||||
|
self._modified = False
|
||||||
|
|
||||||
sync = _commit
|
sync = _commit
|
||||||
|
|
||||||
|
|
|
@ -246,9 +246,27 @@ class DumbDBMTestCase(unittest.TestCase):
|
||||||
_delete_files()
|
_delete_files()
|
||||||
with self.assertRaises(FileNotFoundError):
|
with self.assertRaises(FileNotFoundError):
|
||||||
dumbdbm.open(_fname, value)
|
dumbdbm.open(_fname, value)
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.dat'))
|
||||||
self.assertFalse(os.path.exists(_fname + '.dir'))
|
self.assertFalse(os.path.exists(_fname + '.dir'))
|
||||||
self.assertFalse(os.path.exists(_fname + '.bak'))
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
|
||||||
|
for value in ('c', 'n'):
|
||||||
|
_delete_files()
|
||||||
|
with dumbdbm.open(_fname, value) as f:
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.dat'))
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
|
||||||
|
for value in ('c', 'n'):
|
||||||
|
_delete_files()
|
||||||
|
with dumbdbm.open(_fname, value) as f:
|
||||||
|
f['key'] = 'value'
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.dat'))
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.bak'))
|
||||||
|
|
||||||
def test_missing_index(self):
|
def test_missing_index(self):
|
||||||
with dumbdbm.open(_fname, 'n') as f:
|
with dumbdbm.open(_fname, 'n') as f:
|
||||||
pass
|
pass
|
||||||
|
@ -259,6 +277,60 @@ class DumbDBMTestCase(unittest.TestCase):
|
||||||
self.assertFalse(os.path.exists(_fname + '.dir'))
|
self.assertFalse(os.path.exists(_fname + '.dir'))
|
||||||
self.assertFalse(os.path.exists(_fname + '.bak'))
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
|
||||||
|
for value in ('c', 'n'):
|
||||||
|
with dumbdbm.open(_fname, value) as f:
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
os.unlink(_fname + '.dir')
|
||||||
|
|
||||||
|
for value in ('c', 'n'):
|
||||||
|
with dumbdbm.open(_fname, value) as f:
|
||||||
|
f['key'] = 'value'
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.bak'))
|
||||||
|
os.unlink(_fname + '.dir')
|
||||||
|
os.unlink(_fname + '.bak')
|
||||||
|
|
||||||
|
def test_sync_empty_unmodified(self):
|
||||||
|
with dumbdbm.open(_fname, 'n') as f:
|
||||||
|
pass
|
||||||
|
os.unlink(_fname + '.dir')
|
||||||
|
for value in ('c', 'n'):
|
||||||
|
with dumbdbm.open(_fname, value) as f:
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
f.sync()
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
os.unlink(_fname + '.dir')
|
||||||
|
f.sync()
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
|
||||||
|
def test_sync_nonempty_unmodified(self):
|
||||||
|
with dumbdbm.open(_fname, 'n') as f:
|
||||||
|
pass
|
||||||
|
os.unlink(_fname + '.dir')
|
||||||
|
for value in ('c', 'n'):
|
||||||
|
with dumbdbm.open(_fname, value) as f:
|
||||||
|
f['key'] = 'value'
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
f.sync()
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertTrue(os.path.exists(_fname + '.bak'))
|
||||||
|
os.unlink(_fname + '.dir')
|
||||||
|
os.unlink(_fname + '.bak')
|
||||||
|
f.sync()
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.dir'))
|
||||||
|
self.assertFalse(os.path.exists(_fname + '.bak'))
|
||||||
|
|
||||||
def test_invalid_flag(self):
|
def test_invalid_flag(self):
|
||||||
for flag in ('x', 'rf', None):
|
for flag in ('x', 'rf', None):
|
||||||
with self.assertRaisesRegex(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Synchronization of the :mod:`dbm.dumb` database is now no-op if there was no
|
||||||
|
modification since opening or last synchronization.
|
||||||
|
The directory file for a newly created empty :mod:`dbm.dumb` database is now
|
||||||
|
created immediately after opening instead of deferring this until
|
||||||
|
synchronizing or closing.
|
Loading…
Reference in New Issue