[Python-checkins] cpython (2.7): Issue #28847: dubmdbm no longer writes the index file in when it is not

serhiy.storchaka python-checkins at python.org
Fri Dec 2 00:59:05 EST 2016


https://hg.python.org/cpython/rev/0516f54491cb
changeset:   105410:0516f54491cb
branch:      2.7
parent:      105407:7d9f1e455972
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Fri Dec 02 07:58:42 2016 +0200
summary:
  Issue #28847: dubmdbm no longer writes the index file in when it is not
changed and supports reading read-only files.

files:
  Lib/dumbdbm.py           |  12 ++++++++----
  Lib/test/test_dumbdbm.py |  21 +++++++++++++++++++++
  Misc/NEWS                |   3 +++
  3 files changed, 32 insertions(+), 4 deletions(-)


diff --git a/Lib/dumbdbm.py b/Lib/dumbdbm.py
--- a/Lib/dumbdbm.py
+++ b/Lib/dumbdbm.py
@@ -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 --git a/Lib/test/test_dumbdbm.py b/Lib/test/test_dumbdbm.py
--- a/Lib/test/test_dumbdbm.py
+++ b/Lib/test/test_dumbdbm.py
@@ -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 --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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__.
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list