]> granicus.if.org Git - python/commitdiff
Issue #21708: Deprecated dbm.dumb behavior that differs from common dbm
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 6 Jul 2016 09:21:58 +0000 (12:21 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Wed, 6 Jul 2016 09:21:58 +0000 (12:21 +0300)
behavior: creating a database in 'r' and 'w' modes and modifying a database
in 'r' mode.

Doc/library/dbm.rst
Doc/whatsnew/3.6.rst
Lib/dbm/dumb.py
Lib/test/test_dbm_dumb.py
Misc/NEWS

index 2a1db914278398f533eefc619071eca241720628..32e80b2cf6ed222fc822cb69b2b6d26ec40e60b6 100644 (file)
@@ -351,6 +351,10 @@ The module defines the following:
       :func:`.open` always creates a new database when the flag has the value
       ``'n'``.
 
+   .. deprecated-removed:: 3.6 3.8
+      Creating database in ``'r'`` and ``'w'`` modes.  Modifying database in
+      ``'r'`` mode.
+
    In addition to the methods provided by the
    :class:`collections.abc.MutableMapping` class, :class:`dumbdbm` objects
    provide the following methods:
index 1550eef93a1a6fab57a7fe0bfab616922d1c634e..e13800cb6e8a5be7a4dcf50ea9b7a2fe65cf0961 100644 (file)
@@ -604,6 +604,11 @@ Deprecated features
   ``__package__`` are not defined now raises an :exc:`ImportWarning`.
   (Contributed by Rose Ames in :issue:`25791`.)
 
+* Unlike to other :mod:`dbm` implementations, the :mod:`dbm.dumb` module
+  creates database in ``'r'`` and ``'w'`` modes if it doesn't exist and
+  allows modifying database in ``'r'`` mode.  This behavior is now deprecated
+  and will be removed in 3.8.
+  (Contributed by Serhiy Storchaka in :issue:`21708`.)
 
 Deprecated Python behavior
 --------------------------
index 7777a7cae67d0f17805fe06aa36af05525d41ced..e7c6440ee65bada15f889aa7af371faa2ec38d5e 100644 (file)
@@ -47,6 +47,7 @@ class _Database(collections.MutableMapping):
 
     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)
@@ -80,6 +81,11 @@ class _Database(collections.MutableMapping):
         try:
             f = _io.open(self._datfile, 'r', encoding="Latin-1")
         except OSError:
+            if flag not in ('c', 'n'):
+                import warnings
+                warnings.warn("The database file is missing, the "
+                              "semantics of the 'c' flag will be used.",
+                              DeprecationWarning, stacklevel=4)
             with _io.open(self._datfile, 'w', encoding="Latin-1") as f:
                 self._chmod(self._datfile)
         else:
@@ -178,6 +184,10 @@ class _Database(collections.MutableMapping):
             f.write("%r, %r\n" % (key.decode("Latin-1"), pos_and_siz_pair))
 
     def __setitem__(self, key, val):
+        if self._readonly:
+            import warnings
+            warnings.warn('The database is opened for reading only',
+                          DeprecationWarning, stacklevel=2)
         if isinstance(key, str):
             key = key.encode('utf-8')
         elif not isinstance(key, (bytes, bytearray)):
@@ -212,6 +222,10 @@ class _Database(collections.MutableMapping):
             # (so that _commit() never gets called).
 
     def __delitem__(self, key):
+        if self._readonly:
+            import warnings
+            warnings.warn('The database is opened for reading only',
+                          DeprecationWarning, stacklevel=2)
         if isinstance(key, str):
             key = key.encode('utf-8')
         self._verify_open()
@@ -300,4 +314,8 @@ def open(file, flag='c', mode=0o666):
     else:
         # Turn off any bits that are set in the umask
         mode = mode & (~um)
+    if flag not in ('r', 'w', 'c', 'n'):
+        import warnings
+        warnings.warn("Flag must be one of 'r', 'w', 'c', or 'n'",
+                      DeprecationWarning, stacklevel=2)
     return _Database(file, mode, flag=flag)
index ff63c88c0bc5c81342c961568b1ed82f315140ff..2d77f078b76b4234653194e8c62339989e7776dd 100644 (file)
@@ -6,6 +6,7 @@ import io
 import operator
 import os
 import unittest
+import warnings
 import dbm.dumb as dumbdbm
 from test import support
 from functools import partial
@@ -78,6 +79,12 @@ class DumbDBMTestCase(unittest.TestCase):
         self.init_db()
         f = dumbdbm.open(_fname, 'r')
         self.read_helper(f)
+        with self.assertWarnsRegex(DeprecationWarning,
+                                   'The database is opened for reading only'):
+            f[b'g'] = b'x'
+        with self.assertWarnsRegex(DeprecationWarning,
+                                   'The database is opened for reading only'):
+            del f[b'a']
         f.close()
 
     def test_dumbdbm_keys(self):
@@ -148,7 +155,7 @@ class DumbDBMTestCase(unittest.TestCase):
             self.assertEqual(self._dict[key], f[key])
 
     def init_db(self):
-        f = dumbdbm.open(_fname, 'w')
+        f = dumbdbm.open(_fname, 'n')
         for k in self._dict:
             f[k] = self._dict[k]
         f.close()
@@ -234,6 +241,24 @@ class DumbDBMTestCase(unittest.TestCase):
                     pass
             self.assertEqual(stdout.getvalue(), '')
 
+    def test_warn_on_ignored_flags(self):
+        for value in ('r', 'w'):
+            _delete_files()
+            with self.assertWarnsRegex(DeprecationWarning,
+                                       "The database file is missing, the "
+                                       "semantics of the 'c' flag will "
+                                       "be used."):
+                f = dumbdbm.open(_fname, value)
+            f.close()
+
+    def test_invalid_flag(self):
+        for flag in ('x', 'rf', None):
+            with self.assertWarnsRegex(DeprecationWarning,
+                                       "Flag must be one of "
+                                       "'r', 'w', 'c', or 'n'"):
+                f = dumbdbm.open(_fname, flag)
+            f.close()
+
     def tearDown(self):
         _delete_files()
 
index c9a78d085dcca6e4e390a4f14982fd3b2a1099c0..fa5d7261fcbf3cfd5ffd2f72efba304bcf5704e0 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -24,6 +24,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #21708: Deprecated dbm.dumb behavior that differs from common dbm
+  behavior: creating a database in 'r' and 'w' modes and modifying a database
+  in 'r' mode.
+
 - Issue #26721: Change the socketserver.StreamRequestHandler.wfile attribute
   to implement BufferedIOBase. In particular, the write() method no longer
   does partial writes.