Skip to content

Commit 4c73f50

Browse files
corona10vstinner
andauthored
gh-159813: Add a fast path for None in PyUnicodeWriter_WriteRepr (gh-159814)
Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent 71ba39d commit 4c73f50

4 files changed

Lines changed: 39 additions & 0 deletions

File tree

‎Lib/test/test_capi/test_unicode.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,6 +2038,21 @@ def __str__(self):
20382038
self.assertEqual(result, 'abc')
20392039
self.assertIs(type(result), str)
20402040

2041+
def test_repr(self):
2042+
# Test PyUnicodeWriter_WriteRepr()
2043+
writer = self.create_writer(0)
2044+
writer.write_str('str=')
2045+
writer.write_repr('abc')
2046+
writer.write_str(' int=')
2047+
writer.write_repr(123)
2048+
writer.write_str(' none=')
2049+
writer.write_repr_none()
2050+
obj = object()
2051+
writer.write_str(' obj=')
2052+
writer.write_repr(obj)
2053+
self.assertEqual(writer.finish(),
2054+
f"str='abc' int=123 none=None obj={obj!r}")
2055+
20412056
def test_repr_null(self):
20422057
writer = self.create_writer(0)
20432058
writer.write_utf8(b'var=', -1)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add a fast path for :const:`None` in :c:func:`PyUnicodeWriter_WriteRepr`.
2+
Patch by Donghee Na.

‎Modules/_testcapi/unicode.c‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,23 @@ writer_write_repr(PyObject *self_raw, PyObject *obj)
689689
}
690690

691691

692+
// write_repr(None) calls PyUnicodeWriter_WriteRepr(writer, NULL), so add
693+
// a specialized function calling PyUnicodeWriter_WriteRepr(writer, Py_None).
694+
static PyObject*
695+
writer_write_repr_none(PyObject *self_raw, PyObject *Py_UNUSED(arg))
696+
{
697+
WriterObject *self = (WriterObject *)self_raw;
698+
if (writer_check(self) < 0) {
699+
return NULL;
700+
}
701+
702+
if (PyUnicodeWriter_WriteRepr(self->writer, Py_None) < 0) {
703+
return NULL;
704+
}
705+
Py_RETURN_NONE;
706+
}
707+
708+
692709
static PyObject*
693710
writer_write_substring(PyObject *self_raw, PyObject *args)
694711
{
@@ -854,6 +871,7 @@ static PyMethodDef writer_methods[] = {
854871
{"write_ucs4", _PyCFunction_CAST(writer_write_ucs4), METH_VARARGS},
855872
{"write_str", _PyCFunction_CAST(writer_write_str), METH_O},
856873
{"write_repr", _PyCFunction_CAST(writer_write_repr), METH_O},
874+
{"write_repr_none", _PyCFunction_CAST(writer_write_repr_none), METH_NOARGS},
857875
{"write_substring", _PyCFunction_CAST(writer_write_substring), METH_VARARGS},
858876
{"write_latin1", _PyCFunction_CAST(writer_write_latin1), METH_VARARGS},
859877
{"decodeutf8stateful", _PyCFunction_CAST(writer_decodeutf8stateful), METH_VARARGS},

‎Objects/unicode_writer.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ PyUnicodeWriter_WriteRepr(PyUnicodeWriter *pub_writer, PyObject *obj)
320320
if (Py_TYPE(obj) == &PyLong_Type) {
321321
return _PyLong_FormatWriter(writer, obj, 10, 0);
322322
}
323+
// Fast path for None; see gh-159813 for the rationale.
324+
if (obj == Py_None) {
325+
return _PyUnicodeWriter_WriteASCIIString(writer, "None", 4);
326+
}
323327

324328
PyObject *repr = PyObject_Repr(obj);
325329
if (repr == NULL) {

0 commit comments

Comments
 (0)