Commit d96619c1 authored by Serhiy Storchaka's avatar Serhiy Storchaka

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

parent 94cbcb91
...@@ -160,6 +160,9 @@ available for subclassing as well: ...@@ -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
......
...@@ -872,8 +872,7 @@ are always available. They are listed here in alphabetical order. ...@@ -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. ...@@ -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)
......
...@@ -234,6 +234,9 @@ ZipFile Objects ...@@ -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)
......
...@@ -62,8 +62,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, ...@@ -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, ...@@ -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, ...@@ -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")
......
...@@ -222,6 +222,10 @@ class FileInput: ...@@ -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:
......
...@@ -103,7 +103,7 @@ def source_from_cache(path): ...@@ -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): ...@@ -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)
......
...@@ -165,7 +165,7 @@ class ImportTests(unittest.TestCase): ...@@ -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)
......
...@@ -1117,6 +1117,10 @@ class ZipFile: ...@@ -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:
......
...@@ -68,6 +68,8 @@ Core and Builtins ...@@ -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.
......
...@@ -126,8 +126,7 @@ PyDoc_STRVAR(open_doc, ...@@ -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, ...@@ -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) ...@@ -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;
} }
......
...@@ -24,6 +24,8 @@ def text_open(fn, mode, encoding=None): ...@@ -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(): ...@@ -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
......
...@@ -38,9 +38,9 @@ def main(): ...@@ -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:
......
...@@ -60,7 +60,7 @@ def fail(msg): ...@@ -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))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment