8000 gh-106320: Remove private _PyErr_ChainExceptions() (#108713) · python/cpython@79823c1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 79823c1

Browse files
authored
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.
1 parent 059bd4d commit 79823c1

18 files changed

+140
-117
lines changed

Include/cpython/initconfig.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ PyAPI_FUNC(PyStatus) PyStatus_Exit(int exitcode);
2525
PyAPI_FUNC(int) PyStatus_IsError(PyStatus err);
2626
PyAPI_FUNC(int) PyStatus_IsExit(PyStatus err);
2727
PyAPI_FUNC(int) PyStatus_Exception(PyStatus err);
28-
PyAPI_FUNC(PyObject *) _PyErr_SetFromPyStatus(PyStatus status);
2928

3029
/* --- PyWideStringList ------------------------------------------------ */
3130

Include/cpython/pyerrors.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,6 @@ typedef PyOSErrorObject PyEnvironmentErrorObject;
8888
typedef PyOSErrorObject PyWindowsErrorObject;
8989
#endif
9090

91-
/* Context manipulation (PEP 3134) */
92-
93-
Py_DEPRECATED(3.12) PyAPI_FUNC(void) _PyErr_ChainExceptions(PyObject *, PyObject *, PyObject *);
94-
PyAPI_FUNC(void) _PyErr_ChainExceptions1(PyObject *);
95-
9691
/* In exceptions.c */
9792

9893
PyAPI_FUNC(PyObject*) PyUnstable_Exc_PrepReraiseStar(

Include/internal/pycore_initconfig.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ struct pyruntimestate;
4444
#define _PyStatus_UPDATE_FUNC(err) \
4545
do { (err).func = _PyStatus_GET_FUNC(); } while (0)
4646

47+
// Export for '_testinternalcapi' shared extension
48+
PyAPI_FUNC(PyObject *) _PyErr_SetFromPyStatus(PyStatus status);
49+
50+
4751
/* --- PyWideStringList ------------------------------------------------ */
4852

4953
#define _PyWideStringList_INIT (PyWideStringList){.length = 0, .items = NULL}

Include/internal/pycore_pyerrors.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@ PyAPI_FUNC(Py_ssize_t) _Py_UTF8_Edit_Cost(PyObject *str_a, PyObject *str_b,
163163

164164
void _PyErr_FormatNote(const char *format, ...);
165165

166+
/* Context manipulation (PEP 3134) */
167+
168+
Py_DEPRECATED(3.12) extern void _PyErr_ChainExceptions(PyObject *, PyObject *, PyObject *);
169+
170+
// Export for '_zoneinfo' shared extension
171+
PyAPI_FUNC(void) _PyErr_ChainExceptions1(PyObject *);
172+
166173
#ifdef __cplusplus
167174
}
168175
#endif

Lib/test/support/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1821,11 +1821,11 @@ def run_in_subinterp_with_config(code, *, own_gil=None, **config):
18211821
module is enabled.
18221822
"""
18231823
_check_tracemalloc()
1824-
import _testcapi
1824+
import _testinternalcapi
18251825
if own_gil is not None:
18261826
assert 'gil' not in config, (own_gil, config)
18271827
config['gil'] = 2 if own_gil else 1
1828-
return _testcapi.run_in_subinterp_with_config(code, **config)
1828+
return _testinternalcapi.run_in_subinterp_with_config(code, **config)
18291829

18301830

18311831
def _check_tracemalloc():

Lib/test/test_import/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,12 +1805,12 @@ def check_compatible_fresh(self, name, *, strict=False, isolated=False):
18051805
check_multi_interp_extensions=strict,
18061806
)
18071807
_, out, err = script_helper.assert_python_ok('-c', textwrap.dedent(f'''
1808-
import _testcapi, sys
1808+
import _testinternalcapi, sys
18091809
assert (
18101810
{name!r} in sys.builtin_module_names or
18111811
{name!r} not in sys.modules
18121812
), repr({name!r})
1813-
ret = _testcapi.run_in_subinterp_with_config(
1813+
ret = _testinternalcapi.run_in_subinterp_with_config(
18141814
{self.import_script(name, "sys.stdout.fileno()")!r},
18151815
**{kwargs},
18161816
)
@@ -1829,9 +1829,9 @@ def check_incompatible_fresh(self, name, *, isolated=False):
18291829
check_multi_interp_extensions=True,
18301830
)
18311831
_, out, err = script_helper.assert_python_ok('-c', textwrap.dedent(f'''
1832-
import _testcapi, sys
1832+
import _testinternalcapi, sys
18331833
assert {name!r} not in sys.modules, {name!r}
1834-
ret = _testcapi.run_in_subinterp_with_config(
1834+
ret = _testinternalcapi.run_in_subinterp_with_config(
18351835
{self.import_script(name, "sys.stdout.fileno()")!r},
18361836
**{kwargs},
18371837
)

Modules/_io/_iomodule.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "Python.h"
1111
#include "pycore_abstract.h" // _PyNumber_Index()
1212
#include "pycore_initconfig.h" // _PyStatus_OK()
13+
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
1314
#include "pycore_pystate.h" // _PyInterpreterState_GET()
1415

1516
#include "_iomodule.h"

Modules/_io/fileio.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "Python.h"
44
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
55
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
6+
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
67

78
#include <stdbool.h>
89
#ifdef HAVE_SYS_TYPES_H

Modules/_io/iobase.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include "pycore_call.h" // _PyObject_CallMethod()
1313
#include "pycore_long.h" // _PyLong_GetOne()
1414
#include "pycore_object.h" // _PyType_HasFeature()
15+
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
16+
1517
#include <stddef.h> // offsetof()
1618
#include "_iomodule.h"
1719

Modules/_io/textio.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
#include "Python.h"
1010
#include "pycore_call.h" // _PyObject_CallMethod()
1111
#include "pycore_codecs.h" // _PyCodecInfo_GetIncrementalDecoder()
12+
#include "pycore_fileutils.h" // _Py_GetLocaleEncoding()
1213
#include "pycore_interp.h" // PyInterpreterState.fs_codec
1314
#include "pycore_long.h" // _PyLong_GetZero()
14-
#include "pycore_fileutils.h" // _Py_GetLocaleEncoding()
1515
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
16+
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
1617
#include "pycore_pystate.h" // _PyInterpreterState_GET()
1718

1819
#include "_iomodule.h"

Modules/_sqlite/connection.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
#include "blob.h"
3434
#include "prepare_protocol.h"
3535
#include "util.h"
36+
3637
#include "pycore_import.h" // _PyImport_GetModuleAttrString()
38+
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
3739
#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
3840
#include "pycore_weakref.h" // _PyWeakref_IS_DEAD()
3941

Modules/_ssl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "Python.h"
2929
#include "pycore_fileutils.h" // _PyIsSelectable_fd()
30+
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
3031
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
3132

3233
/* Include symbols from _socket module */

Modules/_testcapimodule.c

Lines changed: 0 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,104 +1434,6 @@ run_in_subinterp(PyObject *self, PyObject *args)
14341434
return PyLong_FromLong(r);
14351435
}
14361436

1437-
/* To run some code in a sub-interpreter. */
1438-
static PyObject *
1439-
run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
1440-
{
1441-
const char *code;
1442-
int use_main_obmalloc = -1;
1443-
int allow_fork = -1;
1444-
int allow_exec = -1;
1445-
int allow_threads = -1;
1446-
int allow_daemon_threads = -1;
1447-
int check_multi_interp_extensions = -1;
1448-
int gil = -1;
1449-
int r;
1450-
PyThreadState *substate, *mainstate;
1451-
/* only initialise 'cflags.cf_flags' to test backwards compatibility */
1452-
PyCompilerFlags cflags = {0};
1453-
1454-
static char *kwlist[] = {"code",
1455-
"use_main_obmalloc",
1456-
"allow_fork",
1457-
"allow_exec",
1458-
"allow_threads",
1459-
"allow_daemon_threads",
1460-
"check_multi_interp_extensions",
1461-
"gil",
1462-
NULL};
1463-
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
1464-
"s$ppppppi:run_in_subinterp_with_config", kwlist,
1465-
&code, &use_main_obmalloc,
1466-
&allow_fork, &allow_exec,
1467-
&allow_threads, &allow_daemon_threads,
1468-
&check_multi_interp_extensions,
1469-
&gil)) {
1470-
return NULL;
1471-
}
1472-
if (use_main_obmalloc < 0) {
1473-
PyErr_SetString(PyExc_ValueError, "missing use_main_obmalloc");
1474-
return NULL;
1475-
}
1476-
if (allow_fork < 0) {
1477-
PyErr_SetString(PyExc_ValueError, "missing allow_fork");
1478-
return NULL;
1479-
}
1480-
if (allow_exec < 0) {
1481-
PyErr_SetString(PyExc_ValueError, "missing allow_exec");
1482-
return NULL;
1483-
}
1484-
if (allow_threads < 0) {
1485-
PyErr_SetString(PyExc_ValueError, "missing allow_threads");
1486-
return NULL;
1487-
}
1488-
if (gil < 0) {
1489-
PyErr_SetString(PyExc_ValueError, "missing gil");
1490-
return NULL;
1491-
}
1492-
if (allow_daemon_threads < 0) {
1493-
PyErr_SetString(PyExc_ValueError, "missing allow_daemon_threads");
1494-
return NULL;
1495-
}
1496-
if (check_multi_interp_extensions < 0) {
1497-
PyErr_SetString(PyExc_ValueError, "missing check_multi_interp_extensions");
1498-
return NULL;
1499-
}
1500-
1501-
mainstate = PyThreadState_Get();
1502-
1503-
PyThreadState_Swap(NULL);
1504-
1505-
const PyInterpreterConfig config = {
1506-
.use_main_obmalloc = use_main_obmalloc,
1507-
.allow_fork = allow_fork,
1508-
.allow_exec = allow_exec,
1509-
.allow_threads = allow_threads,
1510-
.allow_daemon_threads = allow_daemon_threads,
1511-
.check_multi_interp_extensions = check_multi_interp_extensions,
1512-
.gil = gil,
1513-
};
1514-
PyStatus status = Py_NewInterpreterFromConfig(&substate, &config);
1515-
if (PyStatus_Exception(status)) {
1516-
/* Since no new thread state was created, there is no exception to
1517-
propagate; raise a fresh one after swapping in the old thread
1518-
state. */
1519-
PyThreadState_Swap(mainstate);
1520-
_PyErr_SetFromPyStatus(status);
1521-
PyObject *exc = PyErr_GetRaisedException();
1522-
PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
1523-
_PyErr_ChainExceptions1(exc);
1524-
return NULL;
1525-
}
1526-
assert(substate != NULL);
1527-
r = PyRun_SimpleStringFlags(code, &cflags);
1528-
Py_EndInterpreter(substate);
1529-
1530-
PyThreadState_Swap(mainstate);
1531-
1532-
return PyLong_FromLong(r);
1533-
}
1534-
15351437
static void
15361438
_xid_capsule_destructor(PyObject *capsule)
15371439
{
@@ -3376,9 +3278,6 @@ static PyMethodDef TestMethods[] = {
33763278
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
33773279
{"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS},
33783280
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
3379-
{"run_in_subinterp_with_config",
3380-
_PyCFunction_CAST(run_in_subinterp_with_config),
3381-
METH_VARARGS | METH_KEYWORDS},
33823281
{"get_crossinterp_data", get_crossinterp_data, METH_VARARGS},
33833282
{"restore_crossinterp_data", restore_crossinterp_data, METH_VARARGS},
33843283
{"create_cfunction", create_cfunction, METH_NOARGS},

Modules/_testinternalcapi.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy()
2626
#include "pycore_object.h" // _PyObject_IsFreed()
2727
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
28+
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
2829
#include "pycore_pyerrors.h" // _Py_UTF8_Edit_Cost()
2930
#include "pycore_pystate.h" // _PyThreadState_GET()
3031

@@ -1593,6 +1594,105 @@ dict_getitem_knownhash(PyObject *self, PyObject *args)
15931594
}
15941595

15951596

1597+
/* To run some code in a sub-interpreter. */
1598+
static PyObject *
1599+
run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
1600+
{
1601+
const char *code;
1602+
int use_main_obmalloc = -1;
1603+
int allow_fork = -1;
1604+
int allow_exec = -1;
1605+
int allow_threads = -1;
1606+
int allow_daemon_threads = -1;
1607+
int check_multi_interp_extensions = -1;
1608+
int gil = -1;
1609+
int r;
1610+
PyThreadState *substate, *mainstate;
1611+
/* only initialise 'cflags.cf_flags' to test backwards compatibility */
1612+
PyCompilerFlags cflags = {0};
1613+
1614+
static char *kwlist[] = {"code",
1615+
"use_main_obmalloc",
1616+
"allow_fork",
1617+
"allow_exec",
1618+
"allow_threads",
1619+
"allow_daemon_threads",
1620+
"check_multi_interp_extensions",
1621+
"gil",
1622+
NULL};
1623+
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
1624+
"s$ppppppi:run_in_subinterp_with_config", kwlist,
1625+
&code, &use_main_obmalloc,
1626+
&allow_fork, &allow_exec,
1627+
&allow_threads, &allow_daemon_threads,
1628+
&check_multi_interp_extensions,
1629+
&gil)) {
1630+
return NULL;
1631+
}
1632+
if (use_main_obmalloc < 0) {
1633+
PyErr_SetString(PyExc_ValueError, "missing use_main_obmalloc");
1634+
return NULL;
1635+
}
1636+
if (allow_fork < 0) {
1637+
PyErr_SetString(PyExc_ValueError, "missing allow_fork");
1638+
return NULL;
1639+
}
1640+
if (allow_exec < 0) {
1641+
PyErr_SetString(PyExc_ValueError, "missing allow_exec");
1642+
return NULL;
1643+
}
1644+
if (allow_threads < 0) {
1645+
PyErr_SetString(PyExc_ValueError, "missing allow_threads");
1646+
return NULL;
1647+
}
1648+
if (gil < 0) {
1649+
PyErr_SetString(PyExc_ValueError, "missing gil");
1650+
return NULL;
1651+
}
1652+
if (allow_daemon_threads < 0) {
1653+
PyErr_SetString(PyExc_ValueError, "missing allow_daemon_threads");
1654+
return NULL;
1655+
}
1656+
if (check_multi_interp_extensions < 0) {
1657+
PyErr_SetString(PyExc_ValueError, "missing check_multi_interp_extensions");
1658+
return NULL;
1659+
}
1660+
1661+
mainstate = PyThreadState_Get();
1662+
1663+
PyThreadState_Swap(NULL);
1664+
1665+
const PyInterpreterConfig config = {
1666+
.use_main_obmalloc = use_main_obmalloc,
1667+
.allow_fork = allow_fork,
1668+
.allow_exec = allow_exec,
1669+
.allow_threads = allow_threads,
1670+
.allow_daemon_threads = allow_daemon_threads,
1671+
.check_multi_interp_extensions = check_multi_interp_extensions,
1672+
.gil = gil,
1673+
};
1674+
PyStatus status = Py_NewInterpreterFromConfig(&substate, &config);
1675+
if (PyStatus_Exception(status)) {
1676+
/* Since no new thread state was created, there is no exception to
1677+
propagate; raise a fresh one after swapping in the old thread
1678+
state. */
1679+
PyThreadState_Swap(mainstate);
1680+
_PyErr_SetFromPyStatus(status);
1681+
PyObject *exc = PyErr_GetRaisedException();
1682+
PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
1683+
_PyErr_ChainExceptions1(exc);
1684+
return NULL;
1685+
}
1686+
assert(substate != NULL);
1687+
r = PyRun_SimpleStringFlags(code, &cflags);
1688+
Py_EndInterpreter(substate);
1689+
1690+
PyThreadState_Swap(mainstate);
1691+
1692+
return PyLong_FromLong(r);
1693+
}
1694+
1695+
15961696
static PyMethodDef module_functions[] = {
15971697
{"get_configs", get_configs, METH_NOARGS},
15981698
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -1659,6 +1759,9 @@ static PyMethodDef module_functions[] = {
16591759
{"get_object_dict_values", get_object_dict_values, METH_O},
16601760
{"hamt", new_hamt, METH_NOARGS},
16611761
{"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS},
1762+
{"run_in_subinterp_with_config",
1763+
_PyCFunction_CAST(run_in_subinterp_with_config),
1764+
METH_VARARGS | METH_KEYWORDS},
16621765
{NULL, NULL} /* sentinel */
16631766
};
16641767

Modules/_xxsubinterpretersmodule.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
/* interpreters module */
22
/* low-level access to interpreter primitives */
33

4+
#ifndef Py_BUILD_CORE_BUILTIN
5+
# define Py_BUILD_CORE_MODULE 1
6+
#endif
7+
48
#include "Python.h"
9+
#include "pycore_initconfig.h" // _PyErr_SetFromPyStatus()
10+
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
511
#include "interpreteridobject.h"
612

713

0 commit comments

Comments
 (0)
0