Issue #15204: Deprecated the 'U' mode in file-like objects.

This commit is contained in:
Serhiy Storchaka 2013-11-23 22:12:06 +02:00
parent d41c343f28
commit 6787a3806e
13 changed files with 45 additions and 13 deletions

View File

@ -160,6 +160,9 @@ available for subclassing as well:
.. versionchanged:: 3.2 .. versionchanged:: 3.2
Can be used as a context manager. Can be used as a context manager.
.. deprecated:: 3.4
The ``'rU'`` and ``'U'`` modes.
**Optional in-place filtering:** if the keyword argument ``inplace=True`` is **Optional in-place filtering:** if the keyword argument ``inplace=True`` is
passed to :func:`fileinput.input` or to the :class:`FileInput` constructor, the passed to :func:`fileinput.input` or to the :class:`FileInput` constructor, the

View File

@ -872,8 +872,7 @@ are always available. They are listed here in alphabetical order.
``'b'`` binary mode ``'b'`` binary mode
``'t'`` text mode (default) ``'t'`` text mode (default)
``'+'`` open a disk file for updating (reading and writing) ``'+'`` open a disk file for updating (reading and writing)
``'U'`` universal newlines mode (for backwards compatibility; should ``'U'`` :term:`universal newlines` mode (deprecated)
not be used in new code)
========= =============================================================== ========= ===============================================================
The default mode is ``'r'`` (open for reading text, synonym of ``'rt'``). The default mode is ``'r'`` (open for reading text, synonym of ``'rt'``).
@ -1029,6 +1028,9 @@ are always available. They are listed here in alphabetical order.
.. versionchanged:: 3.4 .. versionchanged:: 3.4
The file is now non-inheritable. The file is now non-inheritable.
.. deprecated-removed:: 3.4 4.0
The ``'U'`` mode.
.. XXX works for bytes too, but should it? .. XXX works for bytes too, but should it?
.. function:: ord(c) .. function:: ord(c)

View File

@ -234,6 +234,9 @@ ZipFile Objects
or a :class:`ZipInfo` object. You will appreciate this when trying to read a or a :class:`ZipInfo` object. You will appreciate this when trying to read a
ZIP file that contains members with duplicate names. ZIP file that contains members with duplicate names.
.. deprecated-removed:: 3.4 3.6
The ``'U'`` or ``'rU'`` mode. Use :class:`io.TextIOWrapper` for reading
compressed text files in :term:`universal newlines` mode.
.. method:: ZipFile.extract(member, path=None, pwd=None) .. method:: ZipFile.extract(member, path=None, pwd=None)

View File

@ -62,8 +62,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
'b' binary mode 'b' binary mode
't' text mode (default) 't' text mode (default)
'+' open a disk file for updating (reading and writing) '+' open a disk file for updating (reading and writing)
'U' universal newline mode (for backwards compatibility; unneeded 'U' universal newline mode (deprecated)
for new code)
========= =============================================================== ========= ===============================================================
The default mode is 'rt' (open for reading text). For binary random The default mode is 'rt' (open for reading text). For binary random
@ -79,6 +78,10 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
returned as strings, the bytes having been first decoded using a returned as strings, the bytes having been first decoded using a
platform-dependent encoding or using the specified encoding if given. platform-dependent encoding or using the specified encoding if given.
'U' mode is deprecated and will raise an exception in future versions
of Python. It has no effect in Python 3. Use newline to control
universal newlines mode.
buffering is an optional integer used to set the buffering policy. buffering is an optional integer used to set the buffering policy.
Pass 0 to switch buffering off (only allowed in binary mode), 1 to select Pass 0 to switch buffering off (only allowed in binary mode), 1 to select
line buffering (only usable in text mode), and an integer > 1 to indicate line buffering (only usable in text mode), and an integer > 1 to indicate
@ -174,6 +177,9 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
if "U" in modes: if "U" in modes:
if creating or writing or appending: if creating or writing or appending:
raise ValueError("can't use U and writing mode at once") raise ValueError("can't use U and writing mode at once")
import warnings
warnings.warn("'U' mode is deprecated",
DeprecationWarning, 2)
reading = True reading = True
if text and binary: if text and binary:
raise ValueError("can't have text and binary mode at once") raise ValueError("can't have text and binary mode at once")

View File

@ -222,6 +222,10 @@ class FileInput:
if mode not in ('r', 'rU', 'U', 'rb'): if mode not in ('r', 'rU', 'U', 'rb'):
raise ValueError("FileInput opening mode must be one of " raise ValueError("FileInput opening mode must be one of "
"'r', 'rU', 'U' and 'rb'") "'r', 'rU', 'U' and 'rb'")
if 'U' in mode:
import warnings
warnings.warn("Use of 'U' mode is deprecated",
DeprecationWarning, 2)
self._mode = mode self._mode = mode
if openhook: if openhook:
if inplace: if inplace:

View File

@ -103,7 +103,7 @@ def source_from_cache(path):
def get_suffixes(): def get_suffixes():
"""**DEPRECATED**""" """**DEPRECATED**"""
extensions = [(s, 'rb', C_EXTENSION) for s in machinery.EXTENSION_SUFFIXES] extensions = [(s, 'rb', C_EXTENSION) for s in machinery.EXTENSION_SUFFIXES]
source = [(s, 'U', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES] source = [(s, 'r', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES]
bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES] bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES]
return extensions + source + bytecode return extensions + source + bytecode
@ -297,7 +297,7 @@ def find_module(name, path=None):
raise ImportError(_ERR_MSG.format(name), name=name) raise ImportError(_ERR_MSG.format(name), name=name)
encoding = None encoding = None
if mode == 'U': if 'b' not in mode:
with open(file_path, 'rb') as file: with open(file_path, 'rb') as file:
encoding = tokenize.detect_encoding(file.readline)[0] encoding = tokenize.detect_encoding(file.readline)[0]
file = open(file_path, mode, encoding=encoding) file = open(file_path, mode, encoding=encoding)

View File

@ -165,7 +165,7 @@ class ImportTests(unittest.TestCase):
self.assertIsNotNone(file) self.assertIsNotNone(file)
self.assertTrue(filename[:-3].endswith(temp_mod_name)) self.assertTrue(filename[:-3].endswith(temp_mod_name))
self.assertEqual(info[0], '.py') self.assertEqual(info[0], '.py')
self.assertEqual(info[1], 'U') self.assertEqual(info[1], 'r')
self.assertEqual(info[2], imp.PY_SOURCE) self.assertEqual(info[2], imp.PY_SOURCE)
mod = imp.load_module(temp_mod_name, file, filename, info) mod = imp.load_module(temp_mod_name, file, filename, info)

View File

@ -1117,6 +1117,10 @@ class ZipFile:
"""Return file-like object for 'name'.""" """Return file-like object for 'name'."""
if mode not in ("r", "U", "rU"): if mode not in ("r", "U", "rU"):
raise RuntimeError('open() requires mode "r", "U", or "rU"') raise RuntimeError('open() requires mode "r", "U", or "rU"')
if 'U' in mode:
import warnings
warnings.warn("'U' mode is deprecated",
DeprecationWarning, 2)
if pwd and not isinstance(pwd, bytes): if pwd and not isinstance(pwd, bytes):
raise TypeError("pwd: expected bytes, got %s" % type(pwd)) raise TypeError("pwd: expected bytes, got %s" % type(pwd))
if not self.fp: if not self.fp:

View File

@ -68,6 +68,8 @@ Core and Builtins
Library Library
------- -------
- Issue #15204: Deprecated the 'U' mode in file-like objects.
- Issue #17810: Implement PEP 3154, pickle protocol 4. - Issue #17810: Implement PEP 3154, pickle protocol 4.
- Issue #19668: Added support for the cp1125 encoding. - Issue #19668: Added support for the cp1125 encoding.

View File

@ -126,8 +126,7 @@ PyDoc_STRVAR(open_doc,
"'b' binary mode\n" "'b' binary mode\n"
"'t' text mode (default)\n" "'t' text mode (default)\n"
"'+' open a disk file for updating (reading and writing)\n" "'+' open a disk file for updating (reading and writing)\n"
"'U' universal newline mode (for backwards compatibility; unneeded\n" "'U' universal newline mode (deprecated)\n"
" for new code)\n"
"========= ===============================================================\n" "========= ===============================================================\n"
"\n" "\n"
"The default mode is 'rt' (open for reading text). For binary random\n" "The default mode is 'rt' (open for reading text). For binary random\n"
@ -143,6 +142,10 @@ PyDoc_STRVAR(open_doc,
"returned as strings, the bytes having been first decoded using a\n" "returned as strings, the bytes having been first decoded using a\n"
"platform-dependent encoding or using the specified encoding if given.\n" "platform-dependent encoding or using the specified encoding if given.\n"
"\n" "\n"
"'U' mode is deprecated and will raise an exception in future versions\n"
"of Python. It has no effect in Python 3. Use newline to control\n"
"universal newlines mode.\n"
"\n"
"buffering is an optional integer used to set the buffering policy.\n" "buffering is an optional integer used to set the buffering policy.\n"
"Pass 0 to switch buffering off (only allowed in binary mode), 1 to select\n" "Pass 0 to switch buffering off (only allowed in binary mode), 1 to select\n"
"line buffering (only usable in text mode), and an integer > 1 to indicate\n" "line buffering (only usable in text mode), and an integer > 1 to indicate\n"
@ -310,6 +313,9 @@ io_open(PyObject *self, PyObject *args, PyObject *kwds)
"can't use U and writing mode at once"); "can't use U and writing mode at once");
return NULL; return NULL;
} }
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"'U' mode is deprecated", 1) < 0)
return NULL;
reading = 1; reading = 1;
} }

View File

@ -24,6 +24,8 @@ def text_open(fn, mode, encoding=None):
try: try:
return open(fn, mode, encoding=encoding or TEXT_ENCODING) return open(fn, mode, encoding=encoding or TEXT_ENCODING)
except TypeError: except TypeError:
if 'r' in mode:
mode += 'U' # 'U' mode is needed only in Python 2.x
return open(fn, mode) return open(fn, mode)
def get_file_sizes(): def get_file_sizes():
@ -380,7 +382,7 @@ def prepare_files():
f.write(os.urandom(size)) f.write(os.urandom(size))
# Text files # Text files
chunk = [] chunk = []
with text_open(__file__, "rU", encoding='utf8') as f: with text_open(__file__, "r", encoding='utf8') as f:
for line in f: for line in f:
if line.startswith("# <iobench text chunk marker>"): if line.startswith("# <iobench text chunk marker>"):
break break

View File

@ -38,9 +38,9 @@ def main():
fromdate = file_mtime(fromfile) fromdate = file_mtime(fromfile)
todate = file_mtime(tofile) todate = file_mtime(tofile)
with open(fromfile, 'U') as ff: with open(fromfile) as ff:
fromlines = ff.readlines() fromlines = ff.readlines()
with open(tofile, 'U') as tf: with open(tofile) as tf:
tolines = tf.readlines() tolines = tf.readlines()
if options.u: if options.u:

View File

@ -60,7 +60,7 @@ def fail(msg):
# couldn't be opened # couldn't be opened
def fopen(fname): def fopen(fname):
try: try:
return open(fname, 'U') return open(fname)
except IOError as detail: except IOError as detail:
return fail("couldn't open " + fname + ": " + str(detail)) return fail("couldn't open " + fname + ": " + str(detail))