From 372ec0ec22dc65aaceeeba0ccf0cc78401f97ace Mon Sep 17 00:00:00 2001 From: Uno Date: Thu, 30 Oct 2025 15:30:55 +0900 Subject: [PATCH 1/8] Convert _json --- Modules/_json.c | 75 ++++++++++++++++++++++---------------- Modules/clinic/_json.c.h | 79 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 32 deletions(-) create mode 100644 Modules/clinic/_json.c.h diff --git a/Modules/_json.c b/Modules/_json.c index 9a1fc3aba36116..2666c75691768c 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -18,6 +18,12 @@ #include // bool +#include "clinic/_json.c.h" + +/*[clinic input] +module _json +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=549fa53592c925b2]*/ typedef struct _PyScannerObject { PyObject_HEAD @@ -650,17 +656,26 @@ PyDoc_STRVAR(pydoc_scanstring, "after the end quote." ); +/*[clinic input] +_json.scanstring as py_scanstring + pystr: object + end: Py_ssize_t + strict: bool = True + / + +Scan the string s for a JSON string. + +Return a tuple of the decoded string and the index of the character in s +after the end quote. +[clinic start generated code]*/ + static PyObject * -py_scanstring(PyObject* Py_UNUSED(self), PyObject *args) +py_scanstring_impl(PyObject *module, PyObject *pystr, Py_ssize_t end, + int strict) +/*[clinic end generated code: output=961740cfae07cdb3 input=d9077453fa0ca27c]*/ { - PyObject *pystr; PyObject *rval; - Py_ssize_t end; - Py_ssize_t next_end = -1; - int strict = 1; - if (!PyArg_ParseTuple(args, "On|p:scanstring", &pystr, &end, &strict)) { - return NULL; - } + Py_ssize_t next_end; if (PyUnicode_Check(pystr)) { rval = scanstring_unicode(pystr, end, strict, &next_end); } @@ -673,14 +688,17 @@ py_scanstring(PyObject* Py_UNUSED(self), PyObject *args) return _build_rval_index_tuple(rval, next_end); } -PyDoc_STRVAR(pydoc_encode_basestring_ascii, - "encode_basestring_ascii(string) -> string\n" - "\n" - "Return an ASCII-only JSON representation of a Python string" -); +/*[clinic input] +_json.encode_basestring_ascii as py_encode_basestring_ascii + pystr: object + / + +Return an ASCII-only JSON representation of a Python string +[clinic start generated code]*/ static PyObject * -py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr) +py_encode_basestring_ascii(PyObject *module, PyObject *pystr) +/*[clinic end generated code: output=a8afcd88eba0b572 input=f4085ccd5928ea55]*/ { PyObject *rval; /* Return an ASCII-only JSON representation of a Python string */ @@ -697,15 +715,17 @@ py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr) return rval; } +/*[clinic input] +_json.encode_basestring as py_encode_basestring + pystr: object + / -PyDoc_STRVAR(pydoc_encode_basestring, - "encode_basestring(string) -> string\n" - "\n" - "Return a JSON representation of a Python string" -); +Return a JSON representation of a Python string +[clinic start generated code]*/ static PyObject * -py_encode_basestring(PyObject* Py_UNUSED(self), PyObject *pystr) +py_encode_basestring(PyObject *module, PyObject *pystr) +/*[clinic end generated code: output=c87752300776d3b1 input=c3c7ef6e72624f6e]*/ { PyObject *rval; /* Return a JSON representation of a Python string */ @@ -2080,18 +2100,9 @@ static PyType_Spec PyEncoderType_spec = { }; static PyMethodDef speedups_methods[] = { - {"encode_basestring_ascii", - py_encode_basestring_ascii, - METH_O, - pydoc_encode_basestring_ascii}, - {"encode_basestring", - py_encode_basestring, - METH_O, - pydoc_encode_basestring}, - {"scanstring", - py_scanstring, - METH_VARARGS, - pydoc_scanstring}, + PY_ENCODE_BASESTRING_ASCII_METHODDEF + PY_ENCODE_BASESTRING_METHODDEF + PY_SCANSTRING_METHODDEF {NULL, NULL, 0, NULL} }; diff --git a/Modules/clinic/_json.c.h b/Modules/clinic/_json.c.h new file mode 100644 index 00000000000000..0b2dd7f02a9593 --- /dev/null +++ b/Modules/clinic/_json.c.h @@ -0,0 +1,79 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#include "pycore_abstract.h" // _PyNumber_Index() +#include "pycore_modsupport.h" // _PyArg_CheckPositional() + +PyDoc_STRVAR(py_scanstring__doc__, +"scanstring($module, pystr, end, strict=True, /)\n" +"--\n" +"\n" +"Scan the string s for a JSON string.\n" +"\n" +"Return a tuple of the decoded string and the index of the character in s\n" +"after the end quote."); + +#define PY_SCANSTRING_METHODDEF \ + {"scanstring", _PyCFunction_CAST(py_scanstring), METH_FASTCALL, py_scanstring__doc__}, + +static PyObject * +py_scanstring_impl(PyObject *module, PyObject *pystr, Py_ssize_t end, + int strict); + +static PyObject * +py_scanstring(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *pystr; + Py_ssize_t end; + int strict = 1; + + if (!_PyArg_CheckPositional("scanstring", nargs, 2, 3)) { + goto exit; + } + pystr = args[0]; + { + Py_ssize_t ival = -1; + PyObject *iobj = _PyNumber_Index(args[1]); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + end = ival; + } + if (nargs < 3) { + goto skip_optional; + } + strict = PyObject_IsTrue(args[2]); + if (strict < 0) { + goto exit; + } +skip_optional: + return_value = py_scanstring_impl(module, pystr, end, strict); + +exit: + return return_value; +} + +PyDoc_STRVAR(py_encode_basestring_ascii__doc__, +"encode_basestring_ascii($module, pystr, /)\n" +"--\n" +"\n" +"Return an ASCII-only JSON representation of a Python string"); + +#define PY_ENCODE_BASESTRING_ASCII_METHODDEF \ + {"encode_basestring_ascii", (PyCFunction)py_encode_basestring_ascii, METH_O, py_encode_basestring_ascii__doc__}, + +PyDoc_STRVAR(py_encode_basestring__doc__, +"encode_basestring($module, pystr, /)\n" +"--\n" +"\n" +"Return a JSON representation of a Python string"); + +#define PY_ENCODE_BASESTRING_METHODDEF \ + {"encode_basestring", (PyCFunction)py_encode_basestring, METH_O, py_encode_basestring__doc__}, +/*[clinic end generated code: output=c123de56c1cf4ff2 input=a9049054013a1b77]*/ From 314fccbfd126f7e086e39475a921809c310cd4a4 Mon Sep 17 00:00:00 2001 From: Uno Date: Thu, 30 Oct 2025 15:33:49 +0900 Subject: [PATCH 2/8] add NEWS.d --- .../2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst new file mode 100644 index 00000000000000..ec3427fd6a34c3 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst @@ -0,0 +1 @@ +Convert _json module to use Argument Clinic From 6d309b6d4425b7f952655f6e735f6f1d940401f3 Mon Sep 17 00:00:00 2001 From: Uno Date: Thu, 30 Oct 2025 15:36:36 +0900 Subject: [PATCH 3/8] rm py_docstring --- Modules/_json.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Modules/_json.c b/Modules/_json.c index 2666c75691768c..1564903e8e3d6e 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -643,19 +643,6 @@ scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next return NULL; } -PyDoc_STRVAR(pydoc_scanstring, - "scanstring(string, end, strict=True) -> (string, end)\n" - "\n" - "Scan the string s for a JSON string. End is the index of the\n" - "character in s after the quote that started the JSON string.\n" - "Unescapes all valid JSON string escape sequences and raises ValueError\n" - "on attempt to decode an invalid string. If strict is False then literal\n" - "control characters are allowed in the string.\n" - "\n" - "Returns a tuple of the decoded string and the index of the character in s\n" - "after the end quote." -); - /*[clinic input] _json.scanstring as py_scanstring pystr: object From 963ca6b1f3d0828959676353ecc10f6875580f82 Mon Sep 17 00:00:00 2001 From: Uno Date: Thu, 30 Oct 2025 16:09:50 +0900 Subject: [PATCH 4/8] update docstring --- Modules/_json.c | 9 +++++++-- Modules/clinic/_json.c.h | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Modules/_json.c b/Modules/_json.c index 1564903e8e3d6e..aef70b6ead4ce8 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -652,14 +652,19 @@ _json.scanstring as py_scanstring Scan the string s for a JSON string. -Return a tuple of the decoded string and the index of the character in s +End is the index of the character in s after the quote that started the +JSON string. Unescapes all valid JSON string escape sequences and raises +ValueError on attempt to decode an invalid string. If strict is False +then literal control characters are allowed in the string. + +Returns a tuple of the decoded string and the index of the character in s after the end quote. [clinic start generated code]*/ static PyObject * py_scanstring_impl(PyObject *module, PyObject *pystr, Py_ssize_t end, int strict) -/*[clinic end generated code: output=961740cfae07cdb3 input=d9077453fa0ca27c]*/ +/*[clinic end generated code: output=961740cfae07cdb3 input=9d46d7df7ac749b0]*/ { PyObject *rval; Py_ssize_t next_end; diff --git a/Modules/clinic/_json.c.h b/Modules/clinic/_json.c.h index 0b2dd7f02a9593..b80e72ad00a62a 100644 --- a/Modules/clinic/_json.c.h +++ b/Modules/clinic/_json.c.h @@ -11,7 +11,12 @@ PyDoc_STRVAR(py_scanstring__doc__, "\n" "Scan the string s for a JSON string.\n" "\n" -"Return a tuple of the decoded string and the index of the character in s\n" +"End is the index of the character in s after the quote that started the\n" +"JSON string. Unescapes all valid JSON string escape sequences and raises\n" +"ValueError on attempt to decode an invalid string. If strict is False\n" +"then literal control characters are allowed in the string.\n" +"\n" +"Returns a tuple of the decoded string and the index of the character in s\n" "after the end quote."); #define PY_SCANSTRING_METHODDEF \ @@ -76,4 +81,4 @@ PyDoc_STRVAR(py_encode_basestring__doc__, #define PY_ENCODE_BASESTRING_METHODDEF \ {"encode_basestring", (PyCFunction)py_encode_basestring, METH_O, py_encode_basestring__doc__}, -/*[clinic end generated code: output=c123de56c1cf4ff2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d3aa505efc0acb3f input=a9049054013a1b77]*/ From 257f043d678d3a6f0b247f9575407a66eb14e47d Mon Sep 17 00:00:00 2001 From: Uno Date: Thu, 30 Oct 2025 16:12:11 +0900 Subject: [PATCH 5/8] fix var --- Modules/_json.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_json.c b/Modules/_json.c index aef70b6ead4ce8..6a84661a243ea4 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -667,7 +667,7 @@ py_scanstring_impl(PyObject *module, PyObject *pystr, Py_ssize_t end, /*[clinic end generated code: output=961740cfae07cdb3 input=9d46d7df7ac749b0]*/ { PyObject *rval; - Py_ssize_t next_end; + Py_ssize_t next_end = -1; if (PyUnicode_Check(pystr)) { rval = scanstring_unicode(pystr, end, strict, &next_end); } From cdde5c726ba6db4f7fd98e2f5d617a99b98f7328 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Thu, 30 Oct 2025 16:55:39 +0900 Subject: [PATCH 6/8] Update Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst --- .../2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst index ec3427fd6a34c3..f36b9eed097229 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst @@ -1 +1 @@ -Convert _json module to use Argument Clinic +Convert :mod:`_json` module to use Argument Clinic From 9e28ea380cc115e417f1f1ee9a87f756d6a135a7 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Thu, 30 Oct 2025 17:28:06 +0900 Subject: [PATCH 7/8] Update Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst --- .../2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst index f36b9eed097229..ec3427fd6a34c3 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst @@ -1 +1 @@ -Convert :mod:`_json` module to use Argument Clinic +Convert _json module to use Argument Clinic From 63d92fa6f666e391d5677021b368512de663dabc Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Thu, 30 Oct 2025 18:13:25 +0900 Subject: [PATCH 8/8] Update Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst --- .../2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst index ec3427fd6a34c3..124ea3f9993814 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-30-15-33-07.gh-issue-137821.8_Iavt.rst @@ -1 +1 @@ -Convert _json module to use Argument Clinic +Convert ``_json`` module to use Argument Clinic