Skip to content

Commit cd9536a

Browse files
gh-132781: Cleanup Code Related to NotShareableError (gh-132782)
The following are added to the internal C-API: * _PyErr_FormatV() * _PyErr_SetModuleNotFoundError() * _PyXIData_GetNotShareableErrorType() * _PyXIData_FormatNotShareableError() We also drop _PyXIData_lookup_context_t and _PyXIData_GetLookupContext().
1 parent 4c20f46 commit cd9536a

14 files changed

+320
-175
lines changed

Include/internal/pycore_crossinterp.h

+12-14
Original file line numberDiff line numberDiff line change
@@ -97,26 +97,22 @@ PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data);
9797

9898
typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *);
9999

100-
typedef struct _xid_lookup_state _PyXIData_lookup_t;
101-
102-
typedef struct {
103-
_PyXIData_lookup_t *global;
104-
_PyXIData_lookup_t *local;
105-
PyObject *PyExc_NotShareableError;
106-
} _PyXIData_lookup_context_t;
107-
108-
PyAPI_FUNC(int) _PyXIData_GetLookupContext(
109-
PyInterpreterState *,
110-
_PyXIData_lookup_context_t *);
100+
PyAPI_FUNC(PyObject *) _PyXIData_GetNotShareableErrorType(PyThreadState *);
101+
PyAPI_FUNC(void) _PyXIData_SetNotShareableError(PyThreadState *, const char *);
102+
PyAPI_FUNC(void) _PyXIData_FormatNotShareableError(
103+
PyThreadState *,
104+
const char *,
105+
...);
111106

112107
PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(
113-
_PyXIData_lookup_context_t *,
108+
PyThreadState *,
114109
PyObject *);
115110
PyAPI_FUNC(int) _PyObject_CheckXIData(
116-
_PyXIData_lookup_context_t *,
111+
PyThreadState *,
117112
PyObject *);
113+
118114
PyAPI_FUNC(int) _PyObject_GetXIData(
119-
_PyXIData_lookup_context_t *,
115+
PyThreadState *,
120116
PyObject *,
121117
_PyXIData_t *);
122118

@@ -171,6 +167,8 @@ PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *);
171167
/* runtime state & lifecycle */
172168
/*****************************/
173169

170+
typedef struct _xid_lookup_state _PyXIData_lookup_t;
171+
174172
typedef struct {
175173
// builtin types
176174
_PyXIData_lookup_t data_lookup;

Include/internal/pycore_crossinterp_data_registry.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ typedef struct {
2828
} _PyXIData_registry_t;
2929

3030
PyAPI_FUNC(int) _PyXIData_RegisterClass(
31-
_PyXIData_lookup_context_t *,
31+
PyThreadState *,
3232
PyTypeObject *,
3333
xidatafunc);
3434
PyAPI_FUNC(int) _PyXIData_UnregisterClass(
35-
_PyXIData_lookup_context_t *,
35+
PyThreadState *,
3636
PyTypeObject *);
3737

3838
struct _xid_lookup_state {

Include/internal/pycore_pyerrors.h

+8
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ extern PyObject* _PyErr_SetImportErrorWithNameFrom(
6060
PyObject *,
6161
PyObject *,
6262
PyObject *);
63+
extern int _PyErr_SetModuleNotFoundError(PyObject *name);
6364

6465

6566
/* runtime lifecycle */
@@ -113,6 +114,7 @@ extern void _PyErr_SetObject(
113114
PyObject *value);
114115

115116
extern void _PyErr_ChainStackItem(void);
117+
extern void _PyErr_ChainExceptions1Tstate(PyThreadState *, PyObject *);
116118

117119
PyAPI_FUNC(void) _PyErr_Clear(PyThreadState *tstate);
118120

@@ -148,6 +150,12 @@ PyAPI_FUNC(PyObject*) _PyErr_Format(
148150
const char *format,
149151
...);
150152

153+
PyAPI_FUNC(PyObject*) _PyErr_FormatV(
154+
PyThreadState *tstate,
155+
PyObject *exception,
156+
const char *format,
157+
va_list vargs);
158+
151159
extern void _PyErr_NormalizeException(
152160
PyThreadState *tstate,
153161
PyObject **exc,

Lib/test/test__interpreters.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
_interpreters = import_helper.import_module('_interpreters')
1717
_testinternalcapi = import_helper.import_module('_testinternalcapi')
18-
from _interpreters import InterpreterNotFoundError
18+
from _interpreters import InterpreterNotFoundError, NotShareableError
1919

2020

2121
##################################
@@ -189,8 +189,9 @@ def test_non_shareable_int(self):
189189
]
190190
for i in ints:
191191
with self.subTest(i):
192-
with self.assertRaises(OverflowError):
192+
with self.assertRaises(NotShareableError) as cm:
193193
_testinternalcapi.get_crossinterp_data(i)
194+
self.assertIsInstance(cm.exception.__cause__, OverflowError)
194195

195196
def test_bool(self):
196197
self._assert_values([True, False])
@@ -215,14 +216,12 @@ def test_tuples_containing_non_shareable_types(self):
215216
for s in non_shareables:
216217
value = tuple([0, 1.0, s])
217218
with self.subTest(repr(value)):
218-
# XXX Assert the NotShareableError when it is exported
219-
with self.assertRaises(ValueError):
219+
with self.assertRaises(NotShareableError):
220220
_testinternalcapi.get_crossinterp_data(value)
221221
# Check nested as well
222222
value = tuple([0, 1., (s,)])
223223
with self.subTest("nested " + repr(value)):
224-
# XXX Assert the NotShareableError when it is exported
225-
with self.assertRaises(ValueError):
224+
with self.assertRaises(NotShareableError):
226225
_testinternalcapi.get_crossinterp_data(value)
227226

228227

Lib/test/test_interpreters/test_api.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -693,8 +693,7 @@ def test_dict_and_kwargs(self):
693693

694694
def test_not_shareable(self):
695695
interp = interpreters.create()
696-
# XXX TypeError?
697-
with self.assertRaises(ValueError):
696+
with self.assertRaises(interpreters.NotShareableError):
698697
interp.prepare_main(spam={'spam': 'eggs', 'foo': 'bar'})
699698

700699
# Make sure neither was actually bound.

Modules/_interpchannelsmodule.c

+3-10
Original file line numberDiff line numberDiff line change
@@ -1754,17 +1754,10 @@ static int
17541754
channel_send(_channels *channels, int64_t cid, PyObject *obj,
17551755
_waiting_t *waiting, int unboundop)
17561756
{
1757-
PyInterpreterState *interp = _get_current_interp();
1758-
if (interp == NULL) {
1759-
return -1;
1760-
}
1757+
PyThreadState *tstate = _PyThreadState_GET();
1758+
PyInterpreterState *interp = tstate->interp;
17611759
int64_t interpid = PyInterpreterState_GetID(interp);
17621760

1763-
_PyXIData_lookup_context_t ctx;
1764-
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
1765-
return -1;
1766-
}
1767-
17681761
// Look up the channel.
17691762
PyThread_type_lock mutex = NULL;
17701763
_channel_state *chan = NULL;
@@ -1786,7 +1779,7 @@ channel_send(_channels *channels, int64_t cid, PyObject *obj,
17861779
PyThread_release_lock(mutex);
17871780
return -1;
17881781
}
1789-
if (_PyObject_GetXIData(&ctx, obj, data) != 0) {
1782+
if (_PyObject_GetXIData(tstate, obj, data) != 0) {
17901783
PyThread_release_lock(mutex);
17911784
GLOBAL_FREE(data);
17921785
return -1;

Modules/_interpqueuesmodule.c

+4-7
Original file line numberDiff line numberDiff line change
@@ -1127,11 +1127,7 @@ queue_destroy(_queues *queues, int64_t qid)
11271127
static int
11281128
queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
11291129
{
1130-
PyInterpreterState *interp = PyInterpreterState_Get();
1131-
_PyXIData_lookup_context_t ctx;
1132-
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
1133-
return -1;
1134-
}
1130+
PyThreadState *tstate = PyThreadState_Get();
11351131

11361132
// Look up the queue.
11371133
_queue *queue = NULL;
@@ -1147,12 +1143,13 @@ queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
11471143
_queue_unmark_waiter(queue, queues->mutex);
11481144
return -1;
11491145
}
1150-
if (_PyObject_GetXIData(&ctx, obj, data) != 0) {
1146+
if (_PyObject_GetXIData(tstate, obj, data) != 0) {
11511147
_queue_unmark_waiter(queue, queues->mutex);
11521148
GLOBAL_FREE(data);
11531149
return -1;
11541150
}
1155-
assert(_PyXIData_INTERPID(data) == PyInterpreterState_GetID(interp));
1151+
assert(_PyXIData_INTERPID(data) ==
1152+
PyInterpreterState_GetID(tstate->interp));
11561153

11571154
// Add the data to the queue.
11581155
int64_t interpid = -1; // _queueitem_init() will set it.

Modules/_interpreters_common.h

+4-12
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,16 @@
88
static int
99
ensure_xid_class(PyTypeObject *cls, xidatafunc getdata)
1010
{
11-
PyInterpreterState *interp = PyInterpreterState_Get();
12-
_PyXIData_lookup_context_t ctx;
13-
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
14-
return -1;
15-
}
16-
return _PyXIData_RegisterClass(&ctx, cls, getdata);
11+
PyThreadState *tstate = PyThreadState_Get();
12+
return _PyXIData_RegisterClass(tstate, cls, getdata);
1713
}
1814

1915
#ifdef REGISTERS_HEAP_TYPES
2016
static int
2117
clear_xid_class(PyTypeObject *cls)
2218
{
23-
PyInterpreterState *interp = PyInterpreterState_Get();
24-
_PyXIData_lookup_context_t ctx;
25-
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
26-
return -1;
27-
}
28-
return _PyXIData_UnregisterClass(&ctx, cls);
19+
PyThreadState *tstate = PyThreadState_Get();
20+
return _PyXIData_UnregisterClass(tstate, cls);
2921
}
3022
#endif
3123

Modules/_interpretersmodule.c

+5-14
Original file line numberDiff line numberDiff line change
@@ -1278,13 +1278,8 @@ object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds)
12781278
return NULL;
12791279
}
12801280

1281-
PyInterpreterState *interp = PyInterpreterState_Get();
1282-
_PyXIData_lookup_context_t ctx;
1283-
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
1284-
return NULL;
1285-
}
1286-
1287-
if (_PyObject_CheckXIData(&ctx, obj) == 0) {
1281+
PyThreadState *tstate = _PyThreadState_GET();
1282+
if (_PyObject_CheckXIData(tstate, obj) == 0) {
12881283
Py_RETURN_TRUE;
12891284
}
12901285
PyErr_Clear();
@@ -1577,14 +1572,9 @@ The 'interpreters' module provides a more convenient interface.");
15771572
static int
15781573
module_exec(PyObject *mod)
15791574
{
1580-
PyInterpreterState *interp = PyInterpreterState_Get();
1575+
PyThreadState *tstate = _PyThreadState_GET();
15811576
module_state *state = get_module_state(mod);
15821577

1583-
_PyXIData_lookup_context_t ctx;
1584-
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
1585-
return -1;
1586-
}
1587-
15881578
#define ADD_WHENCE(NAME) \
15891579
if (PyModule_AddIntConstant(mod, "WHENCE_" #NAME, \
15901580
_PyInterpreterState_WHENCE_##NAME) < 0) \
@@ -1606,7 +1596,8 @@ module_exec(PyObject *mod)
16061596
if (PyModule_AddType(mod, (PyTypeObject *)PyExc_InterpreterNotFoundError) < 0) {
16071597
goto error;
16081598
}
1609-
if (PyModule_AddType(mod, (PyTypeObject *)ctx.PyExc_NotShareableError) < 0) {
1599+
PyObject *exctype = _PyXIData_GetNotShareableErrorType(tstate);
1600+
if (PyModule_AddType(mod, (PyTypeObject *)exctype) < 0) {
16101601
goto error;
16111602
}
16121603

Modules/_testinternalcapi.c

+2-6
Original file line numberDiff line numberDiff line change
@@ -1696,11 +1696,7 @@ _xid_capsule_destructor(PyObject *capsule)
16961696
static PyObject *
16971697
get_crossinterp_data(PyObject *self, PyObject *args)
16981698
{
1699-
PyInterpreterState *interp = PyInterpreterState_Get();
1700-
_PyXIData_lookup_context_t ctx;
1701-
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
1702-
return NULL;
1703-
}
1699+
PyThreadState *tstate = _PyThreadState_GET();
17041700

17051701
PyObject *obj = NULL;
17061702
if (!PyArg_ParseTuple(args, "O:get_crossinterp_data", &obj)) {
@@ -1711,7 +1707,7 @@ get_crossinterp_data(PyObject *self, PyObject *args)
17111707
if (data == NULL) {
17121708
return NULL;
17131709
}
1714-
if (_PyObject_GetXIData(&ctx, obj, data) != 0) {
1710+
if (_PyObject_GetXIData(tstate, obj, data) != 0) {
17151711
_PyXIData_Free(data);
17161712
return NULL;
17171713
}

0 commit comments

Comments
 (0)