[Python-checkins] gh-91526: io: Remove device encoding support from TextIOWrapper (GH-91529)

methane webhook-mailer at python.org
Mon Apr 18 22:44:45 EDT 2022


https://github.com/python/cpython/commit/6fdb62b1fa344b9cdf1f221eac83404fb1980822
commit: 6fdb62b1fa344b9cdf1f221eac83404fb1980822
branch: main
author: Inada Naoki <songofacandy at gmail.com>
committer: methane <songofacandy at gmail.com>
date: 2022-04-19T11:44:36+09:00
summary:

gh-91526: io: Remove device encoding support from TextIOWrapper (GH-91529)

`TextIOWrapper.__init__()` called `os.device_encoding(file.fileno())` if fileno is 0-2 and encoding=None.
But it is very rarely works, and never documented behavior.

files:
A Misc/NEWS.d/next/Library/2022-04-14-18-06-00.gh-issue-91526.cwfhSB.rst
M Lib/_pyio.py
M Lib/test/test_io.py
M Modules/_io/textio.c

diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index 0f33ed59492e7..380a7a736c64e 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -2021,14 +2021,6 @@ def __init__(self, buffer, encoding=None, errors=None, newline=None,
         self._check_newline(newline)
         encoding = text_encoding(encoding)
 
-        if encoding == "locale" and sys.platform == "win32":
-            # On Unix, os.device_encoding() returns "utf-8" instead of locale encoding
-            # in the UTF-8 mode. So we use os.device_encoding() only on Windows.
-            try:
-                encoding = os.device_encoding(buffer.fileno()) or "locale"
-            except (AttributeError, UnsupportedOperation):
-                pass
-
         if encoding == "locale":
             try:
                 import locale
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index c86251dfe5734..45bf81b61f416 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -2736,18 +2736,6 @@ def test_default_encoding(self):
             os.environ.clear()
             os.environ.update(old_environ)
 
-    @support.cpython_only
-    @unittest.skipIf(sys.platform != "win32", "Windows-only test")
-    @unittest.skipIf(sys.flags.utf8_mode, "utf-8 mode is enabled")
-    def test_device_encoding(self):
-        # Issue 15989
-        import _testcapi
-        b = self.BytesIO()
-        b.fileno = lambda: _testcapi.INT_MAX + 1
-        self.assertRaises(OverflowError, self.TextIOWrapper, b, encoding="locale")
-        b.fileno = lambda: _testcapi.UINT_MAX + 1
-        self.assertRaises(OverflowError, self.TextIOWrapper, b, encoding="locale")
-
     def test_encoding(self):
         # Check the encoding attribute is always set, and valid
         b = self.BytesIO()
diff --git a/Misc/NEWS.d/next/Library/2022-04-14-18-06-00.gh-issue-91526.cwfhSB.rst b/Misc/NEWS.d/next/Library/2022-04-14-18-06-00.gh-issue-91526.cwfhSB.rst
new file mode 100644
index 0000000000000..a6633421e2b0f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-04-14-18-06-00.gh-issue-91526.cwfhSB.rst
@@ -0,0 +1,3 @@
+Stop calling ``os.device_encoding(file.fileno())`` in
+:class:`TextIOWrapper`. It was complex, never documented, and didn't work
+for most cases. (Patch by Inada Naoki.)
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 6ba7393c3a6a3..f45a69787383f 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -1060,7 +1060,6 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
     PyObject *raw, *codec_info = NULL;
     PyObject *res;
     int r;
-    int use_locale_encoding = 0; // Use locale encoding even in UTF-8 mode.
 
     self->ok = 0;
     self->detached = 0;
@@ -1074,10 +1073,6 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
             }
         }
     }
-    else if (strcmp(encoding, "locale") == 0) {
-        encoding = NULL;
-        use_locale_encoding = 1;
-    }
 
     if (errors == Py_None) {
         errors = &_Py_ID(strict);
@@ -1114,57 +1109,18 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
     self->encodefunc = NULL;
     self->b2cratio = 0.0;
 
-#ifdef MS_WINDOWS
-    // os.device_encoding() on Unix is the locale encoding or UTF-8
-    // according to UTF-8 Mode.
-    // Since UTF-8 mode shouldn't affect `encoding="locale"`, we call
-    // os.device_encoding() only on Windows.
-    if (encoding == NULL) {
-        /* Try os.device_encoding(fileno) */
-        PyObject *fileno;
-        _PyIO_State *state = IO_STATE();
-        if (state == NULL)
-            goto error;
-        fileno = PyObject_CallMethodNoArgs(buffer, &_Py_ID(fileno));
-        /* Ignore only AttributeError and UnsupportedOperation */
-        if (fileno == NULL) {
-            if (PyErr_ExceptionMatches(PyExc_AttributeError) ||
-                PyErr_ExceptionMatches(state->unsupported_operation)) {
-                PyErr_Clear();
-            }
-            else {
-                goto error;
-            }
-        }
-        else {
-            int fd = _PyLong_AsInt(fileno);
-            Py_DECREF(fileno);
-            if (fd == -1 && PyErr_Occurred()) {
-                goto error;
-            }
-
-            self->encoding = _Py_device_encoding(fd);
-            if (self->encoding == NULL)
-                goto error;
-            else if (!PyUnicode_Check(self->encoding))
-                Py_CLEAR(self->encoding);
-        }
+    if (encoding == NULL && _PyRuntime.preconfig.utf8_mode) {
+        _Py_DECLARE_STR(utf_8, "utf-8");
+        self->encoding = Py_NewRef(&_Py_STR(utf_8));
     }
-#endif
-
-    if (encoding == NULL && self->encoding == NULL) {
-        if (_PyRuntime.preconfig.utf8_mode && !use_locale_encoding) {
-            _Py_DECLARE_STR(utf_8, "utf-8");
-            self->encoding = Py_NewRef(&_Py_STR(utf_8));
-        }
-        else {
-            self->encoding = _Py_GetLocaleEncodingObject();
-        }
+    else if (encoding == NULL || (strcmp(encoding, "locale") == 0)) {
+        self->encoding = _Py_GetLocaleEncodingObject();
         if (self->encoding == NULL) {
             goto error;
         }
         assert(PyUnicode_Check(self->encoding));
     }
+
     if (self->encoding != NULL) {
         encoding = PyUnicode_AsUTF8(self->encoding);
         if (encoding == NULL)



More information about the Python-checkins mailing list