Skip to content

Commit 02df963

Browse files
committed
gh-157710: Avoid copy for large int in PyUnicodeWriter_WriteStr()
Enable the PyUnicodeWriter read-only optimization for large integer (more than 1000 digits) in PyUnicodeWriter_WriteStr() and PyUnicodeWriter_WriteRepr().
1 parent dc0b1f8 commit 02df963

2 files changed

Lines changed: 29 additions & 4 deletions

File tree

‎Lib/test/test_capi/test_unicode.py‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,6 +2262,35 @@ def __repr__(self):
22622262
self.assertEqual(writer.get_buffer(), expected)
22632263
self.assertIs(writer.finish(), unique_string)
22642264

2265+
def test_readonly_optim_large_int(self):
2266+
# Read-only optimization in _PyLong_FormatWriter() for large integer:
2267+
# use _pylong.int_to_decimal_string() result as a read-only string.
2268+
# See pylong_int_to_decimal_string().
2269+
2270+
self.addCleanup(sys.set_int_max_str_digits,
2271+
sys.get_int_max_str_digits())
2272+
sys.set_int_max_str_digits(0)
2273+
2274+
# _PyLong_FormatWriter() calls _pylong.int_to_decimal_string() for
2275+
# integer with Py_SIZE() > 1000.
2276+
large_int = 1 << (sys.int_info.bits_per_digit * 1020)
2277+
large_int_str = str(large_int)
2278+
expected = (len(large_int_str), 127, True)
2279+
2280+
for size in (0, 123):
2281+
with self.subTest(size=size):
2282+
# Test PyUnicodeWriter_WriteStr()
2283+
writer = self.create_writer(size)
2284+
writer.write_str(large_int)
2285+
self.assertEqual(writer.get_buffer(), expected)
2286+
self.assertEqual(writer.finish(), large_int_str)
2287+
2288+
# Test PyUnicodeWriter_WriteRepr()
2289+
writer = self.create_writer(size)
2290+
writer.write_repr(large_int)
2291+
self.assertEqual(writer.get_buffer(), expected)
2292+
self.assertEqual(writer.finish(), large_int_str)
2293+
22652294

22662295
# Test PyUnicodeWriter_Format()
22672296
@unittest.skipIf(ctypes is None, 'need ctypes')

‎Objects/longobject.c‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,10 +2045,6 @@ pylong_int_to_decimal_string(PyObject *aa,
20452045
goto error;
20462046
}
20472047
if (writer) {
2048-
Py_ssize_t size = PyUnicode_GET_LENGTH(s);
2049-
if (_PyUnicodeWriter_Prepare(writer, size, '9') == -1) {
2050-
goto error;
2051-
}
20522048
if (_PyUnicodeWriter_WriteStr(writer, s) < 0) {
20532049
goto error;
20542050
}

0 commit comments

Comments
 (0)