From f8aabb5042bc474b2c587323919267f7f2a051c4 Mon Sep 17 00:00:00 2001
From: Gihwan Kim <ghkim3221@gmail.com>
Date: Tue, 21 Feb 2023 12:10:29 +0900
Subject: [PATCH] gh-101961 fileinput.hookcompressed should not set the
 encoding value for the binary mode (gh-102068) (cherry picked from commit
 6f25657b83d7a680a97849490f6e973b3a695e1a)

Co-authored-by: Gihwan Kim <ghkim3221@gmail.com>
---
 Lib/fileinput.py                              |  2 +-
 Lib/test/test_fileinput.py                    | 39 +++++++++++++------
 Misc/ACKS                                     |  1 +
 ...-02-21-10-05-33.gh-issue-101961.7e56jh.rst |  2 +
 4 files changed, 32 insertions(+), 12 deletions(-)
 create mode 100644 Misc/NEWS.d/next/Library/2023-02-21-10-05-33.gh-issue-101961.7e56jh.rst

diff --git a/Lib/fileinput.py b/Lib/fileinput.py
index 2ce2f911435b41..3bd19906dcf5d2 100644
--- a/Lib/fileinput.py
+++ b/Lib/fileinput.py
@@ -419,7 +419,7 @@ def isstdin(self):
 
 
 def hook_compressed(filename, mode, *, encoding=None, errors=None):
-    if encoding is None:  # EncodingWarning is emitted in FileInput() already.
+    if encoding is None and "b" not in mode:  # EncodingWarning is emitted in FileInput() already.
         encoding = "locale"
     ext = os.path.splitext(filename)[1]
     if ext == '.gz':
diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py
index 21924ff41a72a4..6c4b5fe5d1299e 100644
--- a/Lib/test/test_fileinput.py
+++ b/Lib/test/test_fileinput.py
@@ -903,29 +903,29 @@ def setUp(self):
         self.fake_open = InvocationRecorder()
 
     def test_empty_string(self):
-        self.do_test_use_builtin_open("", 1)
+        self.do_test_use_builtin_open_text("", "r")
 
     def test_no_ext(self):
-        self.do_test_use_builtin_open("abcd", 2)
+        self.do_test_use_builtin_open_text("abcd", "r")
 
     @unittest.skipUnless(gzip, "Requires gzip and zlib")
     def test_gz_ext_fake(self):
         original_open = gzip.open
         gzip.open = self.fake_open
         try:
-            result = fileinput.hook_compressed("test.gz", "3")
+            result = fileinput.hook_compressed("test.gz", "r")
         finally:
             gzip.open = original_open
 
         self.assertEqual(self.fake_open.invocation_count, 1)
-        self.assertEqual(self.fake_open.last_invocation, (("test.gz", "3"), {}))
+        self.assertEqual(self.fake_open.last_invocation, (("test.gz", "r"), {}))
 
     @unittest.skipUnless(gzip, "Requires gzip and zlib")
     def test_gz_with_encoding_fake(self):
         original_open = gzip.open
         gzip.open = lambda filename, mode: io.BytesIO(b'Ex-binary string')
         try:
-            result = fileinput.hook_compressed("test.gz", "3", encoding="utf-8")
+            result = fileinput.hook_compressed("test.gz", "r", encoding="utf-8")
         finally:
             gzip.open = original_open
         self.assertEqual(list(result), ['Ex-binary string'])
@@ -935,23 +935,40 @@ def test_bz2_ext_fake(self):
         original_open = bz2.BZ2File
         bz2.BZ2File = self.fake_open
         try:
-            result = fileinput.hook_compressed("test.bz2", "4")
+            result = fileinput.hook_compressed("test.bz2", "r")
         finally:
             bz2.BZ2File = original_open
 
         self.assertEqual(self.fake_open.invocation_count, 1)
-        self.assertEqual(self.fake_open.last_invocation, (("test.bz2", "4"), {}))
+        self.assertEqual(self.fake_open.last_invocation, (("test.bz2", "r"), {}))
 
     def test_blah_ext(self):
-        self.do_test_use_builtin_open("abcd.blah", "5")
+        self.do_test_use_builtin_open_binary("abcd.blah", "rb")
 
     def test_gz_ext_builtin(self):
-        self.do_test_use_builtin_open("abcd.Gz", "6")
+        self.do_test_use_builtin_open_binary("abcd.Gz", "rb")
 
     def test_bz2_ext_builtin(self):
-        self.do_test_use_builtin_open("abcd.Bz2", "7")
+        self.do_test_use_builtin_open_binary("abcd.Bz2", "rb")
 
-    def do_test_use_builtin_open(self, filename, mode):
+    def test_binary_mode_encoding(self):
+        self.do_test_use_builtin_open_binary("abcd", "rb")
+
+    def test_text_mode_encoding(self):
+        self.do_test_use_builtin_open_text("abcd", "r")
+
+    def do_test_use_builtin_open_binary(self, filename, mode):
+        original_open = self.replace_builtin_open(self.fake_open)
+        try:
+            result = fileinput.hook_compressed(filename, mode)
+        finally:
+            self.replace_builtin_open(original_open)
+
+        self.assertEqual(self.fake_open.invocation_count, 1)
+        self.assertEqual(self.fake_open.last_invocation,
+                         ((filename, mode), {'encoding': None, 'errors': None}))
+
+    def do_test_use_builtin_open_text(self, filename, mode):
         original_open = self.replace_builtin_open(self.fake_open)
         try:
             result = fileinput.hook_compressed(filename, mode)
diff --git a/Misc/ACKS b/Misc/ACKS
index a78c086e16c642..b9aa307ae08786 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -912,6 +912,7 @@ Tyler Kieft
 Mads Kiilerich
 Jason Killen
 Derek D. Kim
+Gihwan Kim
 Jan Kim
 Taek Joo Kim
 Sam Kimbrel
diff --git a/Misc/NEWS.d/next/Library/2023-02-21-10-05-33.gh-issue-101961.7e56jh.rst b/Misc/NEWS.d/next/Library/2023-02-21-10-05-33.gh-issue-101961.7e56jh.rst
new file mode 100644
index 00000000000000..a3d4119e7cbdce
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-02-21-10-05-33.gh-issue-101961.7e56jh.rst
@@ -0,0 +1,2 @@
+For the binary mode, :func:`fileinput.hookcompressed` doesn't set the ``encoding`` value
+even if the value is ``None``. Patch by Gihwan Kim.