[Python-checkins] bpo-43510: PEP 597: Accept `encoding="locale"` in binary mode (GH-25103)

methane webhook-mailer at python.org
Wed Mar 31 01:26:16 EDT 2021

commit: ff3c9739bd69aa8b58007e63c9e40e6708b4761e
branch: master
author: Inada Naoki <songofacandy at gmail.com>
committer: methane <songofacandy at gmail.com>
date: 2021-03-31T14:26:08+09:00

bpo-43510: PEP 597: Accept `encoding="locale"` in binary mode (GH-25103)

It make `encoding="locale"` usable everywhere `encoding=None` is

M Lib/_pyio.py
M Lib/test/test_io.py
M Modules/_io/_iomodule.c

diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index 0f182d4240206..ba0b0a29b5013 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -221,7 +221,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None,
         raise ValueError("can't have read/write/append mode at once")
     if not (creating or reading or writing or appending):
         raise ValueError("must have exactly one of read/write/append mode")
-    if binary and encoding is not None:
+    if binary and encoding is not None and encoding != "locale":
         raise ValueError("binary mode doesn't take an encoding argument")
     if binary and errors is not None:
         raise ValueError("binary mode doesn't take an errors argument")
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index c731302a9f22f..6a9ce39f08eb5 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -531,6 +531,17 @@ class UnseekableWriter(self.MockUnseekableIO):
                     self.assertRaises(OSError, obj.truncate)
                     self.assertRaises(OSError, obj.truncate, 0)
+    def test_open_binmode_encoding(self):
+        """open() raises ValueError when encoding is specified in bin mode"""
+        self.assertRaises(ValueError, self.open, os_helper.TESTFN,
+                          "wb", encoding="utf-8")
+        # encoding=None and encoding="locale" is allowed.
+        with self.open(os_helper.TESTFN, "wb", encoding=None):
+            pass
+        with self.open(os_helper.TESTFN, "wb", encoding="locale"):
+            pass
     def test_open_handles_NUL_chars(self):
         fn_with_NUL = 'foo\0bar'
         self.assertRaises(ValueError, self.open, fn_with_NUL, 'w')
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c
index 652c2ce5b0d61..c627ca257fd5e 100644
--- a/Modules/_io/_iomodule.c
+++ b/Modules/_io/_iomodule.c
@@ -346,7 +346,8 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
         goto error;
-    if (binary && encoding != NULL) {
+    if (binary && encoding != NULL
+            && strcmp(encoding, "locale") != 0) {
                         "binary mode doesn't take an encoding argument");
         goto error;

More information about the Python-checkins mailing list