]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-106320: Remove private _PyErr_ChainExceptions() (#108713)
authorVictor Stinner <vstinner@python.org>
Thu, 31 Aug 2023 11:53:19 +0000 (13:53 +0200)
committerGitHub <noreply@github.com>
Thu, 31 Aug 2023 11:53:19 +0000 (13:53 +0200)
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.

18 files changed:
Include/cpython/initconfig.h
Include/cpython/pyerrors.h
Include/internal/pycore_initconfig.h
Include/internal/pycore_pyerrors.h
Lib/test/support/__init__.py
Lib/test/test_import/__init__.py
Modules/_io/_iomodule.c
Modules/_io/fileio.c
Modules/_io/iobase.c
Modules/_io/textio.c
Modules/_sqlite/connection.c
Modules/_ssl.c
Modules/_testcapimodule.c
Modules/_testinternalcapi.c
Modules/_xxsubinterpretersmodule.c
Modules/_zoneinfo.c
Objects/odictobject.c
Objects/weakrefobject.c

index cbae97f12f5377f313dc269e170807ad97ec170a..7fb7a9868be9261159270452c53771977f6e70a4 100644 (file)
@@ -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 ------------------------------------------------ */
 
index cbe3be158b38beba4cc9a6b5ea2946b470d9cf92..9633a5407f28a615996f1f927a0970aaec45c20e 100644 (file)
@@ -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(
index c9645c7dc665737250e980cdfa1156ed34668908..6439101ff390ae47efbd3415714b4886aea79079 100644 (file)
@@ -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}
index 0bc20589721f351ca4c1e0e4793a867889ef7ce9..0f16fb894d17e12791c08bb897157ff75835206b 100644 (file)
@@ -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
index 328bddbdc6887b5eb574b17261e53550e6f34a89..c3f8527bd69525f72218aa131dd134953572573a 100644 (file)
@@ -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():
index 051711bfd1fe2420621baf124a530b4ab19078ff..740ce7d5ef26380ee43a5a77f3f1b33c1217362e 100644 (file)
@@ -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},
             )
index 0762e26a36c795cf228516060868da7f3ca8309f..cc844527da5838a3e4c1c2520a521fdda5fba36e 100644 (file)
@@ -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"
index 15df1b2befda82c5fcf39da057ea39cc81bf6566..fb416700e2252310fb8d146718eb2adb1bc2abfc 100644 (file)
@@ -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
index 55508a2214f84d77f4b793aafe5db88a617f5e78..34fcd702391f32d9f2e5619a0aea9ea319e50662 100644 (file)
@@ -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"
 
index 8e44d453269a71e0678f9bc1043ee3422b59460f..0a727a6e0ecd8a9d117c0b81fc2e63ce9f5b6a4d 100644 (file)
@@ -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"
index 24090b0b63936aa8bc9419653563fac35b180389..21bdbc12814698bbb9803c1118e604b0bff8d809 100644 (file)
@@ -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()
 
index be033256adc259239753ac58fd30656abeb454cf..cecc3785c7661c2b8b11a674653e38ecca913aee 100644 (file)
@@ -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 */
index 20b96320f4c33922bc88e8bbaae09922ec4bf9af..d5c8a9d7ae520d3fe2a2713ba5fcd87851acda34 100644 (file)
@@ -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},
index 3e3dfeca037c7f0dabff9b97517e3c9e8e17e332..e375ca8556d21721e5d2245bffcd7acaa27c82e0 100644 (file)
@@ -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 */
 };
 
index ea91e70cad991d3f24326e014c5c9be7a8009aba..6638c2c8e0636b962ff7470f519a04678931cf1c 100644 (file)
@@ -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"
 
 
index fb0b4b40b2ad5d5133244cd5c3cb65826287b640..09f5fd4b2ef0a90aa042ec2a51ee29e3cee5f685 100644 (file)
@@ -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>
index d7a0f914d41aff862c2cdaf671739e04c1f766da..b99896319e0136cd8a9e67096c14d6aea14f0425 100644 (file)
@@ -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"
index 1814c6eb69c29bb9b8e770d95c1b7d90775dc06f..df74be6aba72445eafa083d6572f4a3dc890810b 100644 (file)
@@ -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()