https://github.com/python/cpython/commit/39e5ed7fea8364dc30efd3fa5d68644606b0eac8
commit: 39e5ed7fea8364dc30efd3fa5d68644606b0eac8
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2026-09-29T22:15:41+02:00
summary:

gh-157710: Avoid copy for large int in PyUnicodeWriter_WriteStr() (#158448)

Enable the PyUnicodeWriter read-only optimization for large integer
(more than 1000 digits) in PyUnicodeWriter_WriteStr() and
PyUnicodeWriter_WriteRepr().

files:
M Lib/test/test_capi/test_unicode.py
M Objects/longobject.c

diff --git a/Lib/test/test_capi/test_unicode.py 
b/Lib/test/test_capi/test_unicode.py
index fc2bec2124a39b..36ecca48230ddd 100644
--- a/Lib/test/test_capi/test_unicode.py
+++ b/Lib/test/test_capi/test_unicode.py
@@ -2267,6 +2267,35 @@ def __repr__(self):
                 self.assertEqual(writer.get_buffer(), expected)
                 self.assertIs(writer.finish(), unique_string)
 
+    def test_readonly_optim_large_int(self):
+        # Read-only optimization in _PyLong_FormatWriter() for large integer:
+        # use _pylong.int_to_decimal_string() result as a read-only string.
+        # See pylong_int_to_decimal_string().
+
+        self.addCleanup(sys.set_int_max_str_digits,
+                        sys.get_int_max_str_digits())
+        sys.set_int_max_str_digits(0)
+
+        # _PyLong_FormatWriter() calls _pylong.int_to_decimal_string() for
+        # integer with Py_SIZE() > 1000.
+        large_int = 1 << (sys.int_info.bits_per_digit * 1020)
+        large_int_str = str(large_int)
+        expected = (len(large_int_str), 127, True)
+
+        for size in (0, 123):
+            with self.subTest(size=size):
+                # Test PyUnicodeWriter_WriteStr()
+                writer = self.create_writer(size)
+                writer.write_str(large_int)
+                self.assertEqual(writer.get_buffer(), expected)
+                self.assertEqual(writer.finish(), large_int_str)
+
+                # Test PyUnicodeWriter_WriteRepr()
+                writer = self.create_writer(size)
+                writer.write_repr(large_int)
+                self.assertEqual(writer.get_buffer(), expected)
+                self.assertEqual(writer.finish(), large_int_str)
+
 
 # Test PyUnicodeWriter_Format()
 @unittest.skipIf(ctypes is None, 'need ctypes')
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 1dac70820d142b..b9f00ca6fb471b 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -2045,10 +2045,6 @@ pylong_int_to_decimal_string(PyObject *aa,
         goto error;
     }
     if (writer) {
-        Py_ssize_t size = PyUnicode_GET_LENGTH(s);
-        if (_PyUnicodeWriter_Prepare(writer, size, '9') == -1) {
-            goto error;
-        }
         if (_PyUnicodeWriter_WriteStr(writer, s) < 0) {
             goto error;
         }

_______________________________________________
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