]> granicus.if.org Git - python/commitdiff
Issue #28847: dubmdbm no longer writes the index file in when it is not
authorSerhiy Storchaka <storchaka@gmail.com>
Fri, 2 Dec 2016 05:58:42 +0000 (07:58 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Fri, 2 Dec 2016 05:58:42 +0000 (07:58 +0200)
changed and supports reading read-only files.

Lib/dumbdbm.py
Lib/test/test_dumbdbm.py
Misc/NEWS

index 8ef7e79582c6f59a28872ff4a02dd7523d531543..ac73b89c8887c16c3f6471862c94b37c105400dc 100644 (file)
@@ -45,8 +45,9 @@ class _Database(UserDict.DictMixin):
     _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 @@ class _Database(UserDict.DictMixin):
         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 @@ class _Database(UserDict.DictMixin):
         # 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 @@ class _Database(UserDict.DictMixin):
     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 @@ class _Database(UserDict.DictMixin):
             # (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 @@ def open(file, flag=None, mode=0666):
         # Turn off any bits that are set in the umask
         mode = mode & (~um)
 
-    return _Database(file, mode)
+    return _Database(file, mode, flag)
index 6520efdb83aeaa5d3415bfbe4a28718037992659..024ddda4df8f8978e3a0ed3f20d431b8983a9024 100644 (file)
@@ -3,6 +3,7 @@
 """
 
 import os
+import stat
 import unittest
 import dumbdbm
 from test import test_support
@@ -168,6 +169,26 @@ class DumbDBMTestCase(unittest.TestCase):
                 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()
 
index c7344a2629d3e1b4dee461c57cf6c1d75b2b71eb..cc2ab92604eb274a93a96443ec39846b0a3fcfc4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 2.7.13?
 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__.