https://github.com/python/cpython/commit/4c73f50ca9885e5850dae64463e87cf5e80992a1
commit: 4c73f50ca9885e5850dae64463e87cf5e80992a1
branch: main
author: Donghee Na <[email protected]>
committer: corona10 <[email protected]>
date: 2026-10-19T21:00:42-07:00
summary:

gh-159813: Add a fast path for None in PyUnicodeWriter_WriteRepr (gh-159814)


Co-authored-by: Victor Stinner <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-10-19-16-38-39.gh-issue-159813.wHfSOc.rst
M Lib/test/test_capi/test_unicode.py
M Modules/_testcapi/unicode.c
M Objects/unicode_writer.c

diff --git a/Lib/test/test_capi/test_unicode.py 
b/Lib/test/test_capi/test_unicode.py
index 9237809e7f0dcca..0358bc38dfdf322 100644
--- a/Lib/test/test_capi/test_unicode.py
+++ b/Lib/test/test_capi/test_unicode.py
@@ -2038,6 +2038,21 @@ def __str__(self):
         self.assertEqual(result, 'abc')
         self.assertIs(type(result), str)
 
+    def test_repr(self):
+        # Test PyUnicodeWriter_WriteRepr()
+        writer = self.create_writer(0)
+        writer.write_str('str=')
+        writer.write_repr('abc')
+        writer.write_str(' int=')
+        writer.write_repr(123)
+        writer.write_str(' none=')
+        writer.write_repr_none()
+        obj = object()
+        writer.write_str(' obj=')
+        writer.write_repr(obj)
+        self.assertEqual(writer.finish(),
+                         f"str='abc' int=123 none=None obj={obj!r}")
+
     def test_repr_null(self):
         writer = self.create_writer(0)
         writer.write_utf8(b'var=', -1)
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-19-16-38-39.gh-issue-159813.wHfSOc.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-19-16-38-39.gh-issue-159813.wHfSOc.rst
new file mode 100644
index 000000000000000..7d5f0c8f2f53540
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-19-16-38-39.gh-issue-159813.wHfSOc.rst
@@ -0,0 +1,2 @@
+Add a fast path for :const:`None` in :c:func:`PyUnicodeWriter_WriteRepr`.
+Patch by Donghee Na.
diff --git a/Modules/_testcapi/unicode.c b/Modules/_testcapi/unicode.c
index ec3e9a623519f6e..19178b2977e62ed 100644
--- a/Modules/_testcapi/unicode.c
+++ b/Modules/_testcapi/unicode.c
@@ -689,6 +689,23 @@ writer_write_repr(PyObject *self_raw, PyObject *obj)
 }
 
 
+// write_repr(None) calls PyUnicodeWriter_WriteRepr(writer, NULL), so add
+// a specialized function calling PyUnicodeWriter_WriteRepr(writer, Py_None).
+static PyObject*
+writer_write_repr_none(PyObject *self_raw, PyObject *Py_UNUSED(arg))
+{
+    WriterObject *self = (WriterObject *)self_raw;
+    if (writer_check(self) < 0) {
+        return NULL;
+    }
+
+    if (PyUnicodeWriter_WriteRepr(self->writer, Py_None) < 0) {
+        return NULL;
+    }
+    Py_RETURN_NONE;
+}
+
+
 static PyObject*
 writer_write_substring(PyObject *self_raw, PyObject *args)
 {
@@ -854,6 +871,7 @@ static PyMethodDef writer_methods[] = {
     {"write_ucs4", _PyCFunction_CAST(writer_write_ucs4), METH_VARARGS},
     {"write_str", _PyCFunction_CAST(writer_write_str), METH_O},
     {"write_repr", _PyCFunction_CAST(writer_write_repr), METH_O},
+    {"write_repr_none", _PyCFunction_CAST(writer_write_repr_none), 
METH_NOARGS},
     {"write_substring", _PyCFunction_CAST(writer_write_substring), 
METH_VARARGS},
     {"write_latin1", _PyCFunction_CAST(writer_write_latin1), METH_VARARGS},
     {"decodeutf8stateful", _PyCFunction_CAST(writer_decodeutf8stateful), 
METH_VARARGS},
diff --git a/Objects/unicode_writer.c b/Objects/unicode_writer.c
index e1c8cb884a102f1..8046accfd7e2abb 100644
--- a/Objects/unicode_writer.c
+++ b/Objects/unicode_writer.c
@@ -320,6 +320,10 @@ PyUnicodeWriter_WriteRepr(PyUnicodeWriter *pub_writer, 
PyObject *obj)
     if (Py_TYPE(obj) == &PyLong_Type) {
         return _PyLong_FormatWriter(writer, obj, 10, 0);
     }
+    // Fast path for None; see gh-159813 for the rationale.
+    if (obj == Py_None) {
+        return _PyUnicodeWriter_WriteASCIIString(writer, "None", 4);
+    }
 
     PyObject *repr = PyObject_Repr(obj);
     if (repr == NULL) {

_______________________________________________
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