Skip to content

bpo-40937: Remove deprecated universal mode #20775

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Doc/library/fileinput.rst
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ available for subclassing as well:
and :meth:`~io.TextIOBase.readline` cannot be mixed.

With *mode* you can specify which file mode will be passed to :func:`open`. It
must be one of ``'r'``, ``'rU'``, ``'U'`` and ``'rb'``.
must be one of ``'r'`` and ``'rb'``.

The *openhook*, when given, must be a function that takes two arguments,
*filename* and *mode*, and returns an accordingly opened file-like object. You
Expand All @@ -175,6 +175,8 @@ available for subclassing as well:
.. versionchanged:: 3.8
The keyword parameter *mode* and *openhook* are now keyword-only.

.. versionchanged:: 3.10
The ``'rU'`` and ``'U'`` modes have been removed.


**Optional in-place filtering:** if the keyword argument ``inplace=True`` is
Expand Down
10 changes: 0 additions & 10 deletions Doc/library/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1089,12 +1089,6 @@ are always available. They are listed here in alphabetical order.
first decoded using a platform-dependent encoding or using the specified
*encoding* if given.

There is an additional mode character permitted, ``'U'``, which no longer
has any effect, and is considered deprecated. It previously enabled
:term:`universal newlines` in text mode, which became the default behaviour
in Python 3.0. Refer to the documentation of the
:ref:`newline <open-newline-parameter>` parameter for further details.

.. note::

Python doesn't depend on the underlying operating system's notion of text
Expand Down Expand Up @@ -1251,10 +1245,6 @@ are always available. They are listed here in alphabetical order.

* The file is now non-inheritable.

.. deprecated-removed:: 3.4 3.10

The ``'U'`` mode.

.. versionchanged::
3.5

Expand Down
14 changes: 1 addition & 13 deletions Lib/_pyio.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
'b' binary mode
't' text mode (default)
'+' open a disk file for updating (reading and writing)
'U' universal newline mode (deprecated)
========= ===============================================================

The default mode is 'rt' (open for reading text). For binary random
Expand All @@ -87,10 +86,6 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
returned as strings, the bytes having been first decoded using a
platform-dependent encoding or using the specified encoding if given.

'U' mode is deprecated and will raise an exception in future versions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wont let me add a comment to the line as it is too far away from the changes, but shouldn't line 74 also be removed here?

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.
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
Expand Down Expand Up @@ -176,7 +171,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
if errors is not None and not isinstance(errors, str):
raise TypeError("invalid errors: %r" % errors)
modes = set(mode)
if modes - set("axrwb+tU") or len(mode) > len(modes):
if modes - set("axrwb+t") or len(mode) > len(modes):
raise ValueError("invalid mode: %r" % mode)
creating = "x" in modes
reading = "r" in modes
Expand All @@ -185,13 +180,6 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
updating = "+" in modes
text = "t" in modes
binary = "b" in modes
if "U" in modes:
if creating or writing or appending or updating:
raise ValueError("mode U cannot be combined with 'x', 'w', 'a', or '+'")
import warnings
warnings.warn("'U' mode is deprecated",
DeprecationWarning, 2)
reading = True
if text and binary:
raise ValueError("can't have text and binary mode at once")
if creating + reading + writing + appending > 1:
Expand Down
10 changes: 3 additions & 7 deletions Lib/fileinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,11 @@ def __init__(self, files=None, inplace=False, backup="", *,
self._isstdin = False
self._backupfilename = None
# restrict mode argument to reading modes
if mode not in ('r', 'rU', 'U', 'rb'):
if mode not in ('r', 'rb'):
raise ValueError("FileInput opening mode must be one of "
"'r', 'rU', 'U' and 'rb'")
if 'U' in mode:
import warnings
warnings.warn("'U' mode is deprecated",
DeprecationWarning, 2)
"'r' and 'rb'")
self._mode = mode
self._write_mode = mode.replace('r', 'w') if 'U' not in mode else 'w'
self._write_mode = mode.replace('r', 'w')
if openhook:
if inplace:
raise ValueError("FileInput cannot use an opening hook in inplace mode")
Expand Down
2 changes: 1 addition & 1 deletion Lib/gzip.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def __init__(self, filename=None, mode=None,

"""

if mode and ('t' in mode or 'U' in mode):
if mode and 't' in mode:
raise ValueError("Invalid mode: {!r}".format(mode))
if mode and 'b' not in mode:
mode += 'b'
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_codecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,8 +712,7 @@ def test_bug691291(self):
self.addCleanup(support.unlink, support.TESTFN)
with open(support.TESTFN, 'wb') as fp:
fp.write(s)
with support.check_warnings(('', DeprecationWarning)):
reader = codecs.open(support.TESTFN, 'U', encoding=self.encoding)
reader = codecs.open(support.TESTFN, encoding=self.encoding)
with reader:
self.assertEqual(reader.read(), s1)

Expand Down
11 changes: 3 additions & 8 deletions Lib/test/test_fileinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,8 @@ def test_opening_mode(self):
pass
# try opening in universal newline mode
t1 = self.writeTmp(b"A\nB\r\nC\rD", mode="wb")
with check_warnings(('', DeprecationWarning)):
fi = FileInput(files=t1, mode="U")
with check_warnings(('', DeprecationWarning)):
lines = list(fi)
fi = FileInput(files=t1)
lines = list(fi)
self.assertEqual(lines, ["A\n", "B\n", "C\n", "D"])

def test_stdin_binary_mode(self):
Expand Down Expand Up @@ -985,10 +983,7 @@ def check(mode, expected_lines):
self.assertEqual(lines, expected_lines)

check('r', ['A\n', 'B\n', 'C\n', 'D\u20ac'])
with self.assertWarns(DeprecationWarning):
check('rU', ['A\n', 'B\n', 'C\n', 'D\u20ac'])
with self.assertWarns(DeprecationWarning):
check('U', ['A\n', 'B\n', 'C\n', 'D\u20ac'])
check('r', ['A\n', 'B\n', 'C\n', 'D\u20ac'])
with self.assertRaises(ValueError):
check('rb', ['A\n', 'B\r\n', 'C\r', 'D\u20ac'])

Expand Down
10 changes: 0 additions & 10 deletions Lib/test/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -3901,16 +3901,6 @@ def test_attributes(self):
self.assertEqual(f.mode, "wb")
f.close()

with support.check_warnings(('', DeprecationWarning)):
f = self.open(support.TESTFN, "U")
self.assertEqual(f.name, support.TESTFN)
self.assertEqual(f.buffer.name, support.TESTFN)
self.assertEqual(f.buffer.raw.name, support.TESTFN)
self.assertEqual(f.mode, "U")
self.assertEqual(f.buffer.mode, "rb")
self.assertEqual(f.buffer.raw.mode, "rb")
f.close()

f = self.open(support.TESTFN, "w+")
self.assertEqual(f.mode, "w+")
self.assertEqual(f.buffer.mode, "rb+") # Does it really matter?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The ``'U'`` character mode, deprecated since Python 3.4 and replaced by the
``newline`` argument, has been removed. Pach contributed by Rémi Lapeyre.
26 changes: 2 additions & 24 deletions Modules/_io/_iomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ Character Meaning
'b' binary mode
't' text mode (default)
'+' open a disk file for updating (reading and writing)
'U' universal newline mode (deprecated)
========= ===============================================================

The default mode is 'rt' (open for reading text). For binary random
Expand All @@ -152,10 +151,6 @@ bytes objects without any decoding. In text mode (the default, or when
returned as strings, the bytes having been first decoded using a
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.
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
Expand Down Expand Up @@ -231,12 +226,12 @@ static PyObject *
_io_open_impl(PyObject *module, PyObject *file, const char *mode,
int buffering, const char *encoding, const char *errors,
const char *newline, int closefd, PyObject *opener)
/*[clinic end generated code: output=aefafc4ce2b46dc0 input=7295902222e6b311]*/
/*[clinic end generated code: output=aefafc4ce2b46dc0 input=1543f4511d2356a5]*/
{
unsigned i;

int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0;
int text = 0, binary = 0, universal = 0;
int text = 0, binary = 0;

char rawmode[6], *m;
int line_buffering, is_number;
Expand Down Expand Up @@ -294,10 +289,6 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
case 'b':
binary = 1;
break;
case 'U':
universal = 1;
reading = 1;
break;
default:
goto invalid_mode;
}
Expand All @@ -319,19 +310,6 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
if (updating) *(m++) = '+';
*m = '\0';

/* Parameters validation */
if (universal) {
if (creating || writing || appending || updating) {
PyErr_SetString(PyExc_ValueError,
"mode U cannot be combined with 'x', 'w', 'a', or '+'");
goto error;
}
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"'U' mode is deprecated", 1) < 0)
goto error;
reading = 1;
}

if (text && binary) {
PyErr_SetString(PyExc_ValueError,
"can't have text and binary mode at once");
Expand Down
7 changes: 1 addition & 6 deletions Modules/_io/clinic/_iomodule.c.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ PyDoc_STRVAR(_io_open__doc__,
"\'b\' binary mode\n"
"\'t\' text mode (default)\n"
"\'+\' open a disk file for updating (reading and writing)\n"
"\'U\' universal newline mode (deprecated)\n"
"========= ===============================================================\n"
"\n"
"The default mode is \'rt\' (open for reading text). For binary random\n"
Expand All @@ -52,10 +51,6 @@ PyDoc_STRVAR(_io_open__doc__,
"returned as strings, the bytes having been first decoded using a\n"
"platform-dependent encoding or using the specified encoding if given.\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"
"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"
Expand Down Expand Up @@ -313,4 +308,4 @@ _io_open_code(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObjec
exit:
return return_value;
}
/*[clinic end generated code: output=5c0dd7a262c30ebc input=a9049054013a1b77]*/
/*[clinic end generated code: output=3b1b8dc1fc8bcaae input=a9049054013a1b77]*/