summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2016-07-06 09:21:58 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2016-07-06 09:21:58 (GMT)
commit0122ae9ac83afcad234aac80f77f90afabe342ea (patch)
treed0f671e0007eb5b1a785108aa37db5619b25e44d
parent9862b5194d5aa8f788d3fd38a3951d7d25d91352 (diff)
downloadcpython-0122ae9ac83afcad234aac80f77f90afabe342ea.zip
cpython-0122ae9ac83afcad234aac80f77f90afabe342ea.tar.gz
cpython-0122ae9ac83afcad234aac80f77f90afabe342ea.tar.bz2
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.
-rw-r--r--Doc/library/dbm.rst4
-rw-r--r--Doc/whatsnew/3.6.rst5
-rw-r--r--Lib/dbm/dumb.py18
-rw-r--r--Lib/test/test_dbm_dumb.py27
-rw-r--r--Misc/NEWS4
5 files changed, 57 insertions, 1 deletions
diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst
index 2a1db91..32e80b2 100644
--- a/Doc/library/dbm.rst
+++ b/Doc/library/dbm.rst
@@ -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:
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
index 1550eef..e13800c 100644
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -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
--------------------------
diff --git a/Lib/dbm/dumb.py b/Lib/dbm/dumb.py
index 7777a7c..e7c6440 100644
--- a/Lib/dbm/dumb.py
+++ b/Lib/dbm/dumb.py
@@ -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)
diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py
index ff63c88..2d77f07 100644
--- a/Lib/test/test_dbm_dumb.py
+++ b/Lib/test/test_dbm_dumb.py
@@ -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()
diff --git a/Misc/NEWS b/Misc/NEWS
index c9a78d0..fa5d726 100644
--- 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.