[Python-checkins] cpython (3.4): make operations on closed dumb databases raise a consistent exception (closes

benjamin.peterson python-checkins at python.org
Sat Apr 26 22:57:20 CEST 2014


http://hg.python.org/cpython/rev/e8343cb98cc3
changeset:   90467:e8343cb98cc3
branch:      3.4
parent:      90463:b7fd640fb159
user:        Benjamin Peterson <benjamin at python.org>
date:        Sat Apr 26 16:56:52 2014 -0400
summary:
  make operations on closed dumb databases raise a consistent exception (closes #19385)

Patch by Claudiu Popa.

files:
  Lib/dbm/dumb.py           |  12 +++++++++++
  Lib/test/test_dbm_dumb.py |  29 +++++++++++++++++++++++---
  Misc/NEWS                 |   3 ++
  3 files changed, 40 insertions(+), 4 deletions(-)


diff --git a/Lib/dbm/dumb.py b/Lib/dbm/dumb.py
--- a/Lib/dbm/dumb.py
+++ b/Lib/dbm/dumb.py
@@ -118,9 +118,14 @@
 
     sync = _commit
 
+    def _verify_open(self):
+        if self._index is None:
+            raise error('DBM object has already been closed')
+
     def __getitem__(self, key):
         if isinstance(key, str):
             key = key.encode('utf-8')
+        self._verify_open()
         pos, siz = self._index[key]     # may raise KeyError
         f = _io.open(self._datfile, 'rb')
         f.seek(pos)
@@ -173,6 +178,7 @@
             val = val.encode('utf-8')
         elif not isinstance(val, (bytes, bytearray)):
             raise TypeError("values must be bytes or strings")
+        self._verify_open()
         if key not in self._index:
             self._addkey(key, self._addval(val))
         else:
@@ -200,6 +206,7 @@
     def __delitem__(self, key):
         if isinstance(key, str):
             key = key.encode('utf-8')
+        self._verify_open()
         # 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
@@ -209,21 +216,26 @@
         self._commit()
 
     def keys(self):
+        self._verify_open()
         return list(self._index.keys())
 
     def items(self):
+        self._verify_open()
         return [(key, self[key]) for key in self._index.keys()]
 
     def __contains__(self, key):
         if isinstance(key, str):
             key = key.encode('utf-8')
+        self._verify_open()
         return key in self._index
 
     def iterkeys(self):
+        self._verify_open()
         return iter(self._index.keys())
     __iter__ = iterkeys
 
     def __len__(self):
+        self._verify_open()
         return len(self._index)
 
     def close(self):
diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py
--- a/Lib/test/test_dbm_dumb.py
+++ b/Lib/test/test_dbm_dumb.py
@@ -3,10 +3,12 @@
 """
 
 import io
+import operator
 import os
 import unittest
 import dbm.dumb as dumbdbm
 from test import support
+from functools import partial
 
 _fname = support.TESTFN
 
@@ -190,12 +192,31 @@
         with dumbdbm.open(_fname, 'r') as db:
             self.assertEqual(list(db.keys()), [b"dumbdbm context manager"])
 
-        # This currently just raises AttributeError rather than a specific
-        # exception like the GNU or NDBM based implementations. See
-        # http://bugs.python.org/issue19385 for details.
-        with self.assertRaises(Exception):
+        with self.assertRaises(dumbdbm.error):
             db.keys()
 
+    def test_check_closed(self):
+        f = dumbdbm.open(_fname, 'c')
+        f.close()
+
+        for meth in (partial(operator.delitem, f),
+                     partial(operator.setitem, f, 'b'),
+                     partial(operator.getitem, f),
+                     partial(operator.contains, f)):
+            with self.assertRaises(dumbdbm.error) as cm:
+                meth('test')
+            self.assertEqual(str(cm.exception),
+                             "DBM object has already been closed")
+
+        for meth in (operator.methodcaller('keys'),
+                     operator.methodcaller('iterkeys'),
+                     operator.methodcaller('items'),
+                     len):
+            with self.assertRaises(dumbdbm.error) as cm:
+                meth(f)
+            self.assertEqual(str(cm.exception),
+                             "DBM object has already been closed")
+
     def tearDown(self):
         _delete_files()
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -39,6 +39,9 @@
 Library
 -------
 
+- Issue #19385: Make operations on a closed dbm.dumb database always raise the
+  same exception.
+
 - Issue #21207: Detect when the os.urandom cached fd has been closed or
   replaced, and open it anew.
 

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


More information about the Python-checkins mailing list