[3.14] gh-132775: Make _PyXI_session Opaque (gh-134522)

This is mostly a refactor to clean things up a bit, most notably the "XI namespace" code.

Making the session opaque requires adding the following internal-only functions:

* _PyXI_NewSession()
* _PyXI_FreeSession()
* _PyXI_GetMainNamespace()

(cherry picked from commit 4a4ac3ab4d, gh-134452)

Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
This commit is contained in:
Miss Islington (bot) 2025-05-22 19:12:52 +02:00 committed by GitHub
parent 068d570be8
commit 04e2dd6513
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 929 additions and 861 deletions

View file

@ -444,42 +444,54 @@ _exec_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
PyObject **p_excinfo)
{
assert(!_PyErr_Occurred(tstate));
_PyXI_session session = {0};
_PyXI_session *session = _PyXI_NewSession();
if (session == NULL) {
return -1;
}
// Prep and switch interpreters.
if (_PyXI_Enter(&session, interp, shareables) < 0) {
if (_PyXI_Enter(session, interp, shareables) < 0) {
if (_PyErr_Occurred(tstate)) {
// If an error occured at this step, it means that interp
// was not prepared and switched.
_PyXI_FreeSession(session);
return -1;
}
// Now, apply the error from another interpreter:
PyObject *excinfo = _PyXI_ApplyError(session.error);
PyObject *excinfo = _PyXI_ApplyCapturedException(session);
if (excinfo != NULL) {
*p_excinfo = excinfo;
}
assert(PyErr_Occurred());
_PyXI_FreeSession(session);
return -1;
}
// Run the script.
int res = _run_script(script, session.main_ns);
int res = -1;
PyObject *mainns = _PyXI_GetMainNamespace(session);
if (mainns == NULL) {
goto finally;
}
res = _run_script(script, mainns);
finally:
// Clean up and switch back.
_PyXI_Exit(&session);
_PyXI_Exit(session);
// Propagate any exception out to the caller.
assert(!PyErr_Occurred());
if (res < 0) {
PyObject *excinfo = _PyXI_ApplyCapturedException(&session);
PyObject *excinfo = _PyXI_ApplyCapturedException(session);
if (excinfo != NULL) {
*p_excinfo = excinfo;
}
}
else {
assert(!_PyXI_HasCapturedException(&session));
assert(!_PyXI_HasCapturedException(session));
}
_PyXI_FreeSession(session);
return res;
}
@ -824,22 +836,27 @@ interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs)
}
}
_PyXI_session session = {0};
_PyXI_session *session = _PyXI_NewSession();
if (session == NULL) {
return NULL;
}
// Prep and switch interpreters, including apply the updates.
if (_PyXI_Enter(&session, interp, updates) < 0) {
if (_PyXI_Enter(session, interp, updates) < 0) {
if (!PyErr_Occurred()) {
_PyXI_ApplyCapturedException(&session);
_PyXI_ApplyCapturedException(session);
assert(PyErr_Occurred());
}
else {
assert(!_PyXI_HasCapturedException(&session));
assert(!_PyXI_HasCapturedException(session));
}
_PyXI_FreeSession(session);
return NULL;
}
// Clean up and switch back.
_PyXI_Exit(&session);
_PyXI_Exit(session);
_PyXI_FreeSession(session);
Py_RETURN_NONE;
}