From 5997f182e1d46a6e8d179c4e163ce62e2ab95107 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 01:54:23 +0100 Subject: [PATCH 01/27] Convert _interpreters.create() --- Modules/_interpretersmodule.c | 53 +++++++------- Modules/clinic/_interpretersmodule.c.h | 96 ++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 26 deletions(-) create mode 100644 Modules/clinic/_interpretersmodule.c.h diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index faf3b25b68c4eb..cb0dd40bc68b7b 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -20,12 +20,18 @@ #include "_interpreters_common.h" +#include "clinic/_interpretersmodule.c.h" #define MODULE_NAME _interpreters #define MODULE_NAME_STR Py_STRINGIFY(MODULE_NAME) #define MODINIT_FUNC_NAME RESOLVE_MODINIT_FUNC_NAME(MODULE_NAME) +/*[clinic input] +module _interpreters +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bfd967980a0de892]*/ + static PyInterpreterState * _get_current_interp(void) { @@ -841,17 +847,28 @@ Any keyword arguments are set on the corresponding config fields,\n\ overriding the initial values."); +/*[clinic input] +_interpreters.create + config as configobj: object(py_default="'isolated'") = NULL + * + reqrefs: bool = False + +Create a new interpreter and return a unique generated ID. + +The caller is responsible for destroying the interpreter before exiting, +typically by using _interpreters.destroy(). This can be managed +automatically by passing "reqrefs=True" and then using _incref() and +_decref() appropriately. + +"config" must be a valid interpreter config or the name of a +predefined config ("isolated" or "legacy"). The default +is "isolated". +[clinic start generated code]*/ + static PyObject * -interp_create(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_create_impl(PyObject *module, PyObject *configobj, int reqrefs) +/*[clinic end generated code: output=c1cc6835b1277c16 input=c6d69e3ff2315a65]*/ { - static char *kwlist[] = {"config", "reqrefs", NULL}; - PyObject *configobj = NULL; - int reqrefs = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O$p:create", kwlist, - &configobj, &reqrefs)) { - return NULL; - } - PyInterpreterConfig config; if (config_from_object(configobj, &config) < 0) { return NULL; @@ -885,21 +902,6 @@ interp_create(PyObject *self, PyObject *args, PyObject *kwds) } -PyDoc_STRVAR(create_doc, -"create([config], *, reqrefs=False) -> ID\n\ -\n\ -Create a new interpreter and return a unique generated ID.\n\ -\n\ -The caller is responsible for destroying the interpreter before exiting,\n\ -typically by using _interpreters.destroy(). This can be managed \n\ -automatically by passing \"reqrefs=True\" and then using _incref() and\n\ -_decref() appropriately.\n\ -\n\ -\"config\" must be a valid interpreter config or the name of a\n\ -predefined config (\"isolated\" or \"legacy\"). The default\n\ -is \"isolated\"."); - - static PyObject * interp_destroy(PyObject *self, PyObject *args, PyObject *kwds) { @@ -1605,8 +1607,7 @@ static PyMethodDef module_functions[] = { {"new_config", _PyCFunction_CAST(interp_new_config), METH_VARARGS | METH_KEYWORDS, new_config_doc}, - {"create", _PyCFunction_CAST(interp_create), - METH_VARARGS | METH_KEYWORDS, create_doc}, + _INTERPRETERS_CREATE_METHODDEF {"destroy", _PyCFunction_CAST(interp_destroy), METH_VARARGS | METH_KEYWORDS, destroy_doc}, {"list_all", _PyCFunction_CAST(interp_list_all), diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h new file mode 100644 index 00000000000000..37b6a49569b41a --- /dev/null +++ b/Modules/clinic/_interpretersmodule.c.h @@ -0,0 +1,96 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif +#include "pycore_modsupport.h" // _PyArg_UnpackKeywords() + +PyDoc_STRVAR(_interpreters_create__doc__, +"create($module, /, config=\'isolated\', *, reqrefs=False)\n" +"--\n" +"\n" +"Create a new interpreter and return a unique generated ID.\n" +"\n" +"The caller is responsible for destroying the interpreter before exiting,\n" +"typically by using _interpreters.destroy(). This can be managed\n" +"automatically by passing \"reqrefs=True\" and then using _incref() and\n" +"_decref() appropriately.\n" +"\n" +"\"config\" must be a valid interpreter config or the name of a\n" +"predefined config (\"isolated\" or \"legacy\"). The default\n" +"is \"isolated\"."); + +#define _INTERPRETERS_CREATE_METHODDEF \ + {"create", _PyCFunction_CAST(_interpreters_create), METH_FASTCALL|METH_KEYWORDS, _interpreters_create__doc__}, + +static PyObject * +_interpreters_create_impl(PyObject *module, PyObject *configobj, int reqrefs); + +static PyObject * +_interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(config), &_Py_ID(reqrefs), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"config", "reqrefs", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "create", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *configobj = NULL; + int reqrefs = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[0]) { + configobj = args[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + reqrefs = PyObject_IsTrue(args[1]); + if (reqrefs < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_create_impl(module, configobj, reqrefs); + +exit: + return return_value; +} +/*[clinic end generated code: output=79b9efeeb890ea68 input=a9049054013a1b77]*/ From 4b159b310da967b4b780ea579c806af203fdb3d9 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:00:41 +0100 Subject: [PATCH 02/27] Convert _interpreters.destroy() --- Modules/_interpretersmodule.c | 36 ++++++------- Modules/clinic/_interpretersmodule.c.h | 73 +++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 22 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index cb0dd40bc68b7b..f8941b790fa2a3 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -902,19 +902,22 @@ _interpreters_create_impl(PyObject *module, PyObject *configobj, int reqrefs) } +/*[clinic input] +_interpreters.destroy + id: object + * + restrict as restricted: bool = False + +Destroy the identified interpreter. + +Attempting to destroy the current interpreter raises InterpreterError. +So does an unrecognized ID. +[clinic start generated code]*/ + static PyObject * -interp_destroy(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_destroy_impl(PyObject *module, PyObject *id, int restricted) +/*[clinic end generated code: output=0bc20da8700ab4dd input=561bdd6537639d40]*/ { - static char *kwlist[] = {"id", "restrict", NULL}; - PyObject *id; - int restricted = 0; - // XXX Use "L" for id? - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$p:destroy", kwlist, &id, &restricted)) - { - return NULL; - } - // Look up the interpreter. int reqready = 0; PyInterpreterState *interp = \ @@ -948,14 +951,6 @@ interp_destroy(PyObject *self, PyObject *args, PyObject *kwds) Py_RETURN_NONE; } -PyDoc_STRVAR(destroy_doc, -"destroy(id, *, restrict=False)\n\ -\n\ -Destroy the identified interpreter.\n\ -\n\ -Attempting to destroy the current interpreter raises InterpreterError.\n\ -So does an unrecognized ID."); - static PyObject * interp_list_all(PyObject *self, PyObject *args, PyObject *kwargs) @@ -1608,8 +1603,7 @@ static PyMethodDef module_functions[] = { METH_VARARGS | METH_KEYWORDS, new_config_doc}, _INTERPRETERS_CREATE_METHODDEF - {"destroy", _PyCFunction_CAST(interp_destroy), - METH_VARARGS | METH_KEYWORDS, destroy_doc}, + _INTERPRETERS_DESTROY_METHODDEF {"list_all", _PyCFunction_CAST(interp_list_all), METH_VARARGS | METH_KEYWORDS, list_all_doc}, {"get_current", interp_get_current, diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 37b6a49569b41a..8aea45b8f87dc5 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -93,4 +93,75 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=79b9efeeb890ea68 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_destroy__doc__, +"destroy($module, /, id, *, restrict=False)\n" +"--\n" +"\n" +"Destroy the identified interpreter.\n" +"\n" +"Attempting to destroy the current interpreter raises InterpreterError.\n" +"So does an unrecognized ID."); + +#define _INTERPRETERS_DESTROY_METHODDEF \ + {"destroy", _PyCFunction_CAST(_interpreters_destroy), METH_FASTCALL|METH_KEYWORDS, _interpreters_destroy__doc__}, + +static PyObject * +_interpreters_destroy_impl(PyObject *module, PyObject *id, int restricted); + +static PyObject * +_interpreters_destroy(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", "restrict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "destroy", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *id; + int restricted = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + if (!noptargs) { + goto skip_optional_kwonly; + } + restricted = PyObject_IsTrue(args[1]); + if (restricted < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_destroy_impl(module, id, restricted); + +exit: + return return_value; +} +/*[clinic end generated code: output=02a5b963f63a723f input=a9049054013a1b77]*/ From eda5fa0335cb6014063c984b77561eeb134ff8a3 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:08:29 +0100 Subject: [PATCH 03/27] Convert _interpreters.list_all() --- Modules/_interpretersmodule.c | 28 +++++------ Modules/clinic/_interpretersmodule.c.h | 68 +++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 18 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index f8941b790fa2a3..71869d22ec925c 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -952,18 +952,18 @@ _interpreters_destroy_impl(PyObject *module, PyObject *id, int restricted) } +/*[clinic input] +_interpreters.list_all + * + require_ready as reqready: bool = False + +Return a list containing the ID of every existing interpreter. +[clinic start generated code]*/ + static PyObject * -interp_list_all(PyObject *self, PyObject *args, PyObject *kwargs) +_interpreters_list_all_impl(PyObject *module, int reqready) +/*[clinic end generated code: output=3f21c1a7c78043c0 input=35bae91c381a2cf9]*/ { - static char *kwlist[] = {"require_ready", NULL}; - int reqready = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|$p:" MODULE_NAME_STR ".list_all", - kwlist, &reqready)) - { - return NULL; - } - PyObject *ids = PyList_New(0); if (ids == NULL) { return NULL; @@ -992,11 +992,6 @@ interp_list_all(PyObject *self, PyObject *args, PyObject *kwargs) return ids; } -PyDoc_STRVAR(list_all_doc, -"list_all() -> [(ID, whence)]\n\ -\n\ -Return a list containing the ID of every existing interpreter."); - static PyObject * interp_get_current(PyObject *self, PyObject *Py_UNUSED(ignored)) @@ -1604,8 +1599,7 @@ static PyMethodDef module_functions[] = { _INTERPRETERS_CREATE_METHODDEF _INTERPRETERS_DESTROY_METHODDEF - {"list_all", _PyCFunction_CAST(interp_list_all), - METH_VARARGS | METH_KEYWORDS, list_all_doc}, + _INTERPRETERS_LIST_ALL_METHODDEF {"get_current", interp_get_current, METH_NOARGS, get_current_doc}, {"get_main", interp_get_main, diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 8aea45b8f87dc5..19f8ac6dfb9ced 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -164,4 +164,70 @@ _interpreters_destroy(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=02a5b963f63a723f input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_list_all__doc__, +"list_all($module, /, *, require_ready=False)\n" +"--\n" +"\n" +"Return a list containing the ID of every existing interpreter."); + +#define _INTERPRETERS_LIST_ALL_METHODDEF \ + {"list_all", _PyCFunction_CAST(_interpreters_list_all), METH_FASTCALL|METH_KEYWORDS, _interpreters_list_all__doc__}, + +static PyObject * +_interpreters_list_all_impl(PyObject *module, int reqready); + +static PyObject * +_interpreters_list_all(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(require_ready), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"require_ready", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "list_all", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + int reqready = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 0, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_kwonly; + } + reqready = PyObject_IsTrue(args[0]); + if (reqready < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_list_all_impl(module, reqready); + +exit: + return return_value; +} +/*[clinic end generated code: output=d0cc168bf7b1d459 input=a9049054013a1b77]*/ From 699dc6d31a1c21ba2f15aef5971f38bd282e40c1 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:10:46 +0100 Subject: [PATCH 04/27] Convert _interpreters.get_current() --- Modules/_interpretersmodule.c | 17 +++++++++-------- Modules/clinic/_interpretersmodule.c.h | 20 +++++++++++++++++++- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 71869d22ec925c..7be022631b7003 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -993,8 +993,15 @@ _interpreters_list_all_impl(PyObject *module, int reqready) } +/*[clinic input] +_interpreters.get_current + +Return the ID of current interpreter. +[clinic start generated code]*/ + static PyObject * -interp_get_current(PyObject *self, PyObject *Py_UNUSED(ignored)) +_interpreters_get_current_impl(PyObject *module) +/*[clinic end generated code: output=03161c8fcc0136eb input=6d003c614eacc533]*/ { PyInterpreterState *interp =_get_current_interp(); if (interp == NULL) { @@ -1004,11 +1011,6 @@ interp_get_current(PyObject *self, PyObject *Py_UNUSED(ignored)) return get_summary(interp); } -PyDoc_STRVAR(get_current_doc, -"get_current() -> (ID, whence)\n\ -\n\ -Return the ID of current interpreter."); - static PyObject * interp_get_main(PyObject *self, PyObject *Py_UNUSED(ignored)) @@ -1600,8 +1602,7 @@ static PyMethodDef module_functions[] = { _INTERPRETERS_CREATE_METHODDEF _INTERPRETERS_DESTROY_METHODDEF _INTERPRETERS_LIST_ALL_METHODDEF - {"get_current", interp_get_current, - METH_NOARGS, get_current_doc}, + _INTERPRETERS_GET_CURRENT_METHODDEF {"get_main", interp_get_main, METH_NOARGS, get_main_doc}, diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 19f8ac6dfb9ced..df759cf85d64e7 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -230,4 +230,22 @@ _interpreters_list_all(PyObject *module, PyObject *const *args, Py_ssize_t nargs exit: return return_value; } -/*[clinic end generated code: output=d0cc168bf7b1d459 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_get_current__doc__, +"get_current($module, /)\n" +"--\n" +"\n" +"Return the ID of current interpreter."); + +#define _INTERPRETERS_GET_CURRENT_METHODDEF \ + {"get_current", (PyCFunction)_interpreters_get_current, METH_NOARGS, _interpreters_get_current__doc__}, + +static PyObject * +_interpreters_get_current_impl(PyObject *module); + +static PyObject * +_interpreters_get_current(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _interpreters_get_current_impl(module); +} +/*[clinic end generated code: output=fb7ded6bea2ae0e8 input=a9049054013a1b77]*/ From c313b801f23c01d9c46817c74df71118b55906f7 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:12:19 +0100 Subject: [PATCH 05/27] Convert _interpreters.get_main() --- Modules/_interpretersmodule.c | 17 +++++++++-------- Modules/clinic/_interpretersmodule.c.h | 20 +++++++++++++++++++- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 7be022631b7003..a5008c4da9f824 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1012,19 +1012,21 @@ _interpreters_get_current_impl(PyObject *module) } +/*[clinic input] +_interpreters.get_main + +Return the ID of main interpreter. +[clinic start generated code]*/ + static PyObject * -interp_get_main(PyObject *self, PyObject *Py_UNUSED(ignored)) +_interpreters_get_main_impl(PyObject *module) +/*[clinic end generated code: output=9647288aff735557 input=a05bdf890db4b223]*/ { PyInterpreterState *interp = _PyInterpreterState_Main(); assert(_PyInterpreterState_IsReady(interp)); return get_summary(interp); } -PyDoc_STRVAR(get_main_doc, -"get_main() -> (ID, whence)\n\ -\n\ -Return the ID of main interpreter."); - static PyObject * interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs) @@ -1603,8 +1605,7 @@ static PyMethodDef module_functions[] = { _INTERPRETERS_DESTROY_METHODDEF _INTERPRETERS_LIST_ALL_METHODDEF _INTERPRETERS_GET_CURRENT_METHODDEF - {"get_main", interp_get_main, - METH_NOARGS, get_main_doc}, + _INTERPRETERS_GET_MAIN_METHODDEF {"is_running", _PyCFunction_CAST(interp_is_running), METH_VARARGS | METH_KEYWORDS, is_running_doc}, diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index df759cf85d64e7..b1795f080f28ff 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -248,4 +248,22 @@ _interpreters_get_current(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _interpreters_get_current_impl(module); } -/*[clinic end generated code: output=fb7ded6bea2ae0e8 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_get_main__doc__, +"get_main($module, /)\n" +"--\n" +"\n" +"Return the ID of main interpreter."); + +#define _INTERPRETERS_GET_MAIN_METHODDEF \ + {"get_main", (PyCFunction)_interpreters_get_main, METH_NOARGS, _interpreters_get_main__doc__}, + +static PyObject * +_interpreters_get_main_impl(PyObject *module); + +static PyObject * +_interpreters_get_main(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _interpreters_get_main_impl(module); +} +/*[clinic end generated code: output=a6ba3b909548db9f input=a9049054013a1b77]*/ From abe7aaaa04ae26409fec48ff4175b6f3a8b2c709 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:20:35 +0100 Subject: [PATCH 06/27] Convert _interpreters.set___main___attrs() --- Modules/_interpretersmodule.c | 32 +++++------ Modules/clinic/_interpretersmodule.c.h | 77 +++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 19 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index a5008c4da9f824..82bf7423c8f01c 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1028,19 +1028,21 @@ _interpreters_get_main_impl(PyObject *module) } +/*[clinic input] +_interpreters.set___main___attrs + id: object + updates: object(subclass_of='&PyDict_Type') + * + restrict as restricted: bool = False + +Bind the given attributes in the interpreter's __main__ module. +[clinic start generated code]*/ + static PyObject * -interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs) +_interpreters_set___main___attrs_impl(PyObject *module, PyObject *id, + PyObject *updates, int restricted) +/*[clinic end generated code: output=f3803010cb452bf0 input=d16ab8d81371f86a]*/ { - static char *kwlist[] = {"id", "updates", "restrict", NULL}; - PyObject *id, *updates; - int restricted = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "OO!|$p:" MODULE_NAME_STR ".set___main___attrs", - kwlist, &id, &PyDict_Type, &updates, &restricted)) - { - return NULL; - } - // Look up the interpreter. int reqready = 1; PyInterpreterState *interp = \ @@ -1087,11 +1089,6 @@ interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs) Py_RETURN_NONE; } -PyDoc_STRVAR(set___main___attrs_doc, -"set___main___attrs(id, ns, *, restrict=False)\n\ -\n\ -Bind the given attributes in the interpreter's __main__ module."); - static PyObject * _handle_script_error(struct run_result *runres) @@ -1622,8 +1619,7 @@ static PyMethodDef module_functions[] = { {"run_func", _PyCFunction_CAST(interp_run_func), METH_VARARGS | METH_KEYWORDS, run_func_doc}, - {"set___main___attrs", _PyCFunction_CAST(interp_set___main___attrs), - METH_VARARGS | METH_KEYWORDS, set___main___attrs_doc}, + _INTERPRETERS_SET___MAIN___ATTRS_METHODDEF {"incref", _PyCFunction_CAST(interp_incref), METH_VARARGS | METH_KEYWORDS, NULL}, diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index b1795f080f28ff..5c0a88d8639ae8 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -266,4 +266,79 @@ _interpreters_get_main(PyObject *module, PyObject *Py_UNUSED(ignored)) { return _interpreters_get_main_impl(module); } -/*[clinic end generated code: output=a6ba3b909548db9f input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_set___main___attrs__doc__, +"set___main___attrs($module, /, id, updates, *, restrict=False)\n" +"--\n" +"\n" +"Bind the given attributes in the interpreter\'s __main__ module."); + +#define _INTERPRETERS_SET___MAIN___ATTRS_METHODDEF \ + {"set___main___attrs", _PyCFunction_CAST(_interpreters_set___main___attrs), METH_FASTCALL|METH_KEYWORDS, _interpreters_set___main___attrs__doc__}, + +static PyObject * +_interpreters_set___main___attrs_impl(PyObject *module, PyObject *id, + PyObject *updates, int restricted); + +static PyObject * +_interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), &_Py_ID(updates), &_Py_ID(restrict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", "updates", "restrict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "set___main___attrs", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *id; + PyObject *updates; + int restricted = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + if (!PyDict_Check(args[1])) { + _PyArg_BadArgument("set___main___attrs", "argument 'updates'", "dict", args[1]); + goto exit; + } + updates = args[1]; + if (!noptargs) { + goto skip_optional_kwonly; + } + restricted = PyObject_IsTrue(args[2]); + if (restricted < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_set___main___attrs_impl(module, id, updates, restricted); + +exit: + return return_value; +} +/*[clinic end generated code: output=61cb084380333368 input=a9049054013a1b77]*/ From 6903b3f2ceb4198d4528c8d65c4c1bf64bd60ee3 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:36:53 +0100 Subject: [PATCH 07/27] Convert _interpreters.exec() --- Modules/_interpretersmodule.c | 62 +++++++-------- Modules/clinic/_interpretersmodule.c.h | 101 ++++++++++++++++++++++++- 2 files changed, 128 insertions(+), 35 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 82bf7423c8f01c..57f8d45a97a025 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1102,23 +1102,36 @@ _handle_script_error(struct run_result *runres) return runres->excinfo; } +/*[clinic input] +_interpreters.exec + id: object + code: object + shared: object(subclass_of='&PyDict_Type', c_default='NULL') = {} + * + restrict as restricted: bool = False + +Execute the provided code in the identified interpreter. + +This is equivalent to running the builtin exec() under the target +interpreter, using the __dict__ of its __main__ module as both +globals and locals. + +"code" may be a string containing the text of a Python script. + +Functions (and code objects) are also supported, with some restrictions. +The code/function must not take any arguments or be a closure +(i.e. have cell vars). Methods and other callables are not supported. + +If a function is provided, its code object is used and all its state +is ignored, including its __globals__ dict. +[clinic start generated code]*/ + static PyObject * -interp_exec(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_exec_impl(PyObject *module, PyObject *id, PyObject *code, + PyObject *shared, int restricted) +/*[clinic end generated code: output=492057c4f10dc304 input=5a22c1ed0c5dbcf3]*/ { -#define FUNCNAME MODULE_NAME_STR ".exec" PyThreadState *tstate = _PyThreadState_GET(); - static char *kwlist[] = {"id", "code", "shared", "restrict", NULL}; - PyObject *id, *code; - PyObject *shared = NULL; - int restricted = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "OO|O!$p:" FUNCNAME, kwlist, - &id, &code, &PyDict_Type, &shared, - &restricted)) - { - return NULL; - } - int reqready = 1; PyInterpreterState *interp = \ resolve_interp(id, restricted, reqready, "exec code for"); @@ -1143,26 +1156,8 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds) } assert(runres.result == NULL); Py_RETURN_NONE; -#undef FUNCNAME } -PyDoc_STRVAR(exec_doc, -"exec(id, code, shared=None, *, restrict=False)\n\ -\n\ -Execute the provided code in the identified interpreter.\n\ -This is equivalent to running the builtin exec() under the target\n\ -interpreter, using the __dict__ of its __main__ module as both\n\ -globals and locals.\n\ -\n\ -\"code\" may be a string containing the text of a Python script.\n\ -\n\ -Functions (and code objects) are also supported, with some restrictions.\n\ -The code/function must not take any arguments or be a closure\n\ -(i.e. have cell vars). Methods and other callables are not supported.\n\ -\n\ -If a function is provided, its code object is used and all its state\n\ -is ignored, including its __globals__ dict."); - static PyObject * interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) { @@ -1610,8 +1605,7 @@ static PyMethodDef module_functions[] = { METH_VARARGS | METH_KEYWORDS, get_config_doc}, {"whence", _PyCFunction_CAST(interp_whence), METH_VARARGS | METH_KEYWORDS, whence_doc}, - {"exec", _PyCFunction_CAST(interp_exec), - METH_VARARGS | METH_KEYWORDS, exec_doc}, + _INTERPRETERS_EXEC_METHODDEF {"call", _PyCFunction_CAST(interp_call), METH_VARARGS | METH_KEYWORDS, call_doc}, {"run_string", _PyCFunction_CAST(interp_run_string), diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 5c0a88d8639ae8..7c94c0c26739ae 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -341,4 +341,103 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi exit: return return_value; } -/*[clinic end generated code: output=61cb084380333368 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_exec__doc__, +"exec($module, /, id, code, shared={}, *, restrict=False)\n" +"--\n" +"\n" +"Execute the provided code in the identified interpreter.\n" +"\n" +"This is equivalent to running the builtin exec() under the target\n" +"interpreter, using the __dict__ of its __main__ module as both\n" +"globals and locals.\n" +"\n" +"\"code\" may be a string containing the text of a Python script.\n" +"\n" +"Functions (and code objects) are also supported, with some restrictions.\n" +"The code/function must not take any arguments or be a closure\n" +"(i.e. have cell vars). Methods and other callables are not supported.\n" +"\n" +"If a function is provided, its code object is used and all its state\n" +"is ignored, including its __globals__ dict."); + +#define _INTERPRETERS_EXEC_METHODDEF \ + {"exec", _PyCFunction_CAST(_interpreters_exec), METH_FASTCALL|METH_KEYWORDS, _interpreters_exec__doc__}, + +static PyObject * +_interpreters_exec_impl(PyObject *module, PyObject *id, PyObject *code, + PyObject *shared, int restricted); + +static PyObject * +_interpreters_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), &_Py_ID(code), &_Py_ID(shared), &_Py_ID(restrict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", "code", "shared", "restrict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "exec", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *id; + PyObject *code; + PyObject *shared = NULL; + int restricted = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + code = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + if (!PyDict_Check(args[2])) { + _PyArg_BadArgument("exec", "argument 'shared'", "dict", args[2]); + goto exit; + } + shared = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + restricted = PyObject_IsTrue(args[3]); + if (restricted < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_exec_impl(module, id, code, shared, restricted); + +exit: + return return_value; +} +/*[clinic end generated code: output=863235940fd4f2de input=a9049054013a1b77]*/ From d0b2e8df908a8a505c3c146d78ac7aa3505bf20f Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:40:41 +0100 Subject: [PATCH 08/27] Convert _interpreters.run_string() --- Modules/_interpretersmodule.c | 40 +++++------ Modules/clinic/_interpretersmodule.c.h | 95 +++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 23 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 57f8d45a97a025..c8c858fa8d7497 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1158,23 +1158,27 @@ _interpreters_exec_impl(PyObject *module, PyObject *id, PyObject *code, Py_RETURN_NONE; } +/*[clinic input] +_interpreters.run_string + id: object + script: unicode + shared: object(subclass_of='&PyDict_Type', c_default='NULL') = {} + * + restrict as restricted: bool = False + +Execute the provided string in the identified interpreter. + +(See _interpreters.exec().) +[clinic start generated code]*/ + static PyObject * -interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_run_string_impl(PyObject *module, PyObject *id, + PyObject *script, PyObject *shared, + int restricted) +/*[clinic end generated code: output=a30a64fb9ad396a2 input=9158a58996e05957]*/ { #define FUNCNAME MODULE_NAME_STR ".run_string" PyThreadState *tstate = _PyThreadState_GET(); - static char *kwlist[] = {"id", "script", "shared", "restrict", NULL}; - PyObject *id, *script; - PyObject *shared = NULL; - int restricted = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "OU|O!$p:" FUNCNAME, kwlist, - &id, &script, &PyDict_Type, &shared, - &restricted)) - { - return NULL; - } - int reqready = 1; PyInterpreterState *interp = \ resolve_interp(id, restricted, reqready, "run a string in"); @@ -1205,13 +1209,6 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) #undef FUNCNAME } -PyDoc_STRVAR(run_string_doc, -"run_string(id, script, shared=None, *, restrict=False)\n\ -\n\ -Execute the provided string in the identified interpreter.\n\ -\n\ -(See " MODULE_NAME_STR ".exec()."); - static PyObject * interp_run_func(PyObject *self, PyObject *args, PyObject *kwds) { @@ -1608,8 +1605,7 @@ static PyMethodDef module_functions[] = { _INTERPRETERS_EXEC_METHODDEF {"call", _PyCFunction_CAST(interp_call), METH_VARARGS | METH_KEYWORDS, call_doc}, - {"run_string", _PyCFunction_CAST(interp_run_string), - METH_VARARGS | METH_KEYWORDS, run_string_doc}, + _INTERPRETERS_RUN_STRING_METHODDEF {"run_func", _PyCFunction_CAST(interp_run_func), METH_VARARGS | METH_KEYWORDS, run_func_doc}, diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 7c94c0c26739ae..1e0d739415b16d 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -440,4 +440,97 @@ _interpreters_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py exit: return return_value; } -/*[clinic end generated code: output=863235940fd4f2de input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_run_string__doc__, +"run_string($module, /, id, script, shared={}, *, restrict=False)\n" +"--\n" +"\n" +"Execute the provided string in the identified interpreter.\n" +"\n" +"(See _interpreters.exec().)"); + +#define _INTERPRETERS_RUN_STRING_METHODDEF \ + {"run_string", _PyCFunction_CAST(_interpreters_run_string), METH_FASTCALL|METH_KEYWORDS, _interpreters_run_string__doc__}, + +static PyObject * +_interpreters_run_string_impl(PyObject *module, PyObject *id, + PyObject *script, PyObject *shared, + int restricted); + +static PyObject * +_interpreters_run_string(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), &_Py_ID(script), &_Py_ID(shared), &_Py_ID(restrict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", "script", "shared", "restrict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "run_string", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *id; + PyObject *script; + PyObject *shared = NULL; + int restricted = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("run_string", "argument 'script'", "str", args[1]); + goto exit; + } + script = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + if (!PyDict_Check(args[2])) { + _PyArg_BadArgument("run_string", "argument 'shared'", "dict", args[2]); + goto exit; + } + shared = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + restricted = PyObject_IsTrue(args[3]); + if (restricted < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_run_string_impl(module, id, script, shared, restricted); + +exit: + return return_value; +} +/*[clinic end generated code: output=6214a59c741feddb input=a9049054013a1b77]*/ From 91d15b575b113e4cdd9a4e10f278fc6c196d9062 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:44:11 +0100 Subject: [PATCH 09/27] Convert _interpreters.run_func() --- Modules/_interpretersmodule.c | 44 ++++++------ Modules/clinic/_interpretersmodule.c.h | 93 +++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 25 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index c8c858fa8d7497..354dc62d32812f 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1209,23 +1209,29 @@ _interpreters_run_string_impl(PyObject *module, PyObject *id, #undef FUNCNAME } +/*[clinic input] +_interpreters.run_func + id: object + func: object + shared: object(subclass_of='&PyDict_Type', c_default='NULL') = {} + * + restrict as restricted: bool = False + +Execute the body of the provided function in the identified interpreter. + +Code objects are also supported. In both cases, closures and args +are not supported. Methods and other callables are not supported either. + +(See _interpreters.exec().) +[clinic start generated code]*/ + static PyObject * -interp_run_func(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_run_func_impl(PyObject *module, PyObject *id, PyObject *func, + PyObject *shared, int restricted) +/*[clinic end generated code: output=131f7202ca4a0c5e input=2d62bb9b9eaf4948]*/ { #define FUNCNAME MODULE_NAME_STR ".run_func" PyThreadState *tstate = _PyThreadState_GET(); - static char *kwlist[] = {"id", "func", "shared", "restrict", NULL}; - PyObject *id, *func; - PyObject *shared = NULL; - int restricted = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "OO|O!$p:" FUNCNAME, kwlist, - &id, &func, &PyDict_Type, &shared, - &restricted)) - { - return NULL; - } - int reqready = 1; PyInterpreterState *interp = \ resolve_interp(id, restricted, reqready, "run a function in"); @@ -1265,15 +1271,6 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds) #undef FUNCNAME } -PyDoc_STRVAR(run_func_doc, -"run_func(id, func, shared=None, *, restrict=False)\n\ -\n\ -Execute the body of the provided function in the identified interpreter.\n\ -Code objects are also supported. In both cases, closures and args\n\ -are not supported. Methods and other callables are not supported either.\n\ -\n\ -(See " MODULE_NAME_STR ".exec()."); - static PyObject * interp_call(PyObject *self, PyObject *args, PyObject *kwds) { @@ -1606,8 +1603,7 @@ static PyMethodDef module_functions[] = { {"call", _PyCFunction_CAST(interp_call), METH_VARARGS | METH_KEYWORDS, call_doc}, _INTERPRETERS_RUN_STRING_METHODDEF - {"run_func", _PyCFunction_CAST(interp_run_func), - METH_VARARGS | METH_KEYWORDS, run_func_doc}, + _INTERPRETERS_RUN_FUNC_METHODDEF _INTERPRETERS_SET___MAIN___ATTRS_METHODDEF diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 1e0d739415b16d..7f59e86173b4f4 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -533,4 +533,95 @@ _interpreters_run_string(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=6214a59c741feddb input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_run_func__doc__, +"run_func($module, /, id, func, shared={}, *, restrict=False)\n" +"--\n" +"\n" +"Execute the body of the provided function in the identified interpreter.\n" +"\n" +"Code objects are also supported. In both cases, closures and args\n" +"are not supported. Methods and other callables are not supported either.\n" +"\n" +"(See _interpreters.exec().)"); + +#define _INTERPRETERS_RUN_FUNC_METHODDEF \ + {"run_func", _PyCFunction_CAST(_interpreters_run_func), METH_FASTCALL|METH_KEYWORDS, _interpreters_run_func__doc__}, + +static PyObject * +_interpreters_run_func_impl(PyObject *module, PyObject *id, PyObject *func, + PyObject *shared, int restricted); + +static PyObject * +_interpreters_run_func(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), &_Py_ID(func), &_Py_ID(shared), &_Py_ID(restrict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", "func", "shared", "restrict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "run_func", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *id; + PyObject *func; + PyObject *shared = NULL; + int restricted = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + func = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + if (!PyDict_Check(args[2])) { + _PyArg_BadArgument("run_func", "argument 'shared'", "dict", args[2]); + goto exit; + } + shared = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + restricted = PyObject_IsTrue(args[3]); + if (restricted < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_run_func_impl(module, id, func, shared, restricted); + +exit: + return return_value; +} +/*[clinic end generated code: output=18c9d4cdaf74b200 input=a9049054013a1b77]*/ From 98a75b257ac0111b64e116d4c4b7a38660596393 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:53:45 +0100 Subject: [PATCH 10/27] Convert _interpreters.call() --- Modules/_interpretersmodule.c | 48 +++++------ Modules/clinic/_interpretersmodule.c.h | 113 ++++++++++++++++++++++++- 2 files changed, 132 insertions(+), 29 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 354dc62d32812f..405c91fee7a2dc 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1271,28 +1271,28 @@ _interpreters_run_func_impl(PyObject *module, PyObject *id, PyObject *func, #undef FUNCNAME } +/*[clinic input] +_interpreters.call + id: object + callable: object + args as args_obj: object(subclass_of='&PyTuple_Type', c_default='NULL') = () + kwargs as kwargs_obj: object(subclass_of='&PyDict_Type', c_default='NULL') = {} + * + preserve_exc: bool = False + restrict as restricted: bool = False + +Call the provided object in the identified interpreter. + +Pass the given args and kwargs, if possible. +[clinic start generated code]*/ + static PyObject * -interp_call(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_call_impl(PyObject *module, PyObject *id, PyObject *callable, + PyObject *args_obj, PyObject *kwargs_obj, + int preserve_exc, int restricted) +/*[clinic end generated code: output=983ee27b3c43f6ef input=77590fdb3f519d65]*/ { -#define FUNCNAME MODULE_NAME_STR ".call" PyThreadState *tstate = _PyThreadState_GET(); - static char *kwlist[] = {"id", "callable", "args", "kwargs", - "preserve_exc", "restrict", NULL}; - PyObject *id, *callable; - PyObject *args_obj = NULL; - PyObject *kwargs_obj = NULL; - int preserve_exc = 0; - int restricted = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "OO|O!O!$pp:" FUNCNAME, kwlist, - &id, &callable, - &PyTuple_Type, &args_obj, - &PyDict_Type, &kwargs_obj, - &preserve_exc, &restricted)) - { - return NULL; - } - int reqready = 1; PyInterpreterState *interp = \ resolve_interp(id, restricted, reqready, "make a call in"); @@ -1323,15 +1323,8 @@ interp_call(PyObject *self, PyObject *args, PyObject *kwds) _interp_call_clear(&call); _run_result_clear(&runres); return res_and_exc; -#undef FUNCNAME } -PyDoc_STRVAR(call_doc, -"call(id, callable, args=None, kwargs=None, *, restrict=False)\n\ -\n\ -Call the provided object in the identified interpreter.\n\ -Pass the given args and kwargs, if possible."); - static PyObject * object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds) @@ -1600,8 +1593,7 @@ static PyMethodDef module_functions[] = { {"whence", _PyCFunction_CAST(interp_whence), METH_VARARGS | METH_KEYWORDS, whence_doc}, _INTERPRETERS_EXEC_METHODDEF - {"call", _PyCFunction_CAST(interp_call), - METH_VARARGS | METH_KEYWORDS, call_doc}, + _INTERPRETERS_CALL_METHODDEF _INTERPRETERS_RUN_STRING_METHODDEF _INTERPRETERS_RUN_FUNC_METHODDEF diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 7f59e86173b4f4..12541dbd48c003 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -624,4 +624,115 @@ _interpreters_run_func(PyObject *module, PyObject *const *args, Py_ssize_t nargs exit: return return_value; } -/*[clinic end generated code: output=18c9d4cdaf74b200 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_call__doc__, +"call($module, /, id, callable, args=(), kwargs={}, *,\n" +" preserve_exc=False, restrict=False)\n" +"--\n" +"\n" +"Call the provided object in the identified interpreter.\n" +"\n" +"Pass the given args and kwargs, if possible."); + +#define _INTERPRETERS_CALL_METHODDEF \ + {"call", _PyCFunction_CAST(_interpreters_call), METH_FASTCALL|METH_KEYWORDS, _interpreters_call__doc__}, + +static PyObject * +_interpreters_call_impl(PyObject *module, PyObject *id, PyObject *callable, + PyObject *args_obj, PyObject *kwargs_obj, + int preserve_exc, int restricted); + +static PyObject * +_interpreters_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 6 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), &_Py_ID(callable), &_Py_ID(args), &_Py_ID(kwargs), &_Py_ID(preserve_exc), &_Py_ID(restrict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", "callable", "args", "kwargs", "preserve_exc", "restrict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "call", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[6]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; + PyObject *id; + PyObject *callable; + PyObject *args_obj = NULL; + PyObject *kwargs_obj = NULL; + int preserve_exc = 0; + int restricted = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 2, /*maxpos*/ 4, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + callable = args[1]; + if (!noptargs) { + goto skip_optional_pos; + } + if (args[2]) { + if (!PyTuple_Check(args[2])) { + _PyArg_BadArgument("call", "argument 'args'", "tuple", args[2]); + goto exit; + } + args_obj = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[3]) { + if (!PyDict_Check(args[3])) { + _PyArg_BadArgument("call", "argument 'kwargs'", "dict", args[3]); + goto exit; + } + kwargs_obj = args[3]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[4]) { + preserve_exc = PyObject_IsTrue(args[4]); + if (preserve_exc < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + restricted = PyObject_IsTrue(args[5]); + if (restricted < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_call_impl(module, id, callable, args_obj, kwargs_obj, preserve_exc, restricted); + +exit: + return return_value; +} +/*[clinic end generated code: output=d009f06b21136592 input=a9049054013a1b77]*/ From 6d863cbeb0aba6577f1a989d63a42f016bfa8857 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:55:59 +0100 Subject: [PATCH 11/27] Convert _interpreters.is_shareable() --- Modules/_interpretersmodule.c | 26 +++++------ Modules/clinic/_interpretersmodule.c.h | 60 +++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 17 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 405c91fee7a2dc..2c427cd06fc5e7 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1326,16 +1326,17 @@ _interpreters_call_impl(PyObject *module, PyObject *id, PyObject *callable, } +/*[clinic input] +_interpreters.is_shareable + obj: object + +Return True if the object's data may be shared between interpreters and False otherwise. +[clinic start generated code]*/ + static PyObject * -object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_is_shareable_impl(PyObject *module, PyObject *obj) +/*[clinic end generated code: output=227856926a22940b input=72b9a36bdf1d2a53]*/ { - static char *kwlist[] = {"obj", NULL}; - PyObject *obj; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O:is_shareable", kwlist, &obj)) { - return NULL; - } - PyThreadState *tstate = _PyThreadState_GET(); if (_PyObject_CheckXIData(tstate, obj) == 0) { Py_RETURN_TRUE; @@ -1344,12 +1345,6 @@ object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds) Py_RETURN_FALSE; } -PyDoc_STRVAR(is_shareable_doc, -"is_shareable(obj) -> bool\n\ -\n\ -Return True if the object's data may be shared between interpreters and\n\ -False otherwise."); - static PyObject * interp_is_running(PyObject *self, PyObject *args, PyObject *kwds) @@ -1604,8 +1599,7 @@ static PyMethodDef module_functions[] = { {"decref", _PyCFunction_CAST(interp_decref), METH_VARARGS | METH_KEYWORDS, NULL}, - {"is_shareable", _PyCFunction_CAST(object_is_shareable), - METH_VARARGS | METH_KEYWORDS, is_shareable_doc}, + _INTERPRETERS_IS_SHAREABLE_METHODDEF {"capture_exception", _PyCFunction_CAST(capture_exception), METH_VARARGS | METH_KEYWORDS, capture_exception_doc}, diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 12541dbd48c003..fea7fdf40af027 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -735,4 +735,62 @@ _interpreters_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py exit: return return_value; } -/*[clinic end generated code: output=d009f06b21136592 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_is_shareable__doc__, +"is_shareable($module, /, obj)\n" +"--\n" +"\n" +"Return True if the object\'s data may be shared between interpreters and False otherwise."); + +#define _INTERPRETERS_IS_SHAREABLE_METHODDEF \ + {"is_shareable", _PyCFunction_CAST(_interpreters_is_shareable), METH_FASTCALL|METH_KEYWORDS, _interpreters_is_shareable__doc__}, + +static PyObject * +_interpreters_is_shareable_impl(PyObject *module, PyObject *obj); + +static PyObject * +_interpreters_is_shareable(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(obj), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"obj", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "is_shareable", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *obj; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + obj = args[0]; + return_value = _interpreters_is_shareable_impl(module, obj); + +exit: + return return_value; +} +/*[clinic end generated code: output=95284c14ff28beed input=a9049054013a1b77]*/ From 84217c892d01e7ea6838e3cb4afa4c30cd16c170 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:58:04 +0100 Subject: [PATCH 12/27] Convert _interpreters.is_running() --- Modules/_interpretersmodule.c | 30 +++++------ Modules/clinic/_interpretersmodule.c.h | 70 +++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 2c427cd06fc5e7..bb930cbe6afc30 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1346,19 +1346,19 @@ _interpreters_is_shareable_impl(PyObject *module, PyObject *obj) } +/*[clinic input] +_interpreters.is_running + id: object + * + restrict as restricted: bool = False + +Return whether or not the identified interpreter is running. +[clinic start generated code]*/ + static PyObject * -interp_is_running(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_is_running_impl(PyObject *module, PyObject *id, int restricted) +/*[clinic end generated code: output=32a6225d5ded9bdb input=3291578d04231125]*/ { - static char *kwlist[] = {"id", "restrict", NULL}; - PyObject *id; - int restricted = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$p:is_running", kwlist, - &id, &restricted)) - { - return NULL; - } - int reqready = 1; PyInterpreterState *interp = \ resolve_interp(id, restricted, reqready, "check if running for"); @@ -1372,11 +1372,6 @@ interp_is_running(PyObject *self, PyObject *args, PyObject *kwds) Py_RETURN_FALSE; } -PyDoc_STRVAR(is_running_doc, -"is_running(id, *, restrict=False) -> bool\n\ -\n\ -Return whether or not the identified interpreter is running."); - static PyObject * interp_get_config(PyObject *self, PyObject *args, PyObject *kwds) @@ -1581,8 +1576,7 @@ static PyMethodDef module_functions[] = { _INTERPRETERS_GET_CURRENT_METHODDEF _INTERPRETERS_GET_MAIN_METHODDEF - {"is_running", _PyCFunction_CAST(interp_is_running), - METH_VARARGS | METH_KEYWORDS, is_running_doc}, + _INTERPRETERS_IS_RUNNING_METHODDEF {"get_config", _PyCFunction_CAST(interp_get_config), METH_VARARGS | METH_KEYWORDS, get_config_doc}, {"whence", _PyCFunction_CAST(interp_whence), diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index fea7fdf40af027..0ccfe755c97eae 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -793,4 +793,72 @@ _interpreters_is_shareable(PyObject *module, PyObject *const *args, Py_ssize_t n exit: return return_value; } -/*[clinic end generated code: output=95284c14ff28beed input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_is_running__doc__, +"is_running($module, /, id, *, restrict=False)\n" +"--\n" +"\n" +"Return whether or not the identified interpreter is running."); + +#define _INTERPRETERS_IS_RUNNING_METHODDEF \ + {"is_running", _PyCFunction_CAST(_interpreters_is_running), METH_FASTCALL|METH_KEYWORDS, _interpreters_is_running__doc__}, + +static PyObject * +_interpreters_is_running_impl(PyObject *module, PyObject *id, int restricted); + +static PyObject * +_interpreters_is_running(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", "restrict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "is_running", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *id; + int restricted = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + if (!noptargs) { + goto skip_optional_kwonly; + } + restricted = PyObject_IsTrue(args[1]); + if (restricted < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_is_running_impl(module, id, restricted); + +exit: + return return_value; +} +/*[clinic end generated code: output=623fce9726f3efa0 input=a9049054013a1b77]*/ From bfed2bf84970f8ede0acf0ff1da0b03ea4ac0bdd Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 02:59:37 +0100 Subject: [PATCH 13/27] Convert _interpreters.get_config() --- Modules/_interpretersmodule.c | 30 +++++------ Modules/clinic/_interpretersmodule.c.h | 71 +++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 18 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index bb930cbe6afc30..20313b6e030299 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1373,18 +1373,20 @@ _interpreters_is_running_impl(PyObject *module, PyObject *id, int restricted) } +/*[clinic input] +_interpreters.get_config + id as idobj: object + * + restrict as restricted: bool = False + +Return a representation of the config used to initialize the interpreter. +[clinic start generated code]*/ + static PyObject * -interp_get_config(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_get_config_impl(PyObject *module, PyObject *idobj, + int restricted) +/*[clinic end generated code: output=63f81d35c2fe1387 input=aa38d50f534eb3c5]*/ { - static char *kwlist[] = {"id", "restrict", NULL}; - PyObject *idobj = NULL; - int restricted = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$p:get_config", kwlist, - &idobj, &restricted)) - { - return NULL; - } if (idobj == Py_None) { idobj = NULL; } @@ -1410,11 +1412,6 @@ interp_get_config(PyObject *self, PyObject *args, PyObject *kwds) return configobj; } -PyDoc_STRVAR(get_config_doc, -"get_config(id, *, restrict=False) -> types.SimpleNamespace\n\ -\n\ -Return a representation of the config used to initialize the interpreter."); - static PyObject * interp_whence(PyObject *self, PyObject *args, PyObject *kwds) @@ -1577,8 +1574,7 @@ static PyMethodDef module_functions[] = { _INTERPRETERS_GET_MAIN_METHODDEF _INTERPRETERS_IS_RUNNING_METHODDEF - {"get_config", _PyCFunction_CAST(interp_get_config), - METH_VARARGS | METH_KEYWORDS, get_config_doc}, + _INTERPRETERS_GET_CONFIG_METHODDEF {"whence", _PyCFunction_CAST(interp_whence), METH_VARARGS | METH_KEYWORDS, whence_doc}, _INTERPRETERS_EXEC_METHODDEF diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 0ccfe755c97eae..dc4ef9772ee314 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -861,4 +861,73 @@ _interpreters_is_running(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=623fce9726f3efa0 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_get_config__doc__, +"get_config($module, /, id, *, restrict=False)\n" +"--\n" +"\n" +"Return a representation of the config used to initialize the interpreter."); + +#define _INTERPRETERS_GET_CONFIG_METHODDEF \ + {"get_config", _PyCFunction_CAST(_interpreters_get_config), METH_FASTCALL|METH_KEYWORDS, _interpreters_get_config__doc__}, + +static PyObject * +_interpreters_get_config_impl(PyObject *module, PyObject *idobj, + int restricted); + +static PyObject * +_interpreters_get_config(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", "restrict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "get_config", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *idobj; + int restricted = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + idobj = args[0]; + if (!noptargs) { + goto skip_optional_kwonly; + } + restricted = PyObject_IsTrue(args[1]); + if (restricted < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_get_config_impl(module, idobj, restricted); + +exit: + return return_value; +} +/*[clinic end generated code: output=e5c4396144a92bad input=a9049054013a1b77]*/ From 599bde4eaf520319ac9cf6c9358a77352c4dd5f1 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 03:01:13 +0100 Subject: [PATCH 14/27] Convert _interpreters.whence() --- Modules/_interpretersmodule.c | 26 +++++------ Modules/clinic/_interpretersmodule.c.h | 60 +++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 17 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 20313b6e030299..1dc35a555e3f51 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1413,17 +1413,17 @@ _interpreters_get_config_impl(PyObject *module, PyObject *idobj, } +/*[clinic input] +_interpreters.whence + id: object + +Return an identifier for where the interpreter was created. +[clinic start generated code]*/ + static PyObject * -interp_whence(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_whence_impl(PyObject *module, PyObject *id) +/*[clinic end generated code: output=ef2c21ab106c2c20 input=eeede0a2fbfa2968]*/ { - static char *kwlist[] = {"id", NULL}; - PyObject *id; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O:whence", kwlist, &id)) - { - return NULL; - } - PyInterpreterState *interp = look_up_interp(id); if (interp == NULL) { return NULL; @@ -1433,11 +1433,6 @@ interp_whence(PyObject *self, PyObject *args, PyObject *kwds) return PyLong_FromLong(whence); } -PyDoc_STRVAR(whence_doc, -"whence(id) -> int\n\ -\n\ -Return an identifier for where the interpreter was created."); - static PyObject * interp_incref(PyObject *self, PyObject *args, PyObject *kwds) @@ -1575,8 +1570,7 @@ static PyMethodDef module_functions[] = { _INTERPRETERS_IS_RUNNING_METHODDEF _INTERPRETERS_GET_CONFIG_METHODDEF - {"whence", _PyCFunction_CAST(interp_whence), - METH_VARARGS | METH_KEYWORDS, whence_doc}, + _INTERPRETERS_WHENCE_METHODDEF _INTERPRETERS_EXEC_METHODDEF _INTERPRETERS_CALL_METHODDEF _INTERPRETERS_RUN_STRING_METHODDEF diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index dc4ef9772ee314..ae7514d84977d3 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -930,4 +930,62 @@ _interpreters_get_config(PyObject *module, PyObject *const *args, Py_ssize_t nar exit: return return_value; } -/*[clinic end generated code: output=e5c4396144a92bad input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_whence__doc__, +"whence($module, /, id)\n" +"--\n" +"\n" +"Return an identifier for where the interpreter was created."); + +#define _INTERPRETERS_WHENCE_METHODDEF \ + {"whence", _PyCFunction_CAST(_interpreters_whence), METH_FASTCALL|METH_KEYWORDS, _interpreters_whence__doc__}, + +static PyObject * +_interpreters_whence_impl(PyObject *module, PyObject *id); + +static PyObject * +_interpreters_whence(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "whence", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *id; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + return_value = _interpreters_whence_impl(module, id); + +exit: + return return_value; +} +/*[clinic end generated code: output=70a1e5c316ae46ac input=a9049054013a1b77]*/ From 20c67ee6293330c7342b14449cf99ca5939d779f Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 03:04:35 +0100 Subject: [PATCH 15/27] Convert _interpreters.incref() --- Modules/_interpretersmodule.c | 27 +++++---- Modules/clinic/_interpretersmodule.c.h | 80 +++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 15 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 1dc35a555e3f51..46f6a5bd4795b8 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1434,20 +1434,20 @@ _interpreters_whence_impl(PyObject *module, PyObject *id) } +/*[clinic input] +_interpreters.incref + id: object + * + implieslink: bool = False + restrict as restricted: bool = False + +[clinic start generated code]*/ + static PyObject * -interp_incref(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_incref_impl(PyObject *module, PyObject *id, int implieslink, + int restricted) +/*[clinic end generated code: output=eccaa4e03fbe8ee2 input=a0a614748f2e348c]*/ { - static char *kwlist[] = {"id", "implieslink", "restrict", NULL}; - PyObject *id; - int implieslink = 0; - int restricted = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$pp:incref", kwlist, - &id, &implieslink, &restricted)) - { - return NULL; - } - int reqready = 1; PyInterpreterState *interp = \ resolve_interp(id, restricted, reqready, "incref"); @@ -1578,8 +1578,7 @@ static PyMethodDef module_functions[] = { _INTERPRETERS_SET___MAIN___ATTRS_METHODDEF - {"incref", _PyCFunction_CAST(interp_incref), - METH_VARARGS | METH_KEYWORDS, NULL}, + _INTERPRETERS_INCREF_METHODDEF {"decref", _PyCFunction_CAST(interp_decref), METH_VARARGS | METH_KEYWORDS, NULL}, diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index ae7514d84977d3..087a2dcf3dd5aa 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -988,4 +988,82 @@ _interpreters_whence(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=70a1e5c316ae46ac input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_incref__doc__, +"incref($module, /, id, *, implieslink=False, restrict=False)\n" +"--\n" +"\n"); + +#define _INTERPRETERS_INCREF_METHODDEF \ + {"incref", _PyCFunction_CAST(_interpreters_incref), METH_FASTCALL|METH_KEYWORDS, _interpreters_incref__doc__}, + +static PyObject * +_interpreters_incref_impl(PyObject *module, PyObject *id, int implieslink, + int restricted); + +static PyObject * +_interpreters_incref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), &_Py_ID(implieslink), &_Py_ID(restrict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", "implieslink", "restrict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "incref", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *id; + int implieslink = 0; + int restricted = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (args[1]) { + implieslink = PyObject_IsTrue(args[1]); + if (implieslink < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + restricted = PyObject_IsTrue(args[2]); + if (restricted < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_incref_impl(module, id, implieslink, restricted); + +exit: + return return_value; +} +/*[clinic end generated code: output=4d41bf64b2186f59 input=a9049054013a1b77]*/ From b7a49d38f28c7808c3718647b2ac8f7456baed17 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 03:05:32 +0100 Subject: [PATCH 16/27] Convert _interpreters.decref() --- Modules/_interpretersmodule.c | 23 ++++----- Modules/clinic/_interpretersmodule.c.h | 69 +++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 13 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 46f6a5bd4795b8..35c7b303dfc5b2 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1465,18 +1465,18 @@ _interpreters_incref_impl(PyObject *module, PyObject *id, int implieslink, } +/*[clinic input] +_interpreters.decref + id: object + * + restrict as restricted: bool = False + +[clinic start generated code]*/ + static PyObject * -interp_decref(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_decref_impl(PyObject *module, PyObject *id, int restricted) +/*[clinic end generated code: output=5c54db4b22086171 input=c4aa34f09c44e62a]*/ { - static char *kwlist[] = {"id", "restrict", NULL}; - PyObject *id; - int restricted = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$p:decref", kwlist, &id, &restricted)) - { - return NULL; - } - int reqready = 1; PyInterpreterState *interp = \ resolve_interp(id, restricted, reqready, "decref"); @@ -1579,8 +1579,7 @@ static PyMethodDef module_functions[] = { _INTERPRETERS_SET___MAIN___ATTRS_METHODDEF _INTERPRETERS_INCREF_METHODDEF - {"decref", _PyCFunction_CAST(interp_decref), - METH_VARARGS | METH_KEYWORDS, NULL}, + _INTERPRETERS_DECREF_METHODDEF _INTERPRETERS_IS_SHAREABLE_METHODDEF diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 087a2dcf3dd5aa..ceffe07643e7f1 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -1066,4 +1066,71 @@ _interpreters_incref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=4d41bf64b2186f59 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_decref__doc__, +"decref($module, /, id, *, restrict=False)\n" +"--\n" +"\n"); + +#define _INTERPRETERS_DECREF_METHODDEF \ + {"decref", _PyCFunction_CAST(_interpreters_decref), METH_FASTCALL|METH_KEYWORDS, _interpreters_decref__doc__}, + +static PyObject * +_interpreters_decref_impl(PyObject *module, PyObject *id, int restricted); + +static PyObject * +_interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", "restrict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "decref", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + PyObject *id; + int restricted = 0; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + if (!noptargs) { + goto skip_optional_kwonly; + } + restricted = PyObject_IsTrue(args[1]); + if (restricted < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = _interpreters_decref_impl(module, id, restricted); + +exit: + return return_value; +} +/*[clinic end generated code: output=78a3c49f45245ed8 input=a9049054013a1b77]*/ From d07daae096c1334fc1cc6be366919589afc0f55b Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 03:10:31 +0100 Subject: [PATCH 17/27] Convert _interpreters.capture_exception() --- Modules/_interpretersmodule.c | 33 +++++-------- Modules/clinic/_interpretersmodule.c.h | 68 +++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 21 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 35c7b303dfc5b2..e9edc4412b9b60 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -1490,18 +1490,20 @@ _interpreters_decref_impl(PyObject *module, PyObject *id, int restricted) } +/*[clinic input] +_interpreters.capture_exception + exc_arg: object(c_default='NULL') = None + +Return a snapshot of an exception. + +If "exc" is None then the current exception, if any, is used (but not cleared). +The returned snapshot is the same as what _interpreters.exec() returns. +[clinic start generated code]*/ + static PyObject * -capture_exception(PyObject *self, PyObject *args, PyObject *kwds) +_interpreters_capture_exception_impl(PyObject *module, PyObject *exc_arg) +/*[clinic end generated code: output=ef3f5393ef9c88a6 input=e607efac7eb95fba]*/ { - static char *kwlist[] = {"exc", NULL}; - PyObject *exc_arg = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "|O:capture_exception", kwlist, - &exc_arg)) - { - return NULL; - } - PyObject *exc = exc_arg; if (exc == NULL || exc == Py_None) { exc = PyErr_GetRaisedException(); @@ -1549,14 +1551,6 @@ capture_exception(PyObject *self, PyObject *args, PyObject *kwds) return captured; } -PyDoc_STRVAR(capture_exception_doc, -"capture_exception(exc=None) -> types.SimpleNamespace\n\ -\n\ -Return a snapshot of an exception. If \"exc\" is None\n\ -then the current exception, if any, is used (but not cleared).\n\ -\n\ -The returned snapshot is the same as what _interpreters.exec() returns."); - static PyMethodDef module_functions[] = { {"new_config", _PyCFunction_CAST(interp_new_config), @@ -1583,8 +1577,7 @@ static PyMethodDef module_functions[] = { _INTERPRETERS_IS_SHAREABLE_METHODDEF - {"capture_exception", _PyCFunction_CAST(capture_exception), - METH_VARARGS | METH_KEYWORDS, capture_exception_doc}, + _INTERPRETERS_CAPTURE_EXCEPTION_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index ceffe07643e7f1..247170db45ff63 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -1133,4 +1133,70 @@ _interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, exit: return return_value; } -/*[clinic end generated code: output=78a3c49f45245ed8 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_interpreters_capture_exception__doc__, +"capture_exception($module, /, exc_arg=None)\n" +"--\n" +"\n" +"Return a snapshot of an exception.\n" +"\n" +"If \"exc\" is None then the current exception, if any, is used (but not cleared).\n" +"The returned snapshot is the same as what _interpreters.exec() returns."); + +#define _INTERPRETERS_CAPTURE_EXCEPTION_METHODDEF \ + {"capture_exception", _PyCFunction_CAST(_interpreters_capture_exception), METH_FASTCALL|METH_KEYWORDS, _interpreters_capture_exception__doc__}, + +static PyObject * +_interpreters_capture_exception_impl(PyObject *module, PyObject *exc_arg); + +static PyObject * +_interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(exc_arg), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"exc_arg", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "capture_exception", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; + PyObject *exc_arg = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + exc_arg = args[0]; +skip_optional_pos: + return_value = _interpreters_capture_exception_impl(module, exc_arg); + +exit: + return return_value; +} +/*[clinic end generated code: output=e83e8292dcd38205 input=a9049054013a1b77]*/ From 9e5577e0af086b53d9a8068995a18140e14dd874 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 03:25:07 +0100 Subject: [PATCH 18/27] Add note on new_config() --- Modules/_interpretersmodule.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index e9edc4412b9b60..a22d83b0927089 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -803,12 +803,12 @@ get_summary(PyInterpreterState *interp) } +// Not converted to Argument Clinic because the function uses ``**kwargs``. static PyObject * interp_new_config(PyObject *self, PyObject *args, PyObject *kwds) { const char *name = NULL; - if (!PyArg_ParseTuple(args, "|s:" MODULE_NAME_STR ".new_config", - &name)) + if (!PyArg_ParseTuple(args, "|s:" MODULE_NAME_STR ".new_config", &name)) { return NULL; } @@ -836,7 +836,8 @@ interp_new_config(PyObject *self, PyObject *args, PyObject *kwds) } PyDoc_STRVAR(new_config_doc, -"new_config(name='isolated', /, **overrides) -> type.SimpleNamespace\n\ +"new_config($module, /, name='isolated', /, **overrides)\n\ +--\n\ \n\ Return a representation of a new PyInterpreterConfig.\n\ \n\ From eb21bb11264b82709b31ffffdc1800105c92a539 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 04:38:58 +0100 Subject: [PATCH 19/27] Indicate positional-only parameters --- Modules/_interpretersmodule.c | 46 +++-- Modules/clinic/_interpretersmodule.c.h | 257 ++++++------------------- 2 files changed, 92 insertions(+), 211 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index a22d83b0927089..5cb5345872f810 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -851,6 +851,7 @@ overriding the initial values."); /*[clinic input] _interpreters.create config as configobj: object(py_default="'isolated'") = NULL + / * reqrefs: bool = False @@ -868,7 +869,7 @@ is "isolated". static PyObject * _interpreters_create_impl(PyObject *module, PyObject *configobj, int reqrefs) -/*[clinic end generated code: output=c1cc6835b1277c16 input=c6d69e3ff2315a65]*/ +/*[clinic end generated code: output=c1cc6835b1277c16 input=9b240f749f0f0972]*/ { PyInterpreterConfig config; if (config_from_object(configobj, &config) < 0) { @@ -906,6 +907,7 @@ _interpreters_create_impl(PyObject *module, PyObject *configobj, int reqrefs) /*[clinic input] _interpreters.destroy id: object + / * restrict as restricted: bool = False @@ -917,7 +919,7 @@ So does an unrecognized ID. static PyObject * _interpreters_destroy_impl(PyObject *module, PyObject *id, int restricted) -/*[clinic end generated code: output=0bc20da8700ab4dd input=561bdd6537639d40]*/ +/*[clinic end generated code: output=0bc20da8700ab4dd input=d2cfa1ef3b4a4ea5]*/ { // Look up the interpreter. int reqready = 0; @@ -1032,7 +1034,8 @@ _interpreters_get_main_impl(PyObject *module) /*[clinic input] _interpreters.set___main___attrs id: object - updates: object(subclass_of='&PyDict_Type') + ns as updates: object(subclass_of='&PyDict_Type') + / * restrict as restricted: bool = False @@ -1042,7 +1045,7 @@ Bind the given attributes in the interpreter's __main__ module. static PyObject * _interpreters_set___main___attrs_impl(PyObject *module, PyObject *id, PyObject *updates, int restricted) -/*[clinic end generated code: output=f3803010cb452bf0 input=d16ab8d81371f86a]*/ +/*[clinic end generated code: output=f3803010cb452bf0 input=69d409c4dd04dab9]*/ { // Look up the interpreter. int reqready = 1; @@ -1106,6 +1109,7 @@ _handle_script_error(struct run_result *runres) /*[clinic input] _interpreters.exec id: object + / code: object shared: object(subclass_of='&PyDict_Type', c_default='NULL') = {} * @@ -1130,7 +1134,7 @@ is ignored, including its __globals__ dict. static PyObject * _interpreters_exec_impl(PyObject *module, PyObject *id, PyObject *code, PyObject *shared, int restricted) -/*[clinic end generated code: output=492057c4f10dc304 input=5a22c1ed0c5dbcf3]*/ +/*[clinic end generated code: output=492057c4f10dc304 input=687f3f6ac5294593]*/ { PyThreadState *tstate = _PyThreadState_GET(); int reqready = 1; @@ -1162,6 +1166,7 @@ _interpreters_exec_impl(PyObject *module, PyObject *id, PyObject *code, /*[clinic input] _interpreters.run_string id: object + / script: unicode shared: object(subclass_of='&PyDict_Type', c_default='NULL') = {} * @@ -1213,6 +1218,7 @@ _interpreters_run_string_impl(PyObject *module, PyObject *id, /*[clinic input] _interpreters.run_func id: object + / func: object shared: object(subclass_of='&PyDict_Type', c_default='NULL') = {} * @@ -1229,7 +1235,7 @@ are not supported. Methods and other callables are not supported either. static PyObject * _interpreters_run_func_impl(PyObject *module, PyObject *id, PyObject *func, PyObject *shared, int restricted) -/*[clinic end generated code: output=131f7202ca4a0c5e input=2d62bb9b9eaf4948]*/ +/*[clinic end generated code: output=131f7202ca4a0c5e input=aa2dbab6f7354cd6]*/ { #define FUNCNAME MODULE_NAME_STR ".run_func" PyThreadState *tstate = _PyThreadState_GET(); @@ -1275,6 +1281,7 @@ _interpreters_run_func_impl(PyObject *module, PyObject *id, PyObject *func, /*[clinic input] _interpreters.call id: object + / callable: object args as args_obj: object(subclass_of='&PyTuple_Type', c_default='NULL') = () kwargs as kwargs_obj: object(subclass_of='&PyDict_Type', c_default='NULL') = {} @@ -1291,7 +1298,7 @@ static PyObject * _interpreters_call_impl(PyObject *module, PyObject *id, PyObject *callable, PyObject *args_obj, PyObject *kwargs_obj, int preserve_exc, int restricted) -/*[clinic end generated code: output=983ee27b3c43f6ef input=77590fdb3f519d65]*/ +/*[clinic end generated code: output=983ee27b3c43f6ef input=826c8dab4b1059b4]*/ { PyThreadState *tstate = _PyThreadState_GET(); int reqready = 1; @@ -1330,13 +1337,14 @@ _interpreters_call_impl(PyObject *module, PyObject *id, PyObject *callable, /*[clinic input] _interpreters.is_shareable obj: object + / Return True if the object's data may be shared between interpreters and False otherwise. [clinic start generated code]*/ static PyObject * -_interpreters_is_shareable_impl(PyObject *module, PyObject *obj) -/*[clinic end generated code: output=227856926a22940b input=72b9a36bdf1d2a53]*/ +_interpreters_is_shareable(PyObject *module, PyObject *obj) +/*[clinic end generated code: output=f2169d4c1f5d7bca input=4239989a8634b292]*/ { PyThreadState *tstate = _PyThreadState_GET(); if (_PyObject_CheckXIData(tstate, obj) == 0) { @@ -1350,6 +1358,7 @@ _interpreters_is_shareable_impl(PyObject *module, PyObject *obj) /*[clinic input] _interpreters.is_running id: object + / * restrict as restricted: bool = False @@ -1358,7 +1367,7 @@ Return whether or not the identified interpreter is running. static PyObject * _interpreters_is_running_impl(PyObject *module, PyObject *id, int restricted) -/*[clinic end generated code: output=32a6225d5ded9bdb input=3291578d04231125]*/ +/*[clinic end generated code: output=32a6225d5ded9bdb input=a4d98a82fcb4bf6e]*/ { int reqready = 1; PyInterpreterState *interp = \ @@ -1377,6 +1386,7 @@ _interpreters_is_running_impl(PyObject *module, PyObject *id, int restricted) /*[clinic input] _interpreters.get_config id as idobj: object + / * restrict as restricted: bool = False @@ -1386,7 +1396,7 @@ Return a representation of the config used to initialize the interpreter. static PyObject * _interpreters_get_config_impl(PyObject *module, PyObject *idobj, int restricted) -/*[clinic end generated code: output=63f81d35c2fe1387 input=aa38d50f534eb3c5]*/ +/*[clinic end generated code: output=63f81d35c2fe1387 input=79d88cf77a8ba034]*/ { if (idobj == Py_None) { idobj = NULL; @@ -1417,13 +1427,14 @@ _interpreters_get_config_impl(PyObject *module, PyObject *idobj, /*[clinic input] _interpreters.whence id: object + / Return an identifier for where the interpreter was created. [clinic start generated code]*/ static PyObject * -_interpreters_whence_impl(PyObject *module, PyObject *id) -/*[clinic end generated code: output=ef2c21ab106c2c20 input=eeede0a2fbfa2968]*/ +_interpreters_whence(PyObject *module, PyObject *id) +/*[clinic end generated code: output=e558d207672470cf input=6148f02c882e39f6]*/ { PyInterpreterState *interp = look_up_interp(id); if (interp == NULL) { @@ -1438,6 +1449,7 @@ _interpreters_whence_impl(PyObject *module, PyObject *id) /*[clinic input] _interpreters.incref id: object + / * implieslink: bool = False restrict as restricted: bool = False @@ -1447,7 +1459,7 @@ _interpreters.incref static PyObject * _interpreters_incref_impl(PyObject *module, PyObject *id, int implieslink, int restricted) -/*[clinic end generated code: output=eccaa4e03fbe8ee2 input=a0a614748f2e348c]*/ +/*[clinic end generated code: output=eccaa4e03fbe8ee2 input=a49374f447dead6f]*/ { int reqready = 1; PyInterpreterState *interp = \ @@ -1469,6 +1481,7 @@ _interpreters_incref_impl(PyObject *module, PyObject *id, int implieslink, /*[clinic input] _interpreters.decref id: object + / * restrict as restricted: bool = False @@ -1476,7 +1489,7 @@ _interpreters.decref static PyObject * _interpreters_decref_impl(PyObject *module, PyObject *id, int restricted) -/*[clinic end generated code: output=5c54db4b22086171 input=c4aa34f09c44e62a]*/ +/*[clinic end generated code: output=5c54db4b22086171 input=6f82beeae0b1c2b1]*/ { int reqready = 1; PyInterpreterState *interp = \ @@ -1494,6 +1507,7 @@ _interpreters_decref_impl(PyObject *module, PyObject *id, int restricted) /*[clinic input] _interpreters.capture_exception exc_arg: object(c_default='NULL') = None + / Return a snapshot of an exception. @@ -1503,7 +1517,7 @@ The returned snapshot is the same as what _interpreters.exec() returns. static PyObject * _interpreters_capture_exception_impl(PyObject *module, PyObject *exc_arg) -/*[clinic end generated code: output=ef3f5393ef9c88a6 input=e607efac7eb95fba]*/ +/*[clinic end generated code: output=ef3f5393ef9c88a6 input=e67d59d7fbb6d58c]*/ { PyObject *exc = exc_arg; if (exc == NULL || exc == Py_None) { diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 247170db45ff63..50f3e4a331959d 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -9,7 +9,7 @@ preserve #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_interpreters_create__doc__, -"create($module, /, config=\'isolated\', *, reqrefs=False)\n" +"create($module, config=\'isolated\', /, *, reqrefs=False)\n" "--\n" "\n" "Create a new interpreter and return a unique generated ID.\n" @@ -35,7 +35,7 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 1 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -44,7 +44,7 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(config), &_Py_ID(reqrefs), }, + .ob_item = { &_Py_ID(reqrefs), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -53,7 +53,7 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"config", "reqrefs", NULL}; + static const char * const _keywords[] = {"", "reqrefs", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "create", @@ -70,16 +70,12 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, if (!args) { goto exit; } - if (!noptargs) { - goto skip_optional_pos; + if (nargs < 1) { + goto skip_optional_posonly; } - if (args[0]) { - configobj = args[0]; - if (!--noptargs) { - goto skip_optional_pos; - } - } -skip_optional_pos: + noptargs--; + configobj = args[0]; +skip_optional_posonly: if (!noptargs) { goto skip_optional_kwonly; } @@ -95,7 +91,7 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } PyDoc_STRVAR(_interpreters_destroy__doc__, -"destroy($module, /, id, *, restrict=False)\n" +"destroy($module, id, /, *, restrict=False)\n" "--\n" "\n" "Destroy the identified interpreter.\n" @@ -115,7 +111,7 @@ _interpreters_destroy(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 1 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -124,7 +120,7 @@ _interpreters_destroy(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -133,7 +129,7 @@ _interpreters_destroy(PyObject *module, PyObject *const *args, Py_ssize_t nargs, # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"id", "restrict", NULL}; + static const char * const _keywords[] = {"", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "destroy", @@ -268,7 +264,7 @@ _interpreters_get_main(PyObject *module, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(_interpreters_set___main___attrs__doc__, -"set___main___attrs($module, /, id, updates, *, restrict=False)\n" +"set___main___attrs($module, id, ns, /, *, restrict=False)\n" "--\n" "\n" "Bind the given attributes in the interpreter\'s __main__ module."); @@ -286,7 +282,7 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 3 + #define NUM_KEYWORDS 1 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -295,7 +291,7 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(id), &_Py_ID(updates), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -304,7 +300,7 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"id", "updates", "restrict", NULL}; + static const char * const _keywords[] = {"", "", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "set___main___attrs", @@ -324,7 +320,7 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi } id = args[0]; if (!PyDict_Check(args[1])) { - _PyArg_BadArgument("set___main___attrs", "argument 'updates'", "dict", args[1]); + _PyArg_BadArgument("set___main___attrs", "argument 2", "dict", args[1]); goto exit; } updates = args[1]; @@ -343,7 +339,7 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi } PyDoc_STRVAR(_interpreters_exec__doc__, -"exec($module, /, id, code, shared={}, *, restrict=False)\n" +"exec($module, id, /, code, shared={}, *, restrict=False)\n" "--\n" "\n" "Execute the provided code in the identified interpreter.\n" @@ -374,7 +370,7 @@ _interpreters_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 4 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -383,7 +379,7 @@ _interpreters_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(id), &_Py_ID(code), &_Py_ID(shared), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(code), &_Py_ID(shared), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -392,7 +388,7 @@ _interpreters_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"id", "code", "shared", "restrict", NULL}; + static const char * const _keywords[] = {"", "code", "shared", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "exec", @@ -442,7 +438,7 @@ _interpreters_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py } PyDoc_STRVAR(_interpreters_run_string__doc__, -"run_string($module, /, id, script, shared={}, *, restrict=False)\n" +"run_string($module, id, /, script, shared={}, *, restrict=False)\n" "--\n" "\n" "Execute the provided string in the identified interpreter.\n" @@ -463,7 +459,7 @@ _interpreters_run_string(PyObject *module, PyObject *const *args, Py_ssize_t nar PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 4 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -472,7 +468,7 @@ _interpreters_run_string(PyObject *module, PyObject *const *args, Py_ssize_t nar } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(id), &_Py_ID(script), &_Py_ID(shared), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(script), &_Py_ID(shared), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -481,7 +477,7 @@ _interpreters_run_string(PyObject *module, PyObject *const *args, Py_ssize_t nar # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"id", "script", "shared", "restrict", NULL}; + static const char * const _keywords[] = {"", "script", "shared", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "run_string", @@ -535,7 +531,7 @@ _interpreters_run_string(PyObject *module, PyObject *const *args, Py_ssize_t nar } PyDoc_STRVAR(_interpreters_run_func__doc__, -"run_func($module, /, id, func, shared={}, *, restrict=False)\n" +"run_func($module, id, /, func, shared={}, *, restrict=False)\n" "--\n" "\n" "Execute the body of the provided function in the identified interpreter.\n" @@ -558,7 +554,7 @@ _interpreters_run_func(PyObject *module, PyObject *const *args, Py_ssize_t nargs PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 4 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -567,7 +563,7 @@ _interpreters_run_func(PyObject *module, PyObject *const *args, Py_ssize_t nargs } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(id), &_Py_ID(func), &_Py_ID(shared), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(func), &_Py_ID(shared), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -576,7 +572,7 @@ _interpreters_run_func(PyObject *module, PyObject *const *args, Py_ssize_t nargs # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"id", "func", "shared", "restrict", NULL}; + static const char * const _keywords[] = {"", "func", "shared", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "run_func", @@ -626,7 +622,7 @@ _interpreters_run_func(PyObject *module, PyObject *const *args, Py_ssize_t nargs } PyDoc_STRVAR(_interpreters_call__doc__, -"call($module, /, id, callable, args=(), kwargs={}, *,\n" +"call($module, id, /, callable, args=(), kwargs={}, *,\n" " preserve_exc=False, restrict=False)\n" "--\n" "\n" @@ -648,7 +644,7 @@ _interpreters_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 6 + #define NUM_KEYWORDS 5 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -657,7 +653,7 @@ _interpreters_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(id), &_Py_ID(callable), &_Py_ID(args), &_Py_ID(kwargs), &_Py_ID(preserve_exc), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(callable), &_Py_ID(args), &_Py_ID(kwargs), &_Py_ID(preserve_exc), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -666,7 +662,7 @@ _interpreters_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"id", "callable", "args", "kwargs", "preserve_exc", "restrict", NULL}; + static const char * const _keywords[] = {"", "callable", "args", "kwargs", "preserve_exc", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "call", @@ -737,65 +733,16 @@ _interpreters_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py } PyDoc_STRVAR(_interpreters_is_shareable__doc__, -"is_shareable($module, /, obj)\n" +"is_shareable($module, obj, /)\n" "--\n" "\n" "Return True if the object\'s data may be shared between interpreters and False otherwise."); #define _INTERPRETERS_IS_SHAREABLE_METHODDEF \ - {"is_shareable", _PyCFunction_CAST(_interpreters_is_shareable), METH_FASTCALL|METH_KEYWORDS, _interpreters_is_shareable__doc__}, - -static PyObject * -_interpreters_is_shareable_impl(PyObject *module, PyObject *obj); - -static PyObject * -_interpreters_is_shareable(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - Py_hash_t ob_hash; - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_hash = -1, - .ob_item = { &_Py_ID(obj), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"obj", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "is_shareable", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *obj; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, - /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); - if (!args) { - goto exit; - } - obj = args[0]; - return_value = _interpreters_is_shareable_impl(module, obj); - -exit: - return return_value; -} + {"is_shareable", (PyCFunction)_interpreters_is_shareable, METH_O, _interpreters_is_shareable__doc__}, PyDoc_STRVAR(_interpreters_is_running__doc__, -"is_running($module, /, id, *, restrict=False)\n" +"is_running($module, id, /, *, restrict=False)\n" "--\n" "\n" "Return whether or not the identified interpreter is running."); @@ -812,7 +759,7 @@ _interpreters_is_running(PyObject *module, PyObject *const *args, Py_ssize_t nar PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 1 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -821,7 +768,7 @@ _interpreters_is_running(PyObject *module, PyObject *const *args, Py_ssize_t nar } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -830,7 +777,7 @@ _interpreters_is_running(PyObject *module, PyObject *const *args, Py_ssize_t nar # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"id", "restrict", NULL}; + static const char * const _keywords[] = {"", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "is_running", @@ -863,7 +810,7 @@ _interpreters_is_running(PyObject *module, PyObject *const *args, Py_ssize_t nar } PyDoc_STRVAR(_interpreters_get_config__doc__, -"get_config($module, /, id, *, restrict=False)\n" +"get_config($module, id, /, *, restrict=False)\n" "--\n" "\n" "Return a representation of the config used to initialize the interpreter."); @@ -881,7 +828,7 @@ _interpreters_get_config(PyObject *module, PyObject *const *args, Py_ssize_t nar PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 1 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -890,7 +837,7 @@ _interpreters_get_config(PyObject *module, PyObject *const *args, Py_ssize_t nar } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -899,7 +846,7 @@ _interpreters_get_config(PyObject *module, PyObject *const *args, Py_ssize_t nar # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"id", "restrict", NULL}; + static const char * const _keywords[] = {"", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "get_config", @@ -932,65 +879,16 @@ _interpreters_get_config(PyObject *module, PyObject *const *args, Py_ssize_t nar } PyDoc_STRVAR(_interpreters_whence__doc__, -"whence($module, /, id)\n" +"whence($module, id, /)\n" "--\n" "\n" "Return an identifier for where the interpreter was created."); #define _INTERPRETERS_WHENCE_METHODDEF \ - {"whence", _PyCFunction_CAST(_interpreters_whence), METH_FASTCALL|METH_KEYWORDS, _interpreters_whence__doc__}, - -static PyObject * -_interpreters_whence_impl(PyObject *module, PyObject *id); - -static PyObject * -_interpreters_whence(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - Py_hash_t ob_hash; - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_hash = -1, - .ob_item = { &_Py_ID(id), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"id", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "whence", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - PyObject *id; - - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, - /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); - if (!args) { - goto exit; - } - id = args[0]; - return_value = _interpreters_whence_impl(module, id); - -exit: - return return_value; -} + {"whence", (PyCFunction)_interpreters_whence, METH_O, _interpreters_whence__doc__}, PyDoc_STRVAR(_interpreters_incref__doc__, -"incref($module, /, id, *, implieslink=False, restrict=False)\n" +"incref($module, id, /, *, implieslink=False, restrict=False)\n" "--\n" "\n"); @@ -1007,7 +905,7 @@ _interpreters_incref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 3 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -1016,7 +914,7 @@ _interpreters_incref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(id), &_Py_ID(implieslink), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(implieslink), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -1025,7 +923,7 @@ _interpreters_incref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"id", "implieslink", "restrict", NULL}; + static const char * const _keywords[] = {"", "implieslink", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "incref", @@ -1068,7 +966,7 @@ _interpreters_incref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } PyDoc_STRVAR(_interpreters_decref__doc__, -"decref($module, /, id, *, restrict=False)\n" +"decref($module, id, /, *, restrict=False)\n" "--\n" "\n"); @@ -1084,7 +982,7 @@ _interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 1 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -1093,7 +991,7 @@ _interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -1102,7 +1000,7 @@ _interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"id", "restrict", NULL}; + static const char * const _keywords[] = {"", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "decref", @@ -1135,7 +1033,7 @@ _interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } PyDoc_STRVAR(_interpreters_capture_exception__doc__, -"capture_exception($module, /, exc_arg=None)\n" +"capture_exception($module, exc_arg=None, /)\n" "--\n" "\n" "Return a snapshot of an exception.\n" @@ -1144,59 +1042,28 @@ PyDoc_STRVAR(_interpreters_capture_exception__doc__, "The returned snapshot is the same as what _interpreters.exec() returns."); #define _INTERPRETERS_CAPTURE_EXCEPTION_METHODDEF \ - {"capture_exception", _PyCFunction_CAST(_interpreters_capture_exception), METH_FASTCALL|METH_KEYWORDS, _interpreters_capture_exception__doc__}, + {"capture_exception", _PyCFunction_CAST(_interpreters_capture_exception), METH_FASTCALL, _interpreters_capture_exception__doc__}, static PyObject * _interpreters_capture_exception_impl(PyObject *module, PyObject *exc_arg); static PyObject * -_interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +_interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - - #define NUM_KEYWORDS 1 - static struct { - PyGC_Head _this_is_not_used; - PyObject_VAR_HEAD - Py_hash_t ob_hash; - PyObject *ob_item[NUM_KEYWORDS]; - } _kwtuple = { - .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_hash = -1, - .ob_item = { &_Py_ID(exc_arg), }, - }; - #undef NUM_KEYWORDS - #define KWTUPLE (&_kwtuple.ob_base.ob_base) - - #else // !Py_BUILD_CORE - # define KWTUPLE NULL - #endif // !Py_BUILD_CORE - - static const char * const _keywords[] = {"exc_arg", NULL}; - static _PyArg_Parser _parser = { - .keywords = _keywords, - .fname = "capture_exception", - .kwtuple = KWTUPLE, - }; - #undef KWTUPLE - PyObject *argsbuf[1]; - Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *exc_arg = NULL; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, - /*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); - if (!args) { + if (!_PyArg_CheckPositional("capture_exception", nargs, 0, 1)) { goto exit; } - if (!noptargs) { - goto skip_optional_pos; + if (nargs < 1) { + goto skip_optional; } exc_arg = args[0]; -skip_optional_pos: +skip_optional: return_value = _interpreters_capture_exception_impl(module, exc_arg); exit: return return_value; } -/*[clinic end generated code: output=e83e8292dcd38205 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e5b52436e3b5a087 input=a9049054013a1b77]*/ From 6e26591c6fde8328a9e180f493008ef2e8b6def5 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 04:39:05 +0100 Subject: [PATCH 20/27] Update docstrings --- Modules/_interpretersmodule.c | 16 ++++++++-------- Modules/clinic/_interpretersmodule.c.h | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 5cb5345872f810..164e20ce0dff63 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -862,14 +862,14 @@ typically by using _interpreters.destroy(). This can be managed automatically by passing "reqrefs=True" and then using _incref() and _decref() appropriately. -"config" must be a valid interpreter config or the name of a -predefined config ("isolated" or "legacy"). The default -is "isolated". +*config* must be a valid interpreter config or the name of a +predefined config ('isolated' or 'legacy'). The default +is 'isolated'. [clinic start generated code]*/ static PyObject * _interpreters_create_impl(PyObject *module, PyObject *configobj, int reqrefs) -/*[clinic end generated code: output=c1cc6835b1277c16 input=9b240f749f0f0972]*/ +/*[clinic end generated code: output=c1cc6835b1277c16 input=7d7dbdefcd992b7e]*/ { PyInterpreterConfig config; if (config_from_object(configobj, &config) < 0) { @@ -1121,7 +1121,7 @@ This is equivalent to running the builtin exec() under the target interpreter, using the __dict__ of its __main__ module as both globals and locals. -"code" may be a string containing the text of a Python script. +*code* may be a string containing the text of a Python script. Functions (and code objects) are also supported, with some restrictions. The code/function must not take any arguments or be a closure @@ -1134,7 +1134,7 @@ is ignored, including its __globals__ dict. static PyObject * _interpreters_exec_impl(PyObject *module, PyObject *id, PyObject *code, PyObject *shared, int restricted) -/*[clinic end generated code: output=492057c4f10dc304 input=687f3f6ac5294593]*/ +/*[clinic end generated code: output=492057c4f10dc304 input=8e0199d4a220bbb8]*/ { PyThreadState *tstate = _PyThreadState_GET(); int reqready = 1; @@ -1511,13 +1511,13 @@ _interpreters.capture_exception Return a snapshot of an exception. -If "exc" is None then the current exception, if any, is used (but not cleared). +If *exc* is None then the current exception, if any, is used (but not cleared). The returned snapshot is the same as what _interpreters.exec() returns. [clinic start generated code]*/ static PyObject * _interpreters_capture_exception_impl(PyObject *module, PyObject *exc_arg) -/*[clinic end generated code: output=ef3f5393ef9c88a6 input=e67d59d7fbb6d58c]*/ +/*[clinic end generated code: output=ef3f5393ef9c88a6 input=5ffe1ced0ec8e093]*/ { PyObject *exc = exc_arg; if (exc == NULL || exc == Py_None) { diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 50f3e4a331959d..1c34a619a069e2 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -19,9 +19,9 @@ PyDoc_STRVAR(_interpreters_create__doc__, "automatically by passing \"reqrefs=True\" and then using _incref() and\n" "_decref() appropriately.\n" "\n" -"\"config\" must be a valid interpreter config or the name of a\n" -"predefined config (\"isolated\" or \"legacy\"). The default\n" -"is \"isolated\"."); +"*config* must be a valid interpreter config or the name of a\n" +"predefined config (\'isolated\' or \'legacy\'). The default\n" +"is \'isolated\'."); #define _INTERPRETERS_CREATE_METHODDEF \ {"create", _PyCFunction_CAST(_interpreters_create), METH_FASTCALL|METH_KEYWORDS, _interpreters_create__doc__}, @@ -348,7 +348,7 @@ PyDoc_STRVAR(_interpreters_exec__doc__, "interpreter, using the __dict__ of its __main__ module as both\n" "globals and locals.\n" "\n" -"\"code\" may be a string containing the text of a Python script.\n" +"*code* may be a string containing the text of a Python script.\n" "\n" "Functions (and code objects) are also supported, with some restrictions.\n" "The code/function must not take any arguments or be a closure\n" @@ -1038,7 +1038,7 @@ PyDoc_STRVAR(_interpreters_capture_exception__doc__, "\n" "Return a snapshot of an exception.\n" "\n" -"If \"exc\" is None then the current exception, if any, is used (but not cleared).\n" +"If *exc* is None then the current exception, if any, is used (but not cleared).\n" "The returned snapshot is the same as what _interpreters.exec() returns."); #define _INTERPRETERS_CAPTURE_EXCEPTION_METHODDEF \ @@ -1066,4 +1066,4 @@ _interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssiz exit: return return_value; } -/*[clinic end generated code: output=e5b52436e3b5a087 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e0357d000b5dc81a input=a9049054013a1b77]*/ From 08dce299ce0cf708d0983fc06c1576e35f526660 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 04:57:15 +0100 Subject: [PATCH 21/27] Update tests --- Lib/test/test__interpreters.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test__interpreters.py b/Lib/test/test__interpreters.py index a32d5d81d2bf2d..78f0778382de35 100644 --- a/Lib/test/test__interpreters.py +++ b/Lib/test/test__interpreters.py @@ -474,19 +474,19 @@ def setUp(self): def test_signatures(self): # See https://github.com/python/cpython/issues/126654 - msg = r'_interpreters.exec\(\) argument 3 must be dict, not int' + msg = r"exec\(\) argument 'shared' must be dict, not int" with self.assertRaisesRegex(TypeError, msg): _interpreters.exec(self.id, 'a', 1) with self.assertRaisesRegex(TypeError, msg): _interpreters.exec(self.id, 'a', shared=1) - msg = r'_interpreters.run_string\(\) argument 3 must be dict, not int' + msg = r"run_string\(\) argument 'shared' must be dict, not int" with self.assertRaisesRegex(TypeError, msg): _interpreters.run_string(self.id, 'a', shared=1) - msg = r'_interpreters.run_func\(\) argument 3 must be dict, not int' + msg = r"run_func\(\) argument 'shared' must be dict, not int" with self.assertRaisesRegex(TypeError, msg): _interpreters.run_func(self.id, lambda: None, shared=1) # See https://github.com/python/cpython/issues/135855 - msg = r'_interpreters.set___main___attrs\(\) argument 2 must be dict, not int' + msg = r'set___main___attrs\(\) argument 2 must be dict, not int' with self.assertRaisesRegex(TypeError, msg): _interpreters.set___main___attrs(self.id, 1) From af6582477387f0aa88b391cf73a64cf44b295bb2 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 05:05:22 +0100 Subject: [PATCH 22/27] Blurb --- .../next/Library/2025-08-11-05-05-08.gh-issue-137630.9lmqyc.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2025-08-11-05-05-08.gh-issue-137630.9lmqyc.rst diff --git a/Misc/NEWS.d/next/Library/2025-08-11-05-05-08.gh-issue-137630.9lmqyc.rst b/Misc/NEWS.d/next/Library/2025-08-11-05-05-08.gh-issue-137630.9lmqyc.rst new file mode 100644 index 00000000000000..94d836c17834fd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-08-11-05-05-08.gh-issue-137630.9lmqyc.rst @@ -0,0 +1,2 @@ +The :mod:`!_interpreters` module now uses Argument Clinic to parse arguments. +Patch by Adam Turner. From 435389fd0070470fc9ee518da13e8613427bd334 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 05:40:32 +0100 Subject: [PATCH 23/27] make regen-all --- .../pycore_global_objects_fini_generated.h | 8 +++++ Include/internal/pycore_global_strings.h | 8 +++++ .../internal/pycore_runtime_init_generated.h | 8 +++++ .../internal/pycore_unicodeobject_generated.h | 32 +++++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index ca4744789f1c23..7d3be37a5ed0e2 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -842,6 +842,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(call)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(call_exception_handler)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(call_soon)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(callable)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(callback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cancel)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(capath)); @@ -1006,6 +1007,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(identity_hint)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ignore)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(imag)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(implieslink)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(importlib)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(in_fd)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(include_aliases)); @@ -1055,6 +1057,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw1)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw2)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kwargs)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kwdefaults)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(label)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(last)); @@ -1171,6 +1174,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos1)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos2)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(posix)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(preserve_exc)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(print_file_and_line)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(priority)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(progress)); @@ -1198,9 +1202,12 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reload)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(repl)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(replace)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reqrefs)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(require_ready)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reserved)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reset)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(resetids)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(restrict)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(return)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reverse)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reversed)); @@ -1227,6 +1234,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(setsigmask)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(setstate)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(shape)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(shared)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(show_cmd)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(signed)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(size)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 47bb6fcecc1ba6..1da2c1e8b79427 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -333,6 +333,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(call) STRUCT_FOR_ID(call_exception_handler) STRUCT_FOR_ID(call_soon) + STRUCT_FOR_ID(callable) STRUCT_FOR_ID(callback) STRUCT_FOR_ID(cancel) STRUCT_FOR_ID(capath) @@ -497,6 +498,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(identity_hint) STRUCT_FOR_ID(ignore) STRUCT_FOR_ID(imag) + STRUCT_FOR_ID(implieslink) STRUCT_FOR_ID(importlib) STRUCT_FOR_ID(in_fd) STRUCT_FOR_ID(include_aliases) @@ -546,6 +548,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(kw) STRUCT_FOR_ID(kw1) STRUCT_FOR_ID(kw2) + STRUCT_FOR_ID(kwargs) STRUCT_FOR_ID(kwdefaults) STRUCT_FOR_ID(label) STRUCT_FOR_ID(last) @@ -662,6 +665,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(pos1) STRUCT_FOR_ID(pos2) STRUCT_FOR_ID(posix) + STRUCT_FOR_ID(preserve_exc) STRUCT_FOR_ID(print_file_and_line) STRUCT_FOR_ID(priority) STRUCT_FOR_ID(progress) @@ -689,9 +693,12 @@ struct _Py_global_strings { STRUCT_FOR_ID(reload) STRUCT_FOR_ID(repl) STRUCT_FOR_ID(replace) + STRUCT_FOR_ID(reqrefs) + STRUCT_FOR_ID(require_ready) STRUCT_FOR_ID(reserved) STRUCT_FOR_ID(reset) STRUCT_FOR_ID(resetids) + STRUCT_FOR_ID(restrict) STRUCT_FOR_ID(return) STRUCT_FOR_ID(reverse) STRUCT_FOR_ID(reversed) @@ -718,6 +725,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(setsigmask) STRUCT_FOR_ID(setstate) STRUCT_FOR_ID(shape) + STRUCT_FOR_ID(shared) STRUCT_FOR_ID(show_cmd) STRUCT_FOR_ID(signed) STRUCT_FOR_ID(size) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 70a54f5273e446..2a60bc3d39c7dc 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -840,6 +840,7 @@ extern "C" { INIT_ID(call), \ INIT_ID(call_exception_handler), \ INIT_ID(call_soon), \ + INIT_ID(callable), \ INIT_ID(callback), \ INIT_ID(cancel), \ INIT_ID(capath), \ @@ -1004,6 +1005,7 @@ extern "C" { INIT_ID(identity_hint), \ INIT_ID(ignore), \ INIT_ID(imag), \ + INIT_ID(implieslink), \ INIT_ID(importlib), \ INIT_ID(in_fd), \ INIT_ID(include_aliases), \ @@ -1053,6 +1055,7 @@ extern "C" { INIT_ID(kw), \ INIT_ID(kw1), \ INIT_ID(kw2), \ + INIT_ID(kwargs), \ INIT_ID(kwdefaults), \ INIT_ID(label), \ INIT_ID(last), \ @@ -1169,6 +1172,7 @@ extern "C" { INIT_ID(pos1), \ INIT_ID(pos2), \ INIT_ID(posix), \ + INIT_ID(preserve_exc), \ INIT_ID(print_file_and_line), \ INIT_ID(priority), \ INIT_ID(progress), \ @@ -1196,9 +1200,12 @@ extern "C" { INIT_ID(reload), \ INIT_ID(repl), \ INIT_ID(replace), \ + INIT_ID(reqrefs), \ + INIT_ID(require_ready), \ INIT_ID(reserved), \ INIT_ID(reset), \ INIT_ID(resetids), \ + INIT_ID(restrict), \ INIT_ID(return), \ INIT_ID(reverse), \ INIT_ID(reversed), \ @@ -1225,6 +1232,7 @@ extern "C" { INIT_ID(setsigmask), \ INIT_ID(setstate), \ INIT_ID(shape), \ + INIT_ID(shared), \ INIT_ID(show_cmd), \ INIT_ID(signed), \ INIT_ID(size), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 89444f4fb83b94..f98ecd9d1a772f 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -1120,6 +1120,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(callable); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(callback); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1776,6 +1780,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(implieslink); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(importlib); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1972,6 +1980,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(kwargs); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(kwdefaults); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2436,6 +2448,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(preserve_exc); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(print_file_and_line); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2544,6 +2560,14 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(reqrefs); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(require_ready); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(reserved); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2556,6 +2580,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(restrict); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(return); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2660,6 +2688,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(shared); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(show_cmd); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); From be2fe0771b34ceb986e1cb29766bef506c9d4faa Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 07:00:30 +0100 Subject: [PATCH 24/27] Fix new_config_doc --- Modules/_interpretersmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 164e20ce0dff63..4ba5d29c3b7b8b 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -836,7 +836,7 @@ interp_new_config(PyObject *self, PyObject *args, PyObject *kwds) } PyDoc_STRVAR(new_config_doc, -"new_config($module, /, name='isolated', /, **overrides)\n\ +"new_config($module, name='isolated', /, **overrides)\n\ --\n\ \n\ Return a representation of a new PyInterpreterConfig.\n\ From 073e2ff62ebcbba8e134b839a00317313c2533c3 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 07:02:26 +0100 Subject: [PATCH 25/27] Undo docstring changes --- Modules/_interpretersmodule.c | 12 ++++++------ Modules/clinic/_interpretersmodule.c.h | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 4ba5d29c3b7b8b..c82c756982a61b 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -862,14 +862,14 @@ typically by using _interpreters.destroy(). This can be managed automatically by passing "reqrefs=True" and then using _incref() and _decref() appropriately. -*config* must be a valid interpreter config or the name of a +"config" must be a valid interpreter config or the name of a predefined config ('isolated' or 'legacy'). The default is 'isolated'. [clinic start generated code]*/ static PyObject * _interpreters_create_impl(PyObject *module, PyObject *configobj, int reqrefs) -/*[clinic end generated code: output=c1cc6835b1277c16 input=7d7dbdefcd992b7e]*/ +/*[clinic end generated code: output=c1cc6835b1277c16 input=74f4d259e9f6f3d0]*/ { PyInterpreterConfig config; if (config_from_object(configobj, &config) < 0) { @@ -1121,7 +1121,7 @@ This is equivalent to running the builtin exec() under the target interpreter, using the __dict__ of its __main__ module as both globals and locals. -*code* may be a string containing the text of a Python script. +"code" may be a string containing the text of a Python script. Functions (and code objects) are also supported, with some restrictions. The code/function must not take any arguments or be a closure @@ -1134,7 +1134,7 @@ is ignored, including its __globals__ dict. static PyObject * _interpreters_exec_impl(PyObject *module, PyObject *id, PyObject *code, PyObject *shared, int restricted) -/*[clinic end generated code: output=492057c4f10dc304 input=8e0199d4a220bbb8]*/ +/*[clinic end generated code: output=492057c4f10dc304 input=687f3f6ac5294593]*/ { PyThreadState *tstate = _PyThreadState_GET(); int reqready = 1; @@ -1511,13 +1511,13 @@ _interpreters.capture_exception Return a snapshot of an exception. -If *exc* is None then the current exception, if any, is used (but not cleared). +If "exc" is None then the current exception, if any, is used (but not cleared). The returned snapshot is the same as what _interpreters.exec() returns. [clinic start generated code]*/ static PyObject * _interpreters_capture_exception_impl(PyObject *module, PyObject *exc_arg) -/*[clinic end generated code: output=ef3f5393ef9c88a6 input=5ffe1ced0ec8e093]*/ +/*[clinic end generated code: output=ef3f5393ef9c88a6 input=e67d59d7fbb6d58c]*/ { PyObject *exc = exc_arg; if (exc == NULL || exc == Py_None) { diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 1c34a619a069e2..7e8a778b077650 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -19,7 +19,7 @@ PyDoc_STRVAR(_interpreters_create__doc__, "automatically by passing \"reqrefs=True\" and then using _incref() and\n" "_decref() appropriately.\n" "\n" -"*config* must be a valid interpreter config or the name of a\n" +"\"config\" must be a valid interpreter config or the name of a\n" "predefined config (\'isolated\' or \'legacy\'). The default\n" "is \'isolated\'."); @@ -348,7 +348,7 @@ PyDoc_STRVAR(_interpreters_exec__doc__, "interpreter, using the __dict__ of its __main__ module as both\n" "globals and locals.\n" "\n" -"*code* may be a string containing the text of a Python script.\n" +"\"code\" may be a string containing the text of a Python script.\n" "\n" "Functions (and code objects) are also supported, with some restrictions.\n" "The code/function must not take any arguments or be a closure\n" @@ -1038,7 +1038,7 @@ PyDoc_STRVAR(_interpreters_capture_exception__doc__, "\n" "Return a snapshot of an exception.\n" "\n" -"If *exc* is None then the current exception, if any, is used (but not cleared).\n" +"If \"exc\" is None then the current exception, if any, is used (but not cleared).\n" "The returned snapshot is the same as what _interpreters.exec() returns."); #define _INTERPRETERS_CAPTURE_EXCEPTION_METHODDEF \ @@ -1066,4 +1066,4 @@ _interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssiz exit: return return_value; } -/*[clinic end generated code: output=e0357d000b5dc81a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0d1ea84a676a7ac2 input=a9049054013a1b77]*/ From 1cdf313021bbeb524887e9cbe0ca83215ed986e5 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 07:03:25 +0100 Subject: [PATCH 26/27] Revert "Indicate positional-only parameters" This reverts commit eb21bb11 --- .../pycore_global_objects_fini_generated.h | 3 + Include/internal/pycore_global_strings.h | 3 + .../internal/pycore_runtime_init_generated.h | 3 + .../internal/pycore_unicodeobject_generated.h | 12 + Lib/test/test__interpreters.py | 2 +- Modules/_interpretersmodule.c | 48 ++-- Modules/clinic/_interpretersmodule.c.h | 257 +++++++++++++----- 7 files changed, 234 insertions(+), 94 deletions(-) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 7d3be37a5ed0e2..0132d6917547a7 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -878,6 +878,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(command)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(comment_factory)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(compile_mode)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(config)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(consts)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(context)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(contravariant)); @@ -936,6 +937,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(errors)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(event)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(eventmask)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_arg)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_type)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_value)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(excepthook)); @@ -1305,6 +1307,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(uid)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(unlink)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(unraisablehook)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(updates)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(uri)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(usedforsecurity)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(value)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 1da2c1e8b79427..d6d71a925c7b71 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -369,6 +369,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(command) STRUCT_FOR_ID(comment_factory) STRUCT_FOR_ID(compile_mode) + STRUCT_FOR_ID(config) STRUCT_FOR_ID(consts) STRUCT_FOR_ID(context) STRUCT_FOR_ID(contravariant) @@ -427,6 +428,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(errors) STRUCT_FOR_ID(event) STRUCT_FOR_ID(eventmask) + STRUCT_FOR_ID(exc_arg) STRUCT_FOR_ID(exc_type) STRUCT_FOR_ID(exc_value) STRUCT_FOR_ID(excepthook) @@ -796,6 +798,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(uid) STRUCT_FOR_ID(unlink) STRUCT_FOR_ID(unraisablehook) + STRUCT_FOR_ID(updates) STRUCT_FOR_ID(uri) STRUCT_FOR_ID(usedforsecurity) STRUCT_FOR_ID(value) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 2a60bc3d39c7dc..7f9abf941d7078 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -876,6 +876,7 @@ extern "C" { INIT_ID(command), \ INIT_ID(comment_factory), \ INIT_ID(compile_mode), \ + INIT_ID(config), \ INIT_ID(consts), \ INIT_ID(context), \ INIT_ID(contravariant), \ @@ -934,6 +935,7 @@ extern "C" { INIT_ID(errors), \ INIT_ID(event), \ INIT_ID(eventmask), \ + INIT_ID(exc_arg), \ INIT_ID(exc_type), \ INIT_ID(exc_value), \ INIT_ID(excepthook), \ @@ -1303,6 +1305,7 @@ extern "C" { INIT_ID(uid), \ INIT_ID(unlink), \ INIT_ID(unraisablehook), \ + INIT_ID(updates), \ INIT_ID(uri), \ INIT_ID(usedforsecurity), \ INIT_ID(value), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index f98ecd9d1a772f..9fc3c545b9c287 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -1264,6 +1264,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(config); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(consts); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1496,6 +1500,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(exc_arg); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(exc_type); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2972,6 +2980,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(updates); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(uri); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Lib/test/test__interpreters.py b/Lib/test/test__interpreters.py index 78f0778382de35..ec5a26bc1c05ad 100644 --- a/Lib/test/test__interpreters.py +++ b/Lib/test/test__interpreters.py @@ -486,7 +486,7 @@ def test_signatures(self): with self.assertRaisesRegex(TypeError, msg): _interpreters.run_func(self.id, lambda: None, shared=1) # See https://github.com/python/cpython/issues/135855 - msg = r'set___main___attrs\(\) argument 2 must be dict, not int' + msg = r"set___main___attrs\(\) argument 'updates' must be dict, not int" with self.assertRaisesRegex(TypeError, msg): _interpreters.set___main___attrs(self.id, 1) diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index c82c756982a61b..387a67f861a0ff 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -851,7 +851,6 @@ overriding the initial values."); /*[clinic input] _interpreters.create config as configobj: object(py_default="'isolated'") = NULL - / * reqrefs: bool = False @@ -869,7 +868,7 @@ is 'isolated'. static PyObject * _interpreters_create_impl(PyObject *module, PyObject *configobj, int reqrefs) -/*[clinic end generated code: output=c1cc6835b1277c16 input=74f4d259e9f6f3d0]*/ +/*[clinic end generated code: output=c1cc6835b1277c16 input=235ce396a23624d5]*/ { PyInterpreterConfig config; if (config_from_object(configobj, &config) < 0) { @@ -907,7 +906,6 @@ _interpreters_create_impl(PyObject *module, PyObject *configobj, int reqrefs) /*[clinic input] _interpreters.destroy id: object - / * restrict as restricted: bool = False @@ -919,7 +917,7 @@ So does an unrecognized ID. static PyObject * _interpreters_destroy_impl(PyObject *module, PyObject *id, int restricted) -/*[clinic end generated code: output=0bc20da8700ab4dd input=d2cfa1ef3b4a4ea5]*/ +/*[clinic end generated code: output=0bc20da8700ab4dd input=561bdd6537639d40]*/ { // Look up the interpreter. int reqready = 0; @@ -1034,8 +1032,7 @@ _interpreters_get_main_impl(PyObject *module) /*[clinic input] _interpreters.set___main___attrs id: object - ns as updates: object(subclass_of='&PyDict_Type') - / + updates: object(subclass_of='&PyDict_Type') * restrict as restricted: bool = False @@ -1045,7 +1042,7 @@ Bind the given attributes in the interpreter's __main__ module. static PyObject * _interpreters_set___main___attrs_impl(PyObject *module, PyObject *id, PyObject *updates, int restricted) -/*[clinic end generated code: output=f3803010cb452bf0 input=69d409c4dd04dab9]*/ +/*[clinic end generated code: output=f3803010cb452bf0 input=d16ab8d81371f86a]*/ { // Look up the interpreter. int reqready = 1; @@ -1109,7 +1106,6 @@ _handle_script_error(struct run_result *runres) /*[clinic input] _interpreters.exec id: object - / code: object shared: object(subclass_of='&PyDict_Type', c_default='NULL') = {} * @@ -1134,7 +1130,7 @@ is ignored, including its __globals__ dict. static PyObject * _interpreters_exec_impl(PyObject *module, PyObject *id, PyObject *code, PyObject *shared, int restricted) -/*[clinic end generated code: output=492057c4f10dc304 input=687f3f6ac5294593]*/ +/*[clinic end generated code: output=492057c4f10dc304 input=5a22c1ed0c5dbcf3]*/ { PyThreadState *tstate = _PyThreadState_GET(); int reqready = 1; @@ -1166,7 +1162,6 @@ _interpreters_exec_impl(PyObject *module, PyObject *id, PyObject *code, /*[clinic input] _interpreters.run_string id: object - / script: unicode shared: object(subclass_of='&PyDict_Type', c_default='NULL') = {} * @@ -1181,7 +1176,7 @@ static PyObject * _interpreters_run_string_impl(PyObject *module, PyObject *id, PyObject *script, PyObject *shared, int restricted) -/*[clinic end generated code: output=a30a64fb9ad396a2 input=9158a58996e05957]*/ +/*[clinic end generated code: output=a30a64fb9ad396a2 input=51ce549b9a8dbe21]*/ { #define FUNCNAME MODULE_NAME_STR ".run_string" PyThreadState *tstate = _PyThreadState_GET(); @@ -1218,7 +1213,6 @@ _interpreters_run_string_impl(PyObject *module, PyObject *id, /*[clinic input] _interpreters.run_func id: object - / func: object shared: object(subclass_of='&PyDict_Type', c_default='NULL') = {} * @@ -1235,7 +1229,7 @@ are not supported. Methods and other callables are not supported either. static PyObject * _interpreters_run_func_impl(PyObject *module, PyObject *id, PyObject *func, PyObject *shared, int restricted) -/*[clinic end generated code: output=131f7202ca4a0c5e input=aa2dbab6f7354cd6]*/ +/*[clinic end generated code: output=131f7202ca4a0c5e input=2d62bb9b9eaf4948]*/ { #define FUNCNAME MODULE_NAME_STR ".run_func" PyThreadState *tstate = _PyThreadState_GET(); @@ -1281,7 +1275,6 @@ _interpreters_run_func_impl(PyObject *module, PyObject *id, PyObject *func, /*[clinic input] _interpreters.call id: object - / callable: object args as args_obj: object(subclass_of='&PyTuple_Type', c_default='NULL') = () kwargs as kwargs_obj: object(subclass_of='&PyDict_Type', c_default='NULL') = {} @@ -1298,7 +1291,7 @@ static PyObject * _interpreters_call_impl(PyObject *module, PyObject *id, PyObject *callable, PyObject *args_obj, PyObject *kwargs_obj, int preserve_exc, int restricted) -/*[clinic end generated code: output=983ee27b3c43f6ef input=826c8dab4b1059b4]*/ +/*[clinic end generated code: output=983ee27b3c43f6ef input=77590fdb3f519d65]*/ { PyThreadState *tstate = _PyThreadState_GET(); int reqready = 1; @@ -1337,14 +1330,13 @@ _interpreters_call_impl(PyObject *module, PyObject *id, PyObject *callable, /*[clinic input] _interpreters.is_shareable obj: object - / Return True if the object's data may be shared between interpreters and False otherwise. [clinic start generated code]*/ static PyObject * -_interpreters_is_shareable(PyObject *module, PyObject *obj) -/*[clinic end generated code: output=f2169d4c1f5d7bca input=4239989a8634b292]*/ +_interpreters_is_shareable_impl(PyObject *module, PyObject *obj) +/*[clinic end generated code: output=227856926a22940b input=72b9a36bdf1d2a53]*/ { PyThreadState *tstate = _PyThreadState_GET(); if (_PyObject_CheckXIData(tstate, obj) == 0) { @@ -1358,7 +1350,6 @@ _interpreters_is_shareable(PyObject *module, PyObject *obj) /*[clinic input] _interpreters.is_running id: object - / * restrict as restricted: bool = False @@ -1367,7 +1358,7 @@ Return whether or not the identified interpreter is running. static PyObject * _interpreters_is_running_impl(PyObject *module, PyObject *id, int restricted) -/*[clinic end generated code: output=32a6225d5ded9bdb input=a4d98a82fcb4bf6e]*/ +/*[clinic end generated code: output=32a6225d5ded9bdb input=3291578d04231125]*/ { int reqready = 1; PyInterpreterState *interp = \ @@ -1386,7 +1377,6 @@ _interpreters_is_running_impl(PyObject *module, PyObject *id, int restricted) /*[clinic input] _interpreters.get_config id as idobj: object - / * restrict as restricted: bool = False @@ -1396,7 +1386,7 @@ Return a representation of the config used to initialize the interpreter. static PyObject * _interpreters_get_config_impl(PyObject *module, PyObject *idobj, int restricted) -/*[clinic end generated code: output=63f81d35c2fe1387 input=79d88cf77a8ba034]*/ +/*[clinic end generated code: output=63f81d35c2fe1387 input=aa38d50f534eb3c5]*/ { if (idobj == Py_None) { idobj = NULL; @@ -1427,14 +1417,13 @@ _interpreters_get_config_impl(PyObject *module, PyObject *idobj, /*[clinic input] _interpreters.whence id: object - / Return an identifier for where the interpreter was created. [clinic start generated code]*/ static PyObject * -_interpreters_whence(PyObject *module, PyObject *id) -/*[clinic end generated code: output=e558d207672470cf input=6148f02c882e39f6]*/ +_interpreters_whence_impl(PyObject *module, PyObject *id) +/*[clinic end generated code: output=ef2c21ab106c2c20 input=eeede0a2fbfa2968]*/ { PyInterpreterState *interp = look_up_interp(id); if (interp == NULL) { @@ -1449,7 +1438,6 @@ _interpreters_whence(PyObject *module, PyObject *id) /*[clinic input] _interpreters.incref id: object - / * implieslink: bool = False restrict as restricted: bool = False @@ -1459,7 +1447,7 @@ _interpreters.incref static PyObject * _interpreters_incref_impl(PyObject *module, PyObject *id, int implieslink, int restricted) -/*[clinic end generated code: output=eccaa4e03fbe8ee2 input=a49374f447dead6f]*/ +/*[clinic end generated code: output=eccaa4e03fbe8ee2 input=a0a614748f2e348c]*/ { int reqready = 1; PyInterpreterState *interp = \ @@ -1481,7 +1469,6 @@ _interpreters_incref_impl(PyObject *module, PyObject *id, int implieslink, /*[clinic input] _interpreters.decref id: object - / * restrict as restricted: bool = False @@ -1489,7 +1476,7 @@ _interpreters.decref static PyObject * _interpreters_decref_impl(PyObject *module, PyObject *id, int restricted) -/*[clinic end generated code: output=5c54db4b22086171 input=6f82beeae0b1c2b1]*/ +/*[clinic end generated code: output=5c54db4b22086171 input=c4aa34f09c44e62a]*/ { int reqready = 1; PyInterpreterState *interp = \ @@ -1507,7 +1494,6 @@ _interpreters_decref_impl(PyObject *module, PyObject *id, int restricted) /*[clinic input] _interpreters.capture_exception exc_arg: object(c_default='NULL') = None - / Return a snapshot of an exception. @@ -1517,7 +1503,7 @@ The returned snapshot is the same as what _interpreters.exec() returns. static PyObject * _interpreters_capture_exception_impl(PyObject *module, PyObject *exc_arg) -/*[clinic end generated code: output=ef3f5393ef9c88a6 input=e67d59d7fbb6d58c]*/ +/*[clinic end generated code: output=ef3f5393ef9c88a6 input=e607efac7eb95fba]*/ { PyObject *exc = exc_arg; if (exc == NULL || exc == Py_None) { diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index 7e8a778b077650..d4bd36ad15649d 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -9,7 +9,7 @@ preserve #include "pycore_modsupport.h" // _PyArg_UnpackKeywords() PyDoc_STRVAR(_interpreters_create__doc__, -"create($module, config=\'isolated\', /, *, reqrefs=False)\n" +"create($module, /, config=\'isolated\', *, reqrefs=False)\n" "--\n" "\n" "Create a new interpreter and return a unique generated ID.\n" @@ -35,7 +35,7 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 1 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -44,7 +44,7 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(reqrefs), }, + .ob_item = { &_Py_ID(config), &_Py_ID(reqrefs), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -53,7 +53,7 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "reqrefs", NULL}; + static const char * const _keywords[] = {"config", "reqrefs", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "create", @@ -70,12 +70,16 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, if (!args) { goto exit; } - if (nargs < 1) { - goto skip_optional_posonly; + if (!noptargs) { + goto skip_optional_pos; } - noptargs--; - configobj = args[0]; -skip_optional_posonly: + if (args[0]) { + configobj = args[0]; + if (!--noptargs) { + goto skip_optional_pos; + } + } +skip_optional_pos: if (!noptargs) { goto skip_optional_kwonly; } @@ -91,7 +95,7 @@ _interpreters_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } PyDoc_STRVAR(_interpreters_destroy__doc__, -"destroy($module, id, /, *, restrict=False)\n" +"destroy($module, /, id, *, restrict=False)\n" "--\n" "\n" "Destroy the identified interpreter.\n" @@ -111,7 +115,7 @@ _interpreters_destroy(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 1 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -120,7 +124,7 @@ _interpreters_destroy(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -129,7 +133,7 @@ _interpreters_destroy(PyObject *module, PyObject *const *args, Py_ssize_t nargs, # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "restrict", NULL}; + static const char * const _keywords[] = {"id", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "destroy", @@ -264,7 +268,7 @@ _interpreters_get_main(PyObject *module, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(_interpreters_set___main___attrs__doc__, -"set___main___attrs($module, id, ns, /, *, restrict=False)\n" +"set___main___attrs($module, /, id, updates, *, restrict=False)\n" "--\n" "\n" "Bind the given attributes in the interpreter\'s __main__ module."); @@ -282,7 +286,7 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 1 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -291,7 +295,7 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(id), &_Py_ID(updates), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -300,7 +304,7 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "", "restrict", NULL}; + static const char * const _keywords[] = {"id", "updates", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "set___main___attrs", @@ -320,7 +324,7 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi } id = args[0]; if (!PyDict_Check(args[1])) { - _PyArg_BadArgument("set___main___attrs", "argument 2", "dict", args[1]); + _PyArg_BadArgument("set___main___attrs", "argument 'updates'", "dict", args[1]); goto exit; } updates = args[1]; @@ -339,7 +343,7 @@ _interpreters_set___main___attrs(PyObject *module, PyObject *const *args, Py_ssi } PyDoc_STRVAR(_interpreters_exec__doc__, -"exec($module, id, /, code, shared={}, *, restrict=False)\n" +"exec($module, /, id, code, shared={}, *, restrict=False)\n" "--\n" "\n" "Execute the provided code in the identified interpreter.\n" @@ -370,7 +374,7 @@ _interpreters_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 3 + #define NUM_KEYWORDS 4 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -379,7 +383,7 @@ _interpreters_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(code), &_Py_ID(shared), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(id), &_Py_ID(code), &_Py_ID(shared), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -388,7 +392,7 @@ _interpreters_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "code", "shared", "restrict", NULL}; + static const char * const _keywords[] = {"id", "code", "shared", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "exec", @@ -438,7 +442,7 @@ _interpreters_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py } PyDoc_STRVAR(_interpreters_run_string__doc__, -"run_string($module, id, /, script, shared={}, *, restrict=False)\n" +"run_string($module, /, id, script, shared={}, *, restrict=False)\n" "--\n" "\n" "Execute the provided string in the identified interpreter.\n" @@ -459,7 +463,7 @@ _interpreters_run_string(PyObject *module, PyObject *const *args, Py_ssize_t nar PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 3 + #define NUM_KEYWORDS 4 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -468,7 +472,7 @@ _interpreters_run_string(PyObject *module, PyObject *const *args, Py_ssize_t nar } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(script), &_Py_ID(shared), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(id), &_Py_ID(script), &_Py_ID(shared), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -477,7 +481,7 @@ _interpreters_run_string(PyObject *module, PyObject *const *args, Py_ssize_t nar # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "script", "shared", "restrict", NULL}; + static const char * const _keywords[] = {"id", "script", "shared", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "run_string", @@ -531,7 +535,7 @@ _interpreters_run_string(PyObject *module, PyObject *const *args, Py_ssize_t nar } PyDoc_STRVAR(_interpreters_run_func__doc__, -"run_func($module, id, /, func, shared={}, *, restrict=False)\n" +"run_func($module, /, id, func, shared={}, *, restrict=False)\n" "--\n" "\n" "Execute the body of the provided function in the identified interpreter.\n" @@ -554,7 +558,7 @@ _interpreters_run_func(PyObject *module, PyObject *const *args, Py_ssize_t nargs PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 3 + #define NUM_KEYWORDS 4 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -563,7 +567,7 @@ _interpreters_run_func(PyObject *module, PyObject *const *args, Py_ssize_t nargs } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(func), &_Py_ID(shared), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(id), &_Py_ID(func), &_Py_ID(shared), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -572,7 +576,7 @@ _interpreters_run_func(PyObject *module, PyObject *const *args, Py_ssize_t nargs # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "func", "shared", "restrict", NULL}; + static const char * const _keywords[] = {"id", "func", "shared", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "run_func", @@ -622,7 +626,7 @@ _interpreters_run_func(PyObject *module, PyObject *const *args, Py_ssize_t nargs } PyDoc_STRVAR(_interpreters_call__doc__, -"call($module, id, /, callable, args=(), kwargs={}, *,\n" +"call($module, /, id, callable, args=(), kwargs={}, *,\n" " preserve_exc=False, restrict=False)\n" "--\n" "\n" @@ -644,7 +648,7 @@ _interpreters_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 5 + #define NUM_KEYWORDS 6 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -653,7 +657,7 @@ _interpreters_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(callable), &_Py_ID(args), &_Py_ID(kwargs), &_Py_ID(preserve_exc), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(id), &_Py_ID(callable), &_Py_ID(args), &_Py_ID(kwargs), &_Py_ID(preserve_exc), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -662,7 +666,7 @@ _interpreters_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "callable", "args", "kwargs", "preserve_exc", "restrict", NULL}; + static const char * const _keywords[] = {"id", "callable", "args", "kwargs", "preserve_exc", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "call", @@ -733,16 +737,65 @@ _interpreters_call(PyObject *module, PyObject *const *args, Py_ssize_t nargs, Py } PyDoc_STRVAR(_interpreters_is_shareable__doc__, -"is_shareable($module, obj, /)\n" +"is_shareable($module, /, obj)\n" "--\n" "\n" "Return True if the object\'s data may be shared between interpreters and False otherwise."); #define _INTERPRETERS_IS_SHAREABLE_METHODDEF \ - {"is_shareable", (PyCFunction)_interpreters_is_shareable, METH_O, _interpreters_is_shareable__doc__}, + {"is_shareable", _PyCFunction_CAST(_interpreters_is_shareable), METH_FASTCALL|METH_KEYWORDS, _interpreters_is_shareable__doc__}, + +static PyObject * +_interpreters_is_shareable_impl(PyObject *module, PyObject *obj); + +static PyObject * +_interpreters_is_shareable(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(obj), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"obj", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "is_shareable", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *obj; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + obj = args[0]; + return_value = _interpreters_is_shareable_impl(module, obj); + +exit: + return return_value; +} PyDoc_STRVAR(_interpreters_is_running__doc__, -"is_running($module, id, /, *, restrict=False)\n" +"is_running($module, /, id, *, restrict=False)\n" "--\n" "\n" "Return whether or not the identified interpreter is running."); @@ -759,7 +812,7 @@ _interpreters_is_running(PyObject *module, PyObject *const *args, Py_ssize_t nar PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 1 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -768,7 +821,7 @@ _interpreters_is_running(PyObject *module, PyObject *const *args, Py_ssize_t nar } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -777,7 +830,7 @@ _interpreters_is_running(PyObject *module, PyObject *const *args, Py_ssize_t nar # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "restrict", NULL}; + static const char * const _keywords[] = {"id", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "is_running", @@ -810,7 +863,7 @@ _interpreters_is_running(PyObject *module, PyObject *const *args, Py_ssize_t nar } PyDoc_STRVAR(_interpreters_get_config__doc__, -"get_config($module, id, /, *, restrict=False)\n" +"get_config($module, /, id, *, restrict=False)\n" "--\n" "\n" "Return a representation of the config used to initialize the interpreter."); @@ -828,7 +881,7 @@ _interpreters_get_config(PyObject *module, PyObject *const *args, Py_ssize_t nar PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 1 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -837,7 +890,7 @@ _interpreters_get_config(PyObject *module, PyObject *const *args, Py_ssize_t nar } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -846,7 +899,7 @@ _interpreters_get_config(PyObject *module, PyObject *const *args, Py_ssize_t nar # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "restrict", NULL}; + static const char * const _keywords[] = {"id", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "get_config", @@ -879,16 +932,65 @@ _interpreters_get_config(PyObject *module, PyObject *const *args, Py_ssize_t nar } PyDoc_STRVAR(_interpreters_whence__doc__, -"whence($module, id, /)\n" +"whence($module, /, id)\n" "--\n" "\n" "Return an identifier for where the interpreter was created."); #define _INTERPRETERS_WHENCE_METHODDEF \ - {"whence", (PyCFunction)_interpreters_whence, METH_O, _interpreters_whence__doc__}, + {"whence", _PyCFunction_CAST(_interpreters_whence), METH_FASTCALL|METH_KEYWORDS, _interpreters_whence__doc__}, + +static PyObject * +_interpreters_whence_impl(PyObject *module, PyObject *id); + +static PyObject * +_interpreters_whence(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(id), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"id", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "whence", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *id; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { + goto exit; + } + id = args[0]; + return_value = _interpreters_whence_impl(module, id); + +exit: + return return_value; +} PyDoc_STRVAR(_interpreters_incref__doc__, -"incref($module, id, /, *, implieslink=False, restrict=False)\n" +"incref($module, /, id, *, implieslink=False, restrict=False)\n" "--\n" "\n"); @@ -905,7 +1007,7 @@ _interpreters_incref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -914,7 +1016,7 @@ _interpreters_incref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(implieslink), &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(id), &_Py_ID(implieslink), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -923,7 +1025,7 @@ _interpreters_incref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "implieslink", "restrict", NULL}; + static const char * const _keywords[] = {"id", "implieslink", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "incref", @@ -966,7 +1068,7 @@ _interpreters_incref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } PyDoc_STRVAR(_interpreters_decref__doc__, -"decref($module, id, /, *, restrict=False)\n" +"decref($module, /, id, *, restrict=False)\n" "--\n" "\n"); @@ -982,7 +1084,7 @@ _interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 1 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD @@ -991,7 +1093,7 @@ _interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(restrict), }, + .ob_item = { &_Py_ID(id), &_Py_ID(restrict), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -1000,7 +1102,7 @@ _interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"", "restrict", NULL}; + static const char * const _keywords[] = {"id", "restrict", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "decref", @@ -1033,7 +1135,7 @@ _interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } PyDoc_STRVAR(_interpreters_capture_exception__doc__, -"capture_exception($module, exc_arg=None, /)\n" +"capture_exception($module, /, exc_arg=None)\n" "--\n" "\n" "Return a snapshot of an exception.\n" @@ -1042,28 +1144,59 @@ PyDoc_STRVAR(_interpreters_capture_exception__doc__, "The returned snapshot is the same as what _interpreters.exec() returns."); #define _INTERPRETERS_CAPTURE_EXCEPTION_METHODDEF \ - {"capture_exception", _PyCFunction_CAST(_interpreters_capture_exception), METH_FASTCALL, _interpreters_capture_exception__doc__}, + {"capture_exception", _PyCFunction_CAST(_interpreters_capture_exception), METH_FASTCALL|METH_KEYWORDS, _interpreters_capture_exception__doc__}, static PyObject * _interpreters_capture_exception_impl(PyObject *module, PyObject *exc_arg); static PyObject * -_interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +_interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + Py_hash_t ob_hash; + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_hash = -1, + .ob_item = { &_Py_ID(exc_arg), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"exc_arg", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "capture_exception", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; PyObject *exc_arg = NULL; - if (!_PyArg_CheckPositional("capture_exception", nargs, 0, 1)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, + /*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); + if (!args) { goto exit; } - if (nargs < 1) { - goto skip_optional; + if (!noptargs) { + goto skip_optional_pos; } exc_arg = args[0]; -skip_optional: +skip_optional_pos: return_value = _interpreters_capture_exception_impl(module, exc_arg); exit: return return_value; } -/*[clinic end generated code: output=0d1ea84a676a7ac2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b6dd60cfb082b53c input=a9049054013a1b77]*/ From e8f0b6ccba3ce5216f140ecc0e34e9d6b33aa47b Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Mon, 11 Aug 2025 07:08:17 +0100 Subject: [PATCH 27/27] Serhiy's review --- .../pycore_global_objects_fini_generated.h | 2 +- Include/internal/pycore_global_strings.h | 2 +- Include/internal/pycore_runtime_init_generated.h | 2 +- Include/internal/pycore_unicodeobject_generated.h | 2 +- Modules/_interpretersmodule.c | 12 ++++++------ Modules/clinic/_interpretersmodule.c.h | 14 +++++++------- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 0132d6917547a7..d8fefa16faf70f 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -937,7 +937,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(errors)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(event)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(eventmask)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_arg)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_type)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_value)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(excepthook)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index d6d71a925c7b71..b9207f46cd729d 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -428,7 +428,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(errors) STRUCT_FOR_ID(event) STRUCT_FOR_ID(eventmask) - STRUCT_FOR_ID(exc_arg) + STRUCT_FOR_ID(exc) STRUCT_FOR_ID(exc_type) STRUCT_FOR_ID(exc_value) STRUCT_FOR_ID(excepthook) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 7f9abf941d7078..254b02be1334bd 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -935,7 +935,7 @@ extern "C" { INIT_ID(errors), \ INIT_ID(event), \ INIT_ID(eventmask), \ - INIT_ID(exc_arg), \ + INIT_ID(exc), \ INIT_ID(exc_type), \ INIT_ID(exc_value), \ INIT_ID(excepthook), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 9fc3c545b9c287..f1f6bc48fdf1a3 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -1500,7 +1500,7 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); - string = &_Py_ID(exc_arg); + string = &_Py_ID(exc); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 387a67f861a0ff..c7a3d54a0b9a52 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -997,12 +997,12 @@ _interpreters_list_all_impl(PyObject *module, int reqready) /*[clinic input] _interpreters.get_current -Return the ID of current interpreter. +Return (ID, whence) of the current interpreter. [clinic start generated code]*/ static PyObject * _interpreters_get_current_impl(PyObject *module) -/*[clinic end generated code: output=03161c8fcc0136eb input=6d003c614eacc533]*/ +/*[clinic end generated code: output=03161c8fcc0136eb input=37fb2c067c14d543]*/ { PyInterpreterState *interp =_get_current_interp(); if (interp == NULL) { @@ -1016,12 +1016,12 @@ _interpreters_get_current_impl(PyObject *module) /*[clinic input] _interpreters.get_main -Return the ID of main interpreter. +Return (ID, whence) of the main interpreter. [clinic start generated code]*/ static PyObject * _interpreters_get_main_impl(PyObject *module) -/*[clinic end generated code: output=9647288aff735557 input=a05bdf890db4b223]*/ +/*[clinic end generated code: output=9647288aff735557 input=b4ace23ca562146f]*/ { PyInterpreterState *interp = _PyInterpreterState_Main(); assert(_PyInterpreterState_IsReady(interp)); @@ -1493,7 +1493,7 @@ _interpreters_decref_impl(PyObject *module, PyObject *id, int restricted) /*[clinic input] _interpreters.capture_exception - exc_arg: object(c_default='NULL') = None + exc as exc_arg: object = None Return a snapshot of an exception. @@ -1503,7 +1503,7 @@ The returned snapshot is the same as what _interpreters.exec() returns. static PyObject * _interpreters_capture_exception_impl(PyObject *module, PyObject *exc_arg) -/*[clinic end generated code: output=ef3f5393ef9c88a6 input=e607efac7eb95fba]*/ +/*[clinic end generated code: output=ef3f5393ef9c88a6 input=32045341e979bc9e]*/ { PyObject *exc = exc_arg; if (exc == NULL || exc == Py_None) { diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h index d4bd36ad15649d..a8f0d3df8908dc 100644 --- a/Modules/clinic/_interpretersmodule.c.h +++ b/Modules/clinic/_interpretersmodule.c.h @@ -235,7 +235,7 @@ PyDoc_STRVAR(_interpreters_get_current__doc__, "get_current($module, /)\n" "--\n" "\n" -"Return the ID of current interpreter."); +"Return (ID, whence) of the current interpreter."); #define _INTERPRETERS_GET_CURRENT_METHODDEF \ {"get_current", (PyCFunction)_interpreters_get_current, METH_NOARGS, _interpreters_get_current__doc__}, @@ -253,7 +253,7 @@ PyDoc_STRVAR(_interpreters_get_main__doc__, "get_main($module, /)\n" "--\n" "\n" -"Return the ID of main interpreter."); +"Return (ID, whence) of the main interpreter."); #define _INTERPRETERS_GET_MAIN_METHODDEF \ {"get_main", (PyCFunction)_interpreters_get_main, METH_NOARGS, _interpreters_get_main__doc__}, @@ -1135,7 +1135,7 @@ _interpreters_decref(PyObject *module, PyObject *const *args, Py_ssize_t nargs, } PyDoc_STRVAR(_interpreters_capture_exception__doc__, -"capture_exception($module, /, exc_arg=None)\n" +"capture_exception($module, /, exc=None)\n" "--\n" "\n" "Return a snapshot of an exception.\n" @@ -1164,7 +1164,7 @@ _interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssiz } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) .ob_hash = -1, - .ob_item = { &_Py_ID(exc_arg), }, + .ob_item = { &_Py_ID(exc), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -1173,7 +1173,7 @@ _interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssiz # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"exc_arg", NULL}; + static const char * const _keywords[] = {"exc", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "capture_exception", @@ -1182,7 +1182,7 @@ _interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssiz #undef KWTUPLE PyObject *argsbuf[1]; Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0; - PyObject *exc_arg = NULL; + PyObject *exc_arg = Py_None; args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, /*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf); @@ -1199,4 +1199,4 @@ _interpreters_capture_exception(PyObject *module, PyObject *const *args, Py_ssiz exit: return return_value; } -/*[clinic end generated code: output=b6dd60cfb082b53c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cf3f54caaa2dd6a2 input=a9049054013a1b77]*/