summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorInada Naoki <songofacandy@gmail.com>2022-04-19 02:44:36 (GMT)
committerGitHub <noreply@github.com>2022-04-19 02:44:36 (GMT)
commit6fdb62b1fa344b9cdf1f221eac83404fb1980822 (patch)
tree97badf048e8285069490b1753bc1a77f997070e7
parent39a54ba63850e081a4a5551a773df5b4d5b1d3cd (diff)
downloadcpython-6fdb62b1fa344b9cdf1f221eac83404fb1980822.zip
cpython-6fdb62b1fa344b9cdf1f221eac83404fb1980822.tar.gz
cpython-6fdb62b1fa344b9cdf1f221eac83404fb1980822.tar.bz2
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.
-rw-r--r--Lib/_pyio.py8
-rw-r--r--Lib/test/test_io.py12
-rw-r--r--Misc/NEWS.d/next/Library/2022-04-14-18-06-00.gh-issue-91526.cwfhSB.rst3
-rw-r--r--Modules/_io/textio.c56
4 files changed, 9 insertions, 70 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index 0f33ed5..380a7a7 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -2021,14 +2021,6 @@ class TextIOWrapper(TextIOBase):
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 c86251d..45bf81b 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -2736,18 +2736,6 @@ class TextIOWrapperTest(unittest.TestCase):
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 0000000..a663342
--- /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 6ba7393..f45a697 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)