mirror of https://github.com/python/cpython
Issue #28847: dbm.dumb now supports reading read-only files and no longer
writes the index file when it is not changed.
This commit is contained in:
commit
43153e4d49
|
@ -97,8 +97,9 @@ class _Database(collections.MutableMapping):
|
||||||
try:
|
try:
|
||||||
f = _io.open(self._dirfile, 'r', encoding="Latin-1")
|
f = _io.open(self._dirfile, 'r', encoding="Latin-1")
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
self._modified = not self._readonly
|
||||||
else:
|
else:
|
||||||
|
self._modified = False
|
||||||
with f:
|
with f:
|
||||||
for line in f:
|
for line in f:
|
||||||
line = line.rstrip()
|
line = line.rstrip()
|
||||||
|
@ -113,7 +114,7 @@ class _Database(collections.MutableMapping):
|
||||||
# CAUTION: It's vital that _commit() succeed, and _commit() can
|
# CAUTION: It's vital that _commit() succeed, and _commit() can
|
||||||
# be called from __del__(). Therefore we must never reference a
|
# be called from __del__(). Therefore we must never reference a
|
||||||
# global in this routine.
|
# global in this routine.
|
||||||
if self._index is None:
|
if self._index is None or not self._modified:
|
||||||
return # nothing to do
|
return # nothing to do
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -197,6 +198,7 @@ class _Database(collections.MutableMapping):
|
||||||
elif not isinstance(val, (bytes, bytearray)):
|
elif not isinstance(val, (bytes, bytearray)):
|
||||||
raise TypeError("values must be bytes or strings")
|
raise TypeError("values must be bytes or strings")
|
||||||
self._verify_open()
|
self._verify_open()
|
||||||
|
self._modified = True
|
||||||
if key not in self._index:
|
if key not in self._index:
|
||||||
self._addkey(key, self._addval(val))
|
self._addkey(key, self._addval(val))
|
||||||
else:
|
else:
|
||||||
|
@ -229,6 +231,7 @@ class _Database(collections.MutableMapping):
|
||||||
if isinstance(key, str):
|
if isinstance(key, str):
|
||||||
key = key.encode('utf-8')
|
key = key.encode('utf-8')
|
||||||
self._verify_open()
|
self._verify_open()
|
||||||
|
self._modified = True
|
||||||
# The blocks used by the associated value are lost.
|
# The blocks used by the associated value are lost.
|
||||||
del self._index[key]
|
del self._index[key]
|
||||||
# XXX It's unclear why we do a _commit() here (the code always
|
# XXX It's unclear why we do a _commit() here (the code always
|
||||||
|
|
|
@ -360,9 +360,9 @@ if sys.platform.startswith("win"):
|
||||||
mode = 0
|
mode = 0
|
||||||
if stat.S_ISDIR(mode):
|
if stat.S_ISDIR(mode):
|
||||||
_waitfor(_rmtree_inner, fullname, waitall=True)
|
_waitfor(_rmtree_inner, fullname, waitall=True)
|
||||||
_force_run(path, os.rmdir, fullname)
|
_force_run(fullname, os.rmdir, fullname)
|
||||||
else:
|
else:
|
||||||
_force_run(path, os.unlink, fullname)
|
_force_run(fullname, os.unlink, fullname)
|
||||||
_waitfor(_rmtree_inner, path, waitall=True)
|
_waitfor(_rmtree_inner, path, waitall=True)
|
||||||
_waitfor(lambda p: _force_run(p, os.rmdir, p), path)
|
_waitfor(lambda p: _force_run(p, os.rmdir, p), path)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
import io
|
import io
|
||||||
import operator
|
import operator
|
||||||
import os
|
import os
|
||||||
|
import stat
|
||||||
import unittest
|
import unittest
|
||||||
import warnings
|
import warnings
|
||||||
import dbm.dumb as dumbdbm
|
import dbm.dumb as dumbdbm
|
||||||
|
@ -259,6 +260,21 @@ class DumbDBMTestCase(unittest.TestCase):
|
||||||
f = dumbdbm.open(_fname, flag)
|
f = dumbdbm.open(_fname, flag)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'chmod'), 'test needs os.chmod()')
|
||||||
|
def test_readonly_files(self):
|
||||||
|
with support.temp_dir() as dir:
|
||||||
|
fname = os.path.join(dir, 'db')
|
||||||
|
with dumbdbm.open(fname, 'n') as f:
|
||||||
|
self.assertEqual(list(f.keys()), [])
|
||||||
|
for key in self._dict:
|
||||||
|
f[key] = self._dict[key]
|
||||||
|
os.chmod(fname + ".dir", stat.S_IRUSR)
|
||||||
|
os.chmod(fname + ".dat", stat.S_IRUSR)
|
||||||
|
os.chmod(dir, stat.S_IRUSR|stat.S_IXUSR)
|
||||||
|
with dumbdbm.open(fname, 'r') as f:
|
||||||
|
self.assertEqual(sorted(f.keys()), sorted(self._dict))
|
||||||
|
f.close() # don't write
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
_delete_files()
|
_delete_files()
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #28847: dbm.dumb now supports reading read-only files and no longer
|
||||||
|
writes the index file when it is not changed.
|
||||||
|
|
||||||
- Issue #27030: Unknown escapes consisting of ``'\'`` and an ASCII letter in
|
- Issue #27030: Unknown escapes consisting of ``'\'`` and an ASCII letter in
|
||||||
re.sub() replacement templates regular expressions now are errors.
|
re.sub() replacement templates regular expressions now are errors.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue