]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-137630: Convert ``_interpreters`` to use Argument Clinic (#137631)
authorAdam Turner <9087854+AA-Turner@users.noreply.github.com>
Tue, 12 Aug 2025 15:23:13 +0000 (16:23 +0100)
committerGitHub <noreply@github.com>
Tue, 12 Aug 2025 15:23:13 +0000 (16:23 +0100)
Include/internal/pycore_global_objects_fini_generated.h
Include/internal/pycore_global_strings.h
Include/internal/pycore_runtime_init_generated.h
Include/internal/pycore_unicodeobject_generated.h
Lib/test/test__interpreters.py
Misc/NEWS.d/next/Library/2025-08-11-05-05-08.gh-issue-137630.9lmqyc.rst [new file with mode: 0644]
Modules/_interpretersmodule.c
Modules/clinic/_interpretersmodule.c.h [new file with mode: 0644]

index ca4744789f1c23523bea362c0cb8d0a62d28f4e2..d8fefa16faf70f13474f5805d37da9cab9803b8a 100644 (file)
@@ -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));
@@ -877,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));
@@ -935,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));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_type));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exc_value));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(excepthook));
@@ -1006,6 +1009,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 +1059,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 +1176,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 +1204,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 +1236,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));
@@ -1297,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));
index 47bb6fcecc1ba652126e4934b63989ff7641e2f6..b9207f46cd729dc8159a67b35f309d67f9a7fc45 100644 (file)
@@ -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)
@@ -368,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)
@@ -426,6 +428,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(errors)
         STRUCT_FOR_ID(event)
         STRUCT_FOR_ID(eventmask)
+        STRUCT_FOR_ID(exc)
         STRUCT_FOR_ID(exc_type)
         STRUCT_FOR_ID(exc_value)
         STRUCT_FOR_ID(excepthook)
@@ -497,6 +500,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 +550,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 +667,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 +695,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 +727,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)
@@ -788,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)
index 70a54f5273e44654ccc18b0916d2c62a94e7abdd..254b02be1334bd5e07ff61901d3b2643812a58a8 100644 (file)
@@ -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), \
@@ -875,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), \
@@ -933,6 +935,7 @@ extern "C" {
     INIT_ID(errors), \
     INIT_ID(event), \
     INIT_ID(eventmask), \
+    INIT_ID(exc), \
     INIT_ID(exc_type), \
     INIT_ID(exc_value), \
     INIT_ID(excepthook), \
@@ -1004,6 +1007,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 +1057,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 +1174,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 +1202,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 +1234,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), \
@@ -1295,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), \
index 89444f4fb83b94a35ff943baa3672bbbdb51ab34..f1f6bc48fdf1a3d6d2a0b62a5b232ac46aa4cec5 100644 (file)
@@ -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));
@@ -1260,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));
@@ -1492,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);
+    _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));
@@ -1776,6 +1788,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 +1988,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 +2456,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 +2568,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 +2588,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 +2696,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));
@@ -2940,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));
index a32d5d81d2bf2da7fd1b5c75810d83c7121bb888..ec5a26bc1c05ad895da5587aae4cc7d9be15a938 100644 (file)
@@ -474,19 +474,19 @@ class CommonTests(TestBase):
 
     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 'updates' must be dict, not int"
         with self.assertRaisesRegex(TypeError, msg):
             _interpreters.set___main___attrs(self.id, 1)
 
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 (file)
index 0000000..94d836c
--- /dev/null
@@ -0,0 +1,2 @@
+The :mod:`!_interpreters` module now uses Argument Clinic to parse arguments.
+Patch by Adam Turner.
index faf3b25b68c4eb3eec231bc7a601bbba016f34be..c7a3d54a0b9a5205b97347fba1a66236b8aaf99c 100644 (file)
 
 #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)
 {
@@ -797,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;
     }
@@ -830,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\
@@ -841,17 +848,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=235ce396a23624d5]*/
 {
-    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,34 +903,22 @@ 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\".");
+/*[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 = \
@@ -946,27 +952,19 @@ 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.");
 
+/*[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;
@@ -995,14 +993,16 @@ 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.");
 
+/*[clinic input]
+_interpreters.get_current
+
+Return (ID, whence) of the 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=37fb2c067c14d543]*/
 {
     PyInterpreterState *interp =_get_current_interp();
     if (interp == NULL) {
@@ -1012,39 +1012,38 @@ 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.");
 
+/*[clinic input]
+_interpreters.get_main
+
+Return (ID, whence) of the 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=b4ace23ca562146f]*/
 {
     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.");
 
+/*[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 = \
@@ -1091,11 +1090,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)
@@ -1109,23 +1103,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");
@@ -1150,43 +1157,29 @@ 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.");
+/*[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=51ce549b9a8dbe21]*/
 {
 #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");
@@ -1217,30 +1210,29 @@ 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().");
+/*[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");
@@ -1280,37 +1272,28 @@ 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().");
+/*[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");
@@ -1341,26 +1324,20 @@ finally:
     _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.");
 
+/*[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;
@@ -1369,26 +1346,20 @@ 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.");
 
+/*[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");
@@ -1402,24 +1373,21 @@ 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.");
 
+/*[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;
     }
@@ -1445,23 +1413,18 @@ 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.");
 
+/*[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;
@@ -1471,26 +1434,21 @@ 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.");
 
+/*[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");
@@ -1508,18 +1466,18 @@ interp_incref(PyObject *self, PyObject *args, PyObject *kwds)
 }
 
 
+/*[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");
@@ -1533,18 +1491,20 @@ interp_decref(PyObject *self, PyObject *args, PyObject *kwds)
 }
 
 
+/*[clinic input]
+_interpreters.capture_exception
+    exc as exc_arg: object = 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=32045341e979bc9e]*/
 {
-    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();
@@ -1592,58 +1552,33 @@ finally:
     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),
      METH_VARARGS | METH_KEYWORDS, new_config_doc},
 
-    {"create",                    _PyCFunction_CAST(interp_create),
-     METH_VARARGS | METH_KEYWORDS, create_doc},
-    {"destroy",                   _PyCFunction_CAST(interp_destroy),
-     METH_VARARGS | METH_KEYWORDS, destroy_doc},
-    {"list_all",                  _PyCFunction_CAST(interp_list_all),
-     METH_VARARGS | METH_KEYWORDS, list_all_doc},
-    {"get_current",               interp_get_current,
-     METH_NOARGS, get_current_doc},
-    {"get_main",                  interp_get_main,
-     METH_NOARGS, get_main_doc},
-
-    {"is_running",                _PyCFunction_CAST(interp_is_running),
-     METH_VARARGS | METH_KEYWORDS, is_running_doc},
-    {"get_config",                _PyCFunction_CAST(interp_get_config),
-     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},
-    {"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},
-    {"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},
-
-    {"incref",                    _PyCFunction_CAST(interp_incref),
-     METH_VARARGS | METH_KEYWORDS, NULL},
-    {"decref",                    _PyCFunction_CAST(interp_decref),
-     METH_VARARGS | METH_KEYWORDS, NULL},
-
-    {"is_shareable",              _PyCFunction_CAST(object_is_shareable),
-     METH_VARARGS | METH_KEYWORDS, is_shareable_doc},
-
-    {"capture_exception",         _PyCFunction_CAST(capture_exception),
-     METH_VARARGS | METH_KEYWORDS, capture_exception_doc},
+    _INTERPRETERS_CREATE_METHODDEF
+    _INTERPRETERS_DESTROY_METHODDEF
+    _INTERPRETERS_LIST_ALL_METHODDEF
+    _INTERPRETERS_GET_CURRENT_METHODDEF
+    _INTERPRETERS_GET_MAIN_METHODDEF
+
+    _INTERPRETERS_IS_RUNNING_METHODDEF
+    _INTERPRETERS_GET_CONFIG_METHODDEF
+    _INTERPRETERS_WHENCE_METHODDEF
+    _INTERPRETERS_EXEC_METHODDEF
+    _INTERPRETERS_CALL_METHODDEF
+    _INTERPRETERS_RUN_STRING_METHODDEF
+    _INTERPRETERS_RUN_FUNC_METHODDEF
+
+    _INTERPRETERS_SET___MAIN___ATTRS_METHODDEF
+
+    _INTERPRETERS_INCREF_METHODDEF
+    _INTERPRETERS_DECREF_METHODDEF
+
+    _INTERPRETERS_IS_SHAREABLE_METHODDEF
+
+    _INTERPRETERS_CAPTURE_EXCEPTION_METHODDEF
 
     {NULL,                        NULL}           /* sentinel */
 };
diff --git a/Modules/clinic/_interpretersmodule.c.h b/Modules/clinic/_interpretersmodule.c.h
new file mode 100644 (file)
index 0000000..a8f0d3d
--- /dev/null
@@ -0,0 +1,1202 @@
+/*[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;
+}
+
+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;
+}
+
+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;
+}
+
+PyDoc_STRVAR(_interpreters_get_current__doc__,
+"get_current($module, /)\n"
+"--\n"
+"\n"
+"Return (ID, whence) of the 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);
+}
+
+PyDoc_STRVAR(_interpreters_get_main__doc__,
+"get_main($module, /)\n"
+"--\n"
+"\n"
+"Return (ID, whence) of the 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);
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+PyDoc_STRVAR(_interpreters_capture_exception__doc__,
+"capture_exception($module, /, exc=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), },
+    };
+    #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", 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 = Py_None;
+
+    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=cf3f54caaa2dd6a2 input=a9049054013a1b77]*/