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.
This commit is contained in:
parent
9862b5194d
commit
0122ae9ac8
|
@ -351,6 +351,10 @@ The module defines the following:
|
||||||
:func:`.open` always creates a new database when the flag has the value
|
:func:`.open` always creates a new database when the flag has the value
|
||||||
``'n'``.
|
``'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
|
In addition to the methods provided by the
|
||||||
:class:`collections.abc.MutableMapping` class, :class:`dumbdbm` objects
|
:class:`collections.abc.MutableMapping` class, :class:`dumbdbm` objects
|
||||||
provide the following methods:
|
provide the following methods:
|
||||||
|
|
|
@ -604,6 +604,11 @@ Deprecated features
|
||||||
``__package__`` are not defined now raises an :exc:`ImportWarning`.
|
``__package__`` are not defined now raises an :exc:`ImportWarning`.
|
||||||
(Contributed by Rose Ames in :issue:`25791`.)
|
(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
|
Deprecated Python behavior
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
|
@ -47,6 +47,7 @@ class _Database(collections.MutableMapping):
|
||||||
|
|
||||||
def __init__(self, filebasename, mode, flag='c'):
|
def __init__(self, filebasename, mode, flag='c'):
|
||||||
self._mode = mode
|
self._mode = mode
|
||||||
|
self._readonly = (flag == 'r')
|
||||||
|
|
||||||
# The directory file is a text file. Each line looks like
|
# The directory file is a text file. Each line looks like
|
||||||
# "%r, (%d, %d)\n" % (key, pos, siz)
|
# "%r, (%d, %d)\n" % (key, pos, siz)
|
||||||
|
@ -80,6 +81,11 @@ class _Database(collections.MutableMapping):
|
||||||
try:
|
try:
|
||||||
f = _io.open(self._datfile, 'r', encoding="Latin-1")
|
f = _io.open(self._datfile, 'r', encoding="Latin-1")
|
||||||
except OSError:
|
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:
|
with _io.open(self._datfile, 'w', encoding="Latin-1") as f:
|
||||||
self._chmod(self._datfile)
|
self._chmod(self._datfile)
|
||||||
else:
|
else:
|
||||||
|
@ -178,6 +184,10 @@ class _Database(collections.MutableMapping):
|
||||||
f.write("%r, %r\n" % (key.decode("Latin-1"), pos_and_siz_pair))
|
f.write("%r, %r\n" % (key.decode("Latin-1"), pos_and_siz_pair))
|
||||||
|
|
||||||
def __setitem__(self, key, val):
|
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):
|
if isinstance(key, str):
|
||||||
key = key.encode('utf-8')
|
key = key.encode('utf-8')
|
||||||
elif not isinstance(key, (bytes, bytearray)):
|
elif not isinstance(key, (bytes, bytearray)):
|
||||||
|
@ -212,6 +222,10 @@ class _Database(collections.MutableMapping):
|
||||||
# (so that _commit() never gets called).
|
# (so that _commit() never gets called).
|
||||||
|
|
||||||
def __delitem__(self, key):
|
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):
|
if isinstance(key, str):
|
||||||
key = key.encode('utf-8')
|
key = key.encode('utf-8')
|
||||||
self._verify_open()
|
self._verify_open()
|
||||||
|
@ -300,4 +314,8 @@ def open(file, flag='c', mode=0o666):
|
||||||
else:
|
else:
|
||||||
# Turn off any bits that are set in the umask
|
# Turn off any bits that are set in the umask
|
||||||
mode = mode & (~um)
|
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)
|
return _Database(file, mode, flag=flag)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import io
|
||||||
import operator
|
import operator
|
||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
import dbm.dumb as dumbdbm
|
import dbm.dumb as dumbdbm
|
||||||
from test import support
|
from test import support
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
@ -78,6 +79,12 @@ class DumbDBMTestCase(unittest.TestCase):
|
||||||
self.init_db()
|
self.init_db()
|
||||||
f = dumbdbm.open(_fname, 'r')
|
f = dumbdbm.open(_fname, 'r')
|
||||||
self.read_helper(f)
|
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()
|
f.close()
|
||||||
|
|
||||||
def test_dumbdbm_keys(self):
|
def test_dumbdbm_keys(self):
|
||||||
|
@ -148,7 +155,7 @@ class DumbDBMTestCase(unittest.TestCase):
|
||||||
self.assertEqual(self._dict[key], f[key])
|
self.assertEqual(self._dict[key], f[key])
|
||||||
|
|
||||||
def init_db(self):
|
def init_db(self):
|
||||||
f = dumbdbm.open(_fname, 'w')
|
f = dumbdbm.open(_fname, 'n')
|
||||||
for k in self._dict:
|
for k in self._dict:
|
||||||
f[k] = self._dict[k]
|
f[k] = self._dict[k]
|
||||||
f.close()
|
f.close()
|
||||||
|
@ -234,6 +241,24 @@ class DumbDBMTestCase(unittest.TestCase):
|
||||||
pass
|
pass
|
||||||
self.assertEqual(stdout.getvalue(), '')
|
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):
|
def tearDown(self):
|
||||||
_delete_files()
|
_delete_files()
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,10 @@ Core and Builtins
|
||||||
Library
|
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
|
- Issue #26721: Change the socketserver.StreamRequestHandler.wfile attribute
|
||||||
to implement BufferedIOBase. In particular, the write() method no longer
|
to implement BufferedIOBase. In particular, the write() method no longer
|
||||||
does partial writes.
|
does partial writes.
|
||||||
|
|
Loading…
Reference in New Issue