summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/dbm.rst27
-rw-r--r--Doc/whatsnew/3.8.rst5
-rw-r--r--Lib/dbm/dumb.py26
-rw-r--r--Lib/test/test_dbm_dumb.py35
-rw-r--r--Misc/NEWS.d/next/Library/2018-02-02-17-21-24.bpo-32749.u5scIn.rst3
5 files changed, 50 insertions, 46 deletions
diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst
index 32e80b2..1abc36c 100644
--- a/Doc/library/dbm.rst
+++ b/Doc/library/dbm.rst
@@ -339,9 +339,23 @@ The module defines the following:
dumbdbm database is created, files with :file:`.dat` and :file:`.dir` extensions
are created.
- The optional *flag* argument supports only the semantics of ``'c'``
- and ``'n'`` values. Other values will default to database being always
- opened for update, and will be created if it does not exist.
+ The optional *flag* argument can be:
+
+ +---------+-------------------------------------------+
+ | Value | Meaning |
+ +=========+===========================================+
+ | ``'r'`` | Open existing database for reading only |
+ | | (default) |
+ +---------+-------------------------------------------+
+ | ``'w'`` | Open existing database for reading and |
+ | | writing |
+ +---------+-------------------------------------------+
+ | ``'c'`` | Open database for reading and writing, |
+ | | creating it if it doesn't exist |
+ +---------+-------------------------------------------+
+ | ``'n'`` | Always create a new, empty database, open |
+ | | for reading and writing |
+ +---------+-------------------------------------------+
The optional *mode* argument is the Unix mode of the file, used only when the
database has to be created. It defaults to octal ``0o666`` (and will be modified
@@ -351,9 +365,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.
+ .. versionchanged:: 3.8
+ A database opened with flags ``'r'`` is now read-only. Opening with
+ flags ``'r'`` and ``'w'`` no longer creates a database if it does not
+ exist.
In addition to the methods provided by the
:class:`collections.abc.MutableMapping` class, :class:`dumbdbm` objects
diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst
index c4063ad..60f54a0 100644
--- a/Doc/whatsnew/3.8.rst
+++ b/Doc/whatsnew/3.8.rst
@@ -130,3 +130,8 @@ Changes in the Python API
arguments for changing the selection was deprecated in Python 3.6. Use
specialized methods like :meth:`~tkinter.ttk.Treeview.selection_set` for
changing the selection. (Contributed by Serhiy Storchaka in :issue:`31508`.)
+
+* A :mod:`dbm.dumb` database opened with flags ``'r'`` is now read-only.
+ :func:`dbm.dumb.open` with flags ``'r'`` and ``'w'`` no longer creates
+ a database if it does not exist.
+ (Contributed by Serhiy Storchaka in :issue:`32749`.)
diff --git a/Lib/dbm/dumb.py b/Lib/dbm/dumb.py
index 5064668..e5c17f5 100644
--- a/Lib/dbm/dumb.py
+++ b/Lib/dbm/dumb.py
@@ -82,10 +82,7 @@ class _Database(collections.abc.MutableMapping):
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)
+ raise
with _io.open(self._datfile, 'w', encoding="Latin-1") as f:
self._chmod(self._datfile)
else:
@@ -93,18 +90,15 @@ class _Database(collections.abc.MutableMapping):
# Read directory file into the in-memory index dict.
def _update(self, flag):
+ self._modified = False
self._index = {}
try:
f = _io.open(self._dirfile, 'r', encoding="Latin-1")
except OSError:
- self._modified = not self._readonly
if flag not in ('c', 'n'):
- import warnings
- warnings.warn("The index file is missing, the "
- "semantics of the 'c' flag will be used.",
- DeprecationWarning, stacklevel=4)
+ raise
+ self._modified = True
else:
- self._modified = False
with f:
for line in f:
line = line.rstrip()
@@ -191,9 +185,7 @@ class _Database(collections.abc.MutableMapping):
def __setitem__(self, key, val):
if self._readonly:
- import warnings
- warnings.warn('The database is opened for reading only',
- DeprecationWarning, stacklevel=2)
+ raise ValueError('The database is opened for reading only')
if isinstance(key, str):
key = key.encode('utf-8')
elif not isinstance(key, (bytes, bytearray)):
@@ -230,9 +222,7 @@ class _Database(collections.abc.MutableMapping):
def __delitem__(self, key):
if self._readonly:
- import warnings
- warnings.warn('The database is opened for reading only',
- DeprecationWarning, stacklevel=2)
+ raise ValueError('The database is opened for reading only')
if isinstance(key, str):
key = key.encode('utf-8')
self._verify_open()
@@ -323,7 +313,5 @@ def open(file, flag='c', mode=0o666):
# 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)
+ raise ValueError("Flag must be one of 'r', 'w', 'c', or 'n'")
return _Database(file, mode, flag=flag)
diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py
index 73f2a32..21f29af 100644
--- a/Lib/test/test_dbm_dumb.py
+++ b/Lib/test/test_dbm_dumb.py
@@ -79,10 +79,10 @@ class DumbDBMTestCase(unittest.TestCase):
self.init_db()
f = dumbdbm.open(_fname, 'r')
self.read_helper(f)
- with self.assertWarnsRegex(DeprecationWarning,
+ with self.assertRaisesRegex(ValueError,
'The database is opened for reading only'):
f[b'g'] = b'x'
- with self.assertWarnsRegex(DeprecationWarning,
+ with self.assertRaisesRegex(ValueError,
'The database is opened for reading only'):
del f[b'a']
f.close()
@@ -241,37 +241,30 @@ class DumbDBMTestCase(unittest.TestCase):
pass
self.assertEqual(stdout.getvalue(), '')
- def test_warn_on_ignored_flags(self):
+ def test_missing_data(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()
+ with self.assertRaises(FileNotFoundError):
+ dumbdbm.open(_fname, value)
+ self.assertFalse(os.path.exists(_fname + '.dir'))
+ self.assertFalse(os.path.exists(_fname + '.bak'))
def test_missing_index(self):
with dumbdbm.open(_fname, 'n') as f:
pass
os.unlink(_fname + '.dir')
for value in ('r', 'w'):
- with self.assertWarnsRegex(DeprecationWarning,
- "The index file is missing, the "
- "semantics of the 'c' flag will "
- "be used."):
- f = dumbdbm.open(_fname, value)
- f.close()
- self.assertEqual(os.path.exists(_fname + '.dir'), value == 'w')
+ with self.assertRaises(FileNotFoundError):
+ dumbdbm.open(_fname, value)
+ self.assertFalse(os.path.exists(_fname + '.dir'))
self.assertFalse(os.path.exists(_fname + '.bak'))
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()
+ with self.assertRaisesRegex(ValueError,
+ "Flag must be one of "
+ "'r', 'w', 'c', or 'n'"):
+ dumbdbm.open(_fname, flag)
@unittest.skipUnless(hasattr(os, 'chmod'), 'test needs os.chmod()')
def test_readonly_files(self):
diff --git a/Misc/NEWS.d/next/Library/2018-02-02-17-21-24.bpo-32749.u5scIn.rst b/Misc/NEWS.d/next/Library/2018-02-02-17-21-24.bpo-32749.u5scIn.rst
new file mode 100644
index 0000000..9665ff1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-02-02-17-21-24.bpo-32749.u5scIn.rst
@@ -0,0 +1,3 @@
+A :mod:`dbm.dumb` database opened with flags 'r' is now read-only.
+:func:`dbm.dumb.open` with flags 'r' and 'w' no longer creates a database if
+it does not exist.