diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2016-12-07 11:02:18 +0200 |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2016-12-07 11:02:18 +0200 |
commit | 43153e4d49100b46a603afa8deeca415eb18d180 (patch) | |
tree | 85fcb5017fe9ce2b58baa853868c7b7fedee587b | |
parent | c29ba8b48962f59ffd5916731b35ac934f96304a (diff) | |
parent | 520348e5c0284668738e0ba98b86e7d1a5fd8600 (diff) | |
download | cpython-git-43153e4d49100b46a603afa8deeca415eb18d180.tar.gz |
Issue #28847: dbm.dumb now supports reading read-only files and no longer
writes the index file when it is not changed.
-rw-r--r-- | Lib/dbm/dumb.py | 7 | ||||
-rw-r--r-- | Lib/test/support/__init__.py | 4 | ||||
-rw-r--r-- | Lib/test/test_dbm_dumb.py | 16 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
4 files changed, 26 insertions, 4 deletions
diff --git a/Lib/dbm/dumb.py b/Lib/dbm/dumb.py index e7c6440ee6..2296dbfd54 100644 --- a/Lib/dbm/dumb.py +++ b/Lib/dbm/dumb.py @@ -97,8 +97,9 @@ class _Database(collections.MutableMapping): try: f = _io.open(self._dirfile, 'r', encoding="Latin-1") except OSError: - pass + self._modified = not self._readonly else: + self._modified = False with f: for line in f: line = line.rstrip() @@ -113,7 +114,7 @@ class _Database(collections.MutableMapping): # CAUTION: It's vital that _commit() succeed, and _commit() can # be called from __del__(). Therefore we must never reference a # global in this routine. - if self._index is None: + if self._index is None or not self._modified: return # nothing to do try: @@ -197,6 +198,7 @@ class _Database(collections.MutableMapping): elif not isinstance(val, (bytes, bytearray)): raise TypeError("values must be bytes or strings") self._verify_open() + self._modified = True if key not in self._index: self._addkey(key, self._addval(val)) else: @@ -229,6 +231,7 @@ class _Database(collections.MutableMapping): if isinstance(key, str): key = key.encode('utf-8') self._verify_open() + self._modified = True # The blocks used by the associated value are lost. del self._index[key] # XXX It's unclear why we do a _commit() here (the code always diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index eb5a89aaf4..09a02daa9d 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -360,9 +360,9 @@ if sys.platform.startswith("win"): mode = 0 if stat.S_ISDIR(mode): _waitfor(_rmtree_inner, fullname, waitall=True) - _force_run(path, os.rmdir, fullname) + _force_run(fullname, os.rmdir, fullname) else: - _force_run(path, os.unlink, fullname) + _force_run(fullname, os.unlink, fullname) _waitfor(_rmtree_inner, path, waitall=True) _waitfor(lambda p: _force_run(p, os.rmdir, p), path) else: diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py index 2d77f078b7..df531d64e4 100644 --- a/Lib/test/test_dbm_dumb.py +++ b/Lib/test/test_dbm_dumb.py @@ -5,6 +5,7 @@ import io import operator import os +import stat import unittest import warnings import dbm.dumb as dumbdbm @@ -259,6 +260,21 @@ class DumbDBMTestCase(unittest.TestCase): f = dumbdbm.open(_fname, flag) 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): _delete_files() @@ -165,6 +165,9 @@ Core and Builtins 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 re.sub() replacement templates regular expressions now are errors. |