summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2023-08-31 11:53:19 (GMT)
committerGitHub <noreply@github.com>2023-08-31 11:53:19 (GMT)
commit79823c103b66030f10e07e04a5462f101674a4fc (patch)
tree9deb7f8c1c2cc2db31fa7613ea1e7844b4bb2768
parent059bd4d299b384d2b434ccb106f91cb4bb03bbb1 (diff)
downloadcpython-79823c103b66030f10e07e04a5462f101674a4fc.zip
cpython-79823c103b66030f10e07e04a5462f101674a4fc.tar.gz
cpython-79823c103b66030f10e07e04a5462f101674a4fc.tar.bz2
gh-106320: Remove private _PyErr_ChainExceptions() (#108713)
Remove _PyErr_ChainExceptions(), _PyErr_ChainExceptions1() and _PyErr_SetFromPyStatus() functions from the public C API. * Move the private _PyErr_ChainExceptions() and _PyErr_ChainExceptions1() function to the internal C API (pycore_pyerrors.h). * Move the private _PyErr_SetFromPyStatus() to the internal C API (pycore_initconfig.h). * No longer export the _PyErr_ChainExceptions() function. * Move run_in_subinterp_with_config() from _testcapi to _testinternalcapi.
-rw-r--r--Include/cpython/initconfig.h1
-rw-r--r--Include/cpython/pyerrors.h5
-rw-r--r--Include/internal/pycore_initconfig.h4
-rw-r--r--Include/internal/pycore_pyerrors.h7
-rw-r--r--Lib/test/support/__init__.py4
-rw-r--r--Lib/test/test_import/__init__.py8
-rw-r--r--Modules/_io/_iomodule.c1
-rw-r--r--Modules/_io/fileio.c1
-rw-r--r--Modules/_io/iobase.c2
-rw-r--r--Modules/_io/textio.c3
-rw-r--r--Modules/_sqlite/connection.c2
-rw-r--r--Modules/_ssl.c1
-rw-r--r--Modules/_testcapimodule.c101
-rw-r--r--Modules/_testinternalcapi.c103
-rw-r--r--Modules/_xxsubinterpretersmodule.c6
-rw-r--r--Modules/_zoneinfo.c2
-rw-r--r--Objects/odictobject.c5
-rw-r--r--Objects/weakrefobject.c1
18 files changed, 140 insertions, 117 deletions
diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h
index cbae97f..7fb7a98 100644
--- a/Include/cpython/initconfig.h
+++ b/Include/cpython/initconfig.h
@@ -25,7 +25,6 @@ PyAPI_FUNC(PyStatus) PyStatus_Exit(int exitcode);
PyAPI_FUNC(int) PyStatus_IsError(PyStatus err);
PyAPI_FUNC(int) PyStatus_IsExit(PyStatus err);
PyAPI_FUNC(int) PyStatus_Exception(PyStatus err);
-PyAPI_FUNC(PyObject *) _PyErr_SetFromPyStatus(PyStatus status);
/* --- PyWideStringList ------------------------------------------------ */
diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h
index cbe3be1..9633a54 100644
--- a/Include/cpython/pyerrors.h
+++ b/Include/cpython/pyerrors.h
@@ -88,11 +88,6 @@ typedef PyOSErrorObject PyEnvironmentErrorObject;
typedef PyOSErrorObject PyWindowsErrorObject;
#endif
-/* Context manipulation (PEP 3134) */
-
-Py_DEPRECATED(3.12) PyAPI_FUNC(void) _PyErr_ChainExceptions(PyObject *, PyObject *, PyObject *);
-PyAPI_FUNC(void) _PyErr_ChainExceptions1(PyObject *);
-
/* In exceptions.c */
PyAPI_FUNC(PyObject*) PyUnstable_Exc_PrepReraiseStar(
diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h
index c9645c7..6439101 100644
--- a/Include/internal/pycore_initconfig.h
+++ b/Include/internal/pycore_initconfig.h
@@ -44,6 +44,10 @@ struct pyruntimestate;
#define _PyStatus_UPDATE_FUNC(err) \
do { (err).func = _PyStatus_GET_FUNC(); } while (0)
+// Export for '_testinternalcapi' shared extension
+PyAPI_FUNC(PyObject *) _PyErr_SetFromPyStatus(PyStatus status);
+
+
/* --- PyWideStringList ------------------------------------------------ */
#define _PyWideStringList_INIT (PyWideStringList){.length = 0, .items = NULL}
diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h
index 0bc2058..0f16fb8 100644
--- a/Include/internal/pycore_pyerrors.h
+++ b/Include/internal/pycore_pyerrors.h
@@ -163,6 +163,13 @@ PyAPI_FUNC(Py_ssize_t) _Py_UTF8_Edit_Cost(PyObject *str_a, PyObject *str_b,
void _PyErr_FormatNote(const char *format, ...);
+/* Context manipulation (PEP 3134) */
+
+Py_DEPRECATED(3.12) extern void _PyErr_ChainExceptions(PyObject *, PyObject *, PyObject *);
+
+// Export for '_zoneinfo' shared extension
+PyAPI_FUNC(void) _PyErr_ChainExceptions1(PyObject *);
+
#ifdef __cplusplus
}
#endif
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 328bddb..c3f8527 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -1821,11 +1821,11 @@ def run_in_subinterp_with_config(code, *, own_gil=None, **config):
module is enabled.
"""
_check_tracemalloc()
- import _testcapi
+ import _testinternalcapi
if own_gil is not None:
assert 'gil' not in config, (own_gil, config)
config['gil'] = 2 if own_gil else 1
- return _testcapi.run_in_subinterp_with_config(code, **config)
+ return _testinternalcapi.run_in_subinterp_with_config(code, **config)
def _check_tracemalloc():
diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py
index 051711b..740ce7d 100644
--- a/Lib/test/test_import/__init__.py
+++ b/Lib/test/test_import/__init__.py
@@ -1805,12 +1805,12 @@ class SubinterpImportTests(unittest.TestCase):
check_multi_interp_extensions=strict,
)
_, out, err = script_helper.assert_python_ok('-c', textwrap.dedent(f'''
- import _testcapi, sys
+ import _testinternalcapi, sys
assert (
{name!r} in sys.builtin_module_names or
{name!r} not in sys.modules
), repr({name!r})
- ret = _testcapi.run_in_subinterp_with_config(
+ ret = _testinternalcapi.run_in_subinterp_with_config(
{self.import_script(name, "sys.stdout.fileno()")!r},
**{kwargs},
)
@@ -1829,9 +1829,9 @@ class SubinterpImportTests(unittest.TestCase):
check_multi_interp_extensions=True,
)
_, out, err = script_helper.assert_python_ok('-c', textwrap.dedent(f'''
- import _testcapi, sys
+ import _testinternalcapi, sys
assert {name!r} not in sys.modules, {name!r}
- ret = _testcapi.run_in_subinterp_with_config(
+ ret = _testinternalcapi.run_in_subinterp_with_config(
{self.import_script(name, "sys.stdout.fileno()")!r},
**{kwargs},
)
diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c
index 0762e26..cc84452 100644
--- a/Modules/_io/_iomodule.c
+++ b/Modules/_io/_iomodule.c
@@ -10,6 +10,7 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyNumber_Index()
#include "pycore_initconfig.h" // _PyStatus_OK()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "_iomodule.h"
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c
index 15df1b2..fb41670 100644
--- a/Modules/_io/fileio.c
+++ b/Modules/_io/fileio.c
@@ -3,6 +3,7 @@
#include "Python.h"
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include <stdbool.h>
#ifdef HAVE_SYS_TYPES_H
diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c
index 55508a2..34fcd70 100644
--- a/Modules/_io/iobase.c
+++ b/Modules/_io/iobase.c
@@ -12,6 +12,8 @@
#include "pycore_call.h" // _PyObject_CallMethod()
#include "pycore_long.h" // _PyLong_GetOne()
#include "pycore_object.h" // _PyType_HasFeature()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
+
#include <stddef.h> // offsetof()
#include "_iomodule.h"
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 8e44d45..0a727a6 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -9,10 +9,11 @@
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallMethod()
#include "pycore_codecs.h" // _PyCodecInfo_GetIncrementalDecoder()
+#include "pycore_fileutils.h" // _Py_GetLocaleEncoding()
#include "pycore_interp.h" // PyInterpreterState.fs_codec
#include "pycore_long.h" // _PyLong_GetZero()
-#include "pycore_fileutils.h" // _Py_GetLocaleEncoding()
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "_iomodule.h"
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 24090b0..21bdbc1 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -33,7 +33,9 @@
#include "blob.h"
#include "prepare_protocol.h"
#include "util.h"
+
#include "pycore_import.h" // _PyImport_GetModuleAttrString()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
#include "pycore_weakref.h" // _PyWeakref_IS_DEAD()
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index be03325..cecc378 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -27,6 +27,7 @@
#include "Python.h"
#include "pycore_fileutils.h" // _PyIsSelectable_fd()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
/* Include symbols from _socket module */
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 20b9632..d5c8a9d 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -1434,104 +1434,6 @@ run_in_subinterp(PyObject *self, PyObject *args)
return PyLong_FromLong(r);
}
-/* To run some code in a sub-interpreter. */
-static PyObject *
-run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- const char *code;
- int use_main_obmalloc = -1;
- int allow_fork = -1;
- int allow_exec = -1;
- int allow_threads = -1;
- int allow_daemon_threads = -1;
- int check_multi_interp_extensions = -1;
- int gil = -1;
- int r;
- PyThreadState *substate, *mainstate;
- /* only initialise 'cflags.cf_flags' to test backwards compatibility */
- PyCompilerFlags cflags = {0};
-
- static char *kwlist[] = {"code",
- "use_main_obmalloc",
- "allow_fork",
- "allow_exec",
- "allow_threads",
- "allow_daemon_threads",
- "check_multi_interp_extensions",
- "gil",
- NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "s$ppppppi:run_in_subinterp_with_config", kwlist,
- &code, &use_main_obmalloc,
- &allow_fork, &allow_exec,
- &allow_threads, &allow_daemon_threads,
- &check_multi_interp_extensions,
- &gil)) {
- return NULL;
- }
- if (use_main_obmalloc < 0) {
- PyErr_SetString(PyExc_ValueError, "missing use_main_obmalloc");
- return NULL;
- }
- if (allow_fork < 0) {
- PyErr_SetString(PyExc_ValueError, "missing allow_fork");
- return NULL;
- }
- if (allow_exec < 0) {
- PyErr_SetString(PyExc_ValueError, "missing allow_exec");
- return NULL;
- }
- if (allow_threads < 0) {
- PyErr_SetString(PyExc_ValueError, "missing allow_threads");
- return NULL;
- }
- if (gil < 0) {
- PyErr_SetString(PyExc_ValueError, "missing gil");
- return NULL;
- }
- if (allow_daemon_threads < 0) {
- PyErr_SetString(PyExc_ValueError, "missing allow_daemon_threads");
- return NULL;
- }
- if (check_multi_interp_extensions < 0) {
- PyErr_SetString(PyExc_ValueError, "missing check_multi_interp_extensions");
- return NULL;
- }
-
- mainstate = PyThreadState_Get();
-
- PyThreadState_Swap(NULL);
-
- const PyInterpreterConfig config = {
- .use_main_obmalloc = use_main_obmalloc,
- .allow_fork = allow_fork,
- .allow_exec = allow_exec,
- .allow_threads = allow_threads,
- .allow_daemon_threads = allow_daemon_threads,
- .check_multi_interp_extensions = check_multi_interp_extensions,
- .gil = gil,
- };
- PyStatus status = Py_NewInterpreterFromConfig(&substate, &config);
- if (PyStatus_Exception(status)) {
- /* Since no new thread state was created, there is no exception to
- propagate; raise a fresh one after swapping in the old thread
- state. */
- PyThreadState_Swap(mainstate);
- _PyErr_SetFromPyStatus(status);
- PyObject *exc = PyErr_GetRaisedException();
- PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
- _PyErr_ChainExceptions1(exc);
- return NULL;
- }
- assert(substate != NULL);
- r = PyRun_SimpleStringFlags(code, &cflags);
- Py_EndInterpreter(substate);
-
- PyThreadState_Swap(mainstate);
-
- return PyLong_FromLong(r);
-}
-
static void
_xid_capsule_destructor(PyObject *capsule)
{
@@ -3376,9 +3278,6 @@ static PyMethodDef TestMethods[] = {
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
{"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS},
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
- {"run_in_subinterp_with_config",
- _PyCFunction_CAST(run_in_subinterp_with_config),
- METH_VARARGS | METH_KEYWORDS},
{"get_crossinterp_data", get_crossinterp_data, METH_VARARGS},
{"restore_crossinterp_data", restore_crossinterp_data, METH_VARARGS},
{"create_cfunction", create_cfunction, METH_NOARGS},
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index 3e3dfec..e375ca8 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -25,6 +25,7 @@
#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy()
#include "pycore_object.h" // _PyObject_IsFreed()
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_pyerrors.h" // _Py_UTF8_Edit_Cost()
#include "pycore_pystate.h" // _PyThreadState_GET()
@@ -1593,6 +1594,105 @@ dict_getitem_knownhash(PyObject *self, PyObject *args)
}
+/* To run some code in a sub-interpreter. */
+static PyObject *
+run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ const char *code;
+ int use_main_obmalloc = -1;
+ int allow_fork = -1;
+ int allow_exec = -1;
+ int allow_threads = -1;
+ int allow_daemon_threads = -1;
+ int check_multi_interp_extensions = -1;
+ int gil = -1;
+ int r;
+ PyThreadState *substate, *mainstate;
+ /* only initialise 'cflags.cf_flags' to test backwards compatibility */
+ PyCompilerFlags cflags = {0};
+
+ static char *kwlist[] = {"code",
+ "use_main_obmalloc",
+ "allow_fork",
+ "allow_exec",
+ "allow_threads",
+ "allow_daemon_threads",
+ "check_multi_interp_extensions",
+ "gil",
+ NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "s$ppppppi:run_in_subinterp_with_config", kwlist,
+ &code, &use_main_obmalloc,
+ &allow_fork, &allow_exec,
+ &allow_threads, &allow_daemon_threads,
+ &check_multi_interp_extensions,
+ &gil)) {
+ return NULL;
+ }
+ if (use_main_obmalloc < 0) {
+ PyErr_SetString(PyExc_ValueError, "missing use_main_obmalloc");
+ return NULL;
+ }
+ if (allow_fork < 0) {
+ PyErr_SetString(PyExc_ValueError, "missing allow_fork");
+ return NULL;
+ }
+ if (allow_exec < 0) {
+ PyErr_SetString(PyExc_ValueError, "missing allow_exec");
+ return NULL;
+ }
+ if (allow_threads < 0) {
+ PyErr_SetString(PyExc_ValueError, "missing allow_threads");
+ return NULL;
+ }
+ if (gil < 0) {
+ PyErr_SetString(PyExc_ValueError, "missing gil");
+ return NULL;
+ }
+ if (allow_daemon_threads < 0) {
+ PyErr_SetString(PyExc_ValueError, "missing allow_daemon_threads");
+ return NULL;
+ }
+ if (check_multi_interp_extensions < 0) {
+ PyErr_SetString(PyExc_ValueError, "missing check_multi_interp_extensions");
+ return NULL;
+ }
+
+ mainstate = PyThreadState_Get();
+
+ PyThreadState_Swap(NULL);
+
+ const PyInterpreterConfig config = {
+ .use_main_obmalloc = use_main_obmalloc,
+ .allow_fork = allow_fork,
+ .allow_exec = allow_exec,
+ .allow_threads = allow_threads,
+ .allow_daemon_threads = allow_daemon_threads,
+ .check_multi_interp_extensions = check_multi_interp_extensions,
+ .gil = gil,
+ };
+ PyStatus status = Py_NewInterpreterFromConfig(&substate, &config);
+ if (PyStatus_Exception(status)) {
+ /* Since no new thread state was created, there is no exception to
+ propagate; raise a fresh one after swapping in the old thread
+ state. */
+ PyThreadState_Swap(mainstate);
+ _PyErr_SetFromPyStatus(status);
+ PyObject *exc = PyErr_GetRaisedException();
+ PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
+ _PyErr_ChainExceptions1(exc);
+ return NULL;
+ }
+ assert(substate != NULL);
+ r = PyRun_SimpleStringFlags(code, &cflags);
+ Py_EndInterpreter(substate);
+
+ PyThreadState_Swap(mainstate);
+
+ return PyLong_FromLong(r);
+}
+
+
static PyMethodDef module_functions[] = {
{"get_configs", get_configs, METH_NOARGS},
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -1659,6 +1759,9 @@ static PyMethodDef module_functions[] = {
{"get_object_dict_values", get_object_dict_values, METH_O},
{"hamt", new_hamt, METH_NOARGS},
{"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS},
+ {"run_in_subinterp_with_config",
+ _PyCFunction_CAST(run_in_subinterp_with_config),
+ METH_VARARGS | METH_KEYWORDS},
{NULL, NULL} /* sentinel */
};
diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c
index ea91e70..6638c2c 100644
--- a/Modules/_xxsubinterpretersmodule.c
+++ b/Modules/_xxsubinterpretersmodule.c
@@ -1,7 +1,13 @@
/* interpreters module */
/* low-level access to interpreter primitives */
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
#include "Python.h"
+#include "pycore_initconfig.h" // _PyErr_SetFromPyStatus()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "interpreteridobject.h"
diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c
index fb0b4b4..09f5fd4 100644
--- a/Modules/_zoneinfo.c
+++ b/Modules/_zoneinfo.c
@@ -4,7 +4,7 @@
#include "Python.h"
#include "pycore_long.h" // _PyLong_GetOne()
-
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include <ctype.h>
#include <stddef.h>
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index d7a0f91..b998963 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -465,10 +465,11 @@ later:
*/
#include "Python.h"
-#include "pycore_ceval.h" // _PyEval_GetBuiltin()
#include "pycore_call.h" // _PyObject_CallNoArgs()
-#include "pycore_object.h" // _PyObject_GC_UNTRACK()
+#include "pycore_ceval.h" // _PyEval_GetBuiltin()
#include "pycore_dict.h" // _Py_dict_lookup()
+#include "pycore_object.h" // _PyObject_GC_UNTRACK()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include <stddef.h> // offsetof()
#include "clinic/odictobject.c.h"
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index 1814c6e..df74be6 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -1,6 +1,7 @@
#include "Python.h"
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _PyObject_GET_WEAKREFS_LISTPTR()
+#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_weakref.h" // _PyWeakref_GET_REF()