changeset: 105410:0516f54491cb branch: 2.7 parent: 105407:7d9f1e455972 user: Serhiy Storchaka date: Fri Dec 02 07:58:42 2016 +0200 files: Lib/dumbdbm.py Lib/test/test_dumbdbm.py Misc/NEWS description: Issue #28847: dubmdbm no longer writes the index file in when it is not changed and supports reading read-only files. diff -r 7d9f1e455972 -r 0516f54491cb Lib/dumbdbm.py --- a/Lib/dumbdbm.py Thu Dec 01 21:42:15 2016 +0100 +++ b/Lib/dumbdbm.py Fri Dec 02 07:58:42 2016 +0200 @@ -45,8 +45,9 @@ _os = _os # for _commit() _open = _open # for _commit() - def __init__(self, filebasename, mode): + def __init__(self, filebasename, mode, flag='c'): self._mode = mode + self._readonly = (flag == 'r') # The directory file is a text file. Each line looks like # "%r, (%d, %d)\n" % (key, pos, siz) @@ -81,8 +82,9 @@ try: f = _open(self._dirfile) except IOError: - pass + self._modified = not self._readonly else: + self._modified = False with f: for line in f: line = line.rstrip() @@ -96,7 +98,7 @@ # 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: @@ -159,6 +161,7 @@ def __setitem__(self, key, val): if not type(key) == type('') == type(val): raise TypeError, "keys and values must be strings" + self._modified = True if key not in self._index: self._addkey(key, self._addval(val)) else: @@ -184,6 +187,7 @@ # (so that _commit() never gets called). def __delitem__(self, key): + 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 @@ -246,4 +250,4 @@ # Turn off any bits that are set in the umask mode = mode & (~um) - return _Database(file, mode) + return _Database(file, mode, flag) diff -r 7d9f1e455972 -r 0516f54491cb Lib/test/test_dumbdbm.py --- a/Lib/test/test_dumbdbm.py Thu Dec 01 21:42:15 2016 +0100 +++ b/Lib/test/test_dumbdbm.py Fri Dec 02 07:58:42 2016 +0200 @@ -3,6 +3,7 @@ """ import os +import stat import unittest import dumbdbm from test import test_support @@ -168,6 +169,26 @@ dumbdbm.open(_fname).close() self.assertEqual(stdout.getvalue(), '') + @unittest.skipUnless(hasattr(os, 'chmod'), 'test needs os.chmod()') + def test_readonly_files(self): + dir = _fname + os.mkdir(dir) + try: + fname = os.path.join(dir, 'db') + f = dumbdbm.open(fname, 'n') + self.assertEqual(list(f.keys()), []) + for key in self._dict: + f[key] = self._dict[key] + f.close() + os.chmod(fname + ".dir", stat.S_IRUSR) + os.chmod(fname + ".dat", stat.S_IRUSR) + os.chmod(dir, stat.S_IRUSR|stat.S_IXUSR) + f = dumbdbm.open(fname, 'r') + self.assertEqual(sorted(f.keys()), sorted(self._dict)) + f.close() # don't write + finally: + test_support.rmtree(dir) + def tearDown(self): _delete_files() diff -r 7d9f1e455972 -r 0516f54491cb Misc/NEWS --- a/Misc/NEWS Thu Dec 01 21:42:15 2016 +0100 +++ b/Misc/NEWS Fri Dec 02 07:58:42 2016 +0200 @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #28847: dubmdbm no longer writes the index file in when it is not + changed and supports reading read-only files. + - Issue #11145: Fixed miscellaneous issues with C-style formatting of types with custom __oct__ and __hex__.