https://github.com/python/cpython/commit/453d886f8592d2f4346d5621b1e4ff31c24338d5
commit: 453d886f8592d2f4346d5621b1e4ff31c24338d5
branch: main
author: Guo Ci <[email protected]>
committer: brettcannon <[email protected]>
date: 2025-11-15T00:13:37Z
summary:

GH-90344: replace single-call `io.IncrementalNewlineDecoder` usage with 
non-incremental newline decoders (GH-30276)

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Brett Cannon <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-10-31-14-03-42.gh-issue-90344.gvZigO.rst
M Lib/doctest.py
M Lib/importlib/_bootstrap_external.py
M Lib/test/test_importlib/test_abc.py

diff --git a/Lib/doctest.py b/Lib/doctest.py
index 92a2ab4f7e66f8..ad8fb900f692c7 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -104,7 +104,7 @@ def _test():
 import traceback
 import types
 import unittest
-from io import StringIO, IncrementalNewlineDecoder
+from io import StringIO, TextIOWrapper, BytesIO
 from collections import namedtuple
 import _colorize  # Used in doctests
 from _colorize import ANSIColors, can_colorize
@@ -237,10 +237,6 @@ def _normalize_module(module, depth=2):
     else:
         raise TypeError("Expected a module, string, or None")
 
-def _newline_convert(data):
-    # The IO module provides a handy decoder for universal newline conversion
-    return IncrementalNewlineDecoder(None, True).decode(data, True)
-
 def _load_testfile(filename, package, module_relative, encoding):
     if module_relative:
         package = _normalize_module(package, 3)
@@ -252,10 +248,9 @@ def _load_testfile(filename, package, module_relative, 
encoding):
                 pass
         if hasattr(loader, 'get_data'):
             file_contents = loader.get_data(filename)
-            file_contents = file_contents.decode(encoding)
             # get_data() opens files as 'rb', so one must do the equivalent
             # conversion as universal newlines would do.
-            return _newline_convert(file_contents), filename
+            return TextIOWrapper(BytesIO(file_contents), encoding=encoding, 
newline=None).read(), filename
     with open(filename, encoding=encoding) as f:
         return f.read(), filename
 
diff --git a/Lib/importlib/_bootstrap_external.py 
b/Lib/importlib/_bootstrap_external.py
index 4ab0e79ea6efeb..192c0261408ead 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -552,8 +552,7 @@ def decode_source(source_bytes):
     import tokenize  # To avoid bootstrap issues.
     source_bytes_readline = _io.BytesIO(source_bytes).readline
     encoding = tokenize.detect_encoding(source_bytes_readline)
-    newline_decoder = _io.IncrementalNewlineDecoder(None, True)
-    return newline_decoder.decode(source_bytes.decode(encoding[0]))
+    return _io.TextIOWrapper(_io.BytesIO(source_bytes), encoding=encoding[0], 
newline=None).read()
 
 
 # Module specifications #######################################################
diff --git a/Lib/test/test_importlib/test_abc.py 
b/Lib/test/test_importlib/test_abc.py
index dd943210ffca3c..bd1540ce403ce2 100644
--- a/Lib/test/test_importlib/test_abc.py
+++ b/Lib/test/test_importlib/test_abc.py
@@ -904,7 +904,7 @@ def test_universal_newlines(self):
         mock = self.SourceOnlyLoaderMock('mod.file')
         source = "x = 42\r\ny = -13\r\n"
         mock.source = source.encode('utf-8')
-        expect = io.IncrementalNewlineDecoder(None, True).decode(source)
+        expect = io.StringIO(source, newline=None).getvalue()
         self.assertEqual(mock.get_source(name), expect)
 
 
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-31-14-03-42.gh-issue-90344.gvZigO.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-31-14-03-42.gh-issue-90344.gvZigO.rst
new file mode 100644
index 00000000000000..b1d05354f65c71
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-31-14-03-42.gh-issue-90344.gvZigO.rst
@@ -0,0 +1 @@
+Replace :class:`io.IncrementalNewlineDecoder` with non incremental newline 
decoders in codebase where :meth:`!io.IncrementalNewlineDecoder.decode` was 
being called once.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to