Kaydet (Commit) 43153e4d authored tarafından Serhiy Storchaka's avatar Serhiy Storchaka

Issue #28847: dbm.dumb now supports reading read-only files and no longer

writes the index file when it is not changed.
...@@ -97,8 +97,9 @@ class _Database(collections.MutableMapping): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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"): ...@@ -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 @@ ...@@ -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): ...@@ -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 ...@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment