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().
This commit is contained in:
Eric Snow 2025-04-25 14:43:38 -06:00 committed by GitHub
parent 4c20f46fa0
commit cd9536a087
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 322 additions and 177 deletions

View file

@ -1,4 +1,25 @@
static void
_ensure_current_cause(PyThreadState *tstate, PyObject *cause)
{
if (cause == NULL) {
return;
}
PyObject *exc = _PyErr_GetRaisedException(tstate);
assert(exc != NULL);
PyObject *ctx = PyException_GetContext(exc);
if (ctx == NULL) {
PyException_SetContext(exc, Py_NewRef(cause));
}
else {
Py_DECREF(ctx);
}
assert(PyException_GetCause(exc) == NULL);
PyException_SetCause(exc, Py_NewRef(cause));
_PyErr_SetRaisedException(tstate, exc);
}
/* InterpreterError extends Exception */
static PyTypeObject _PyExc_InterpreterError = {
@ -25,6 +46,97 @@ static PyTypeObject _PyExc_InterpreterNotFoundError = {
};
PyObject *PyExc_InterpreterNotFoundError = (PyObject *)&_PyExc_InterpreterNotFoundError;
/* NotShareableError extends ValueError */
static int
_init_notshareableerror(exceptions_t *state)
{
const char *name = "interpreters.NotShareableError";
// XXX Inherit from TypeError.
PyObject *base = PyExc_ValueError;
PyObject *ns = NULL;
PyObject *exctype = PyErr_NewException(name, base, ns);
if (exctype == NULL) {
return -1;
}
state->PyExc_NotShareableError = exctype;
return 0;
}
static void
_fini_notshareableerror(exceptions_t *state)
{
Py_CLEAR(state->PyExc_NotShareableError);
}
static PyObject *
get_notshareableerror_type(PyThreadState *tstate)
{
_PyXI_state_t *local = _PyXI_GET_STATE(tstate->interp);
if (local == NULL) {
PyErr_Clear();
return NULL;
}
return local->exceptions.PyExc_NotShareableError;
}
static void
_ensure_notshareableerror(PyThreadState *tstate,
PyObject *cause, int force, PyObject *msgobj)
{
PyObject *ctx = _PyErr_GetRaisedException(tstate);
PyObject *exctype = get_notshareableerror_type(tstate);
if (exctype != NULL) {
if (!force && ctx != NULL && Py_TYPE(ctx) == (PyTypeObject *)exctype) {
// A NotShareableError instance is already set.
assert(cause == NULL);
_PyErr_SetRaisedException(tstate, ctx);
}
}
else {
exctype = PyExc_ValueError;
}
_PyErr_SetObject(tstate, exctype, msgobj);
// We have to set the context manually since _PyErr_SetObject() doesn't.
_PyErr_ChainExceptions1Tstate(tstate, ctx);
_ensure_current_cause(tstate, cause);
}
static void
set_notshareableerror(PyThreadState *tstate, PyObject *cause, int force, const char *msg)
{
PyObject *msgobj = PyUnicode_FromString(msg);
if (msgobj == NULL) {
assert(_PyErr_Occurred(tstate));
}
else {
_ensure_notshareableerror(tstate, cause, force, msgobj);
}
}
static void
format_notshareableerror_v(PyThreadState *tstate, PyObject *cause, int force,
const char *format, va_list vargs)
{
PyObject *msgobj = PyUnicode_FromFormatV(format, vargs);
if (msgobj == NULL) {
assert(_PyErr_Occurred(tstate));
}
else {
_ensure_notshareableerror(tstate, cause, force, msgobj);
}
}
static void
format_notshareableerror(PyThreadState *tstate, PyObject *cause, int force,
const char *format, ...)
{
va_list vargs;
va_start(vargs, format);
format_notshareableerror_v(tstate, cause, force, format, vargs);
va_end(vargs);
}
/* lifecycle */
@ -76,18 +188,9 @@ fini_static_exctypes(exceptions_t *state, PyInterpreterState *interp)
static int
init_heap_exctypes(exceptions_t *state)
{
PyObject *exctype;
/* NotShareableError extends ValueError */
const char *name = "interpreters.NotShareableError";
PyObject *base = PyExc_ValueError;
PyObject *ns = NULL;
exctype = PyErr_NewException(name, base, ns);
if (exctype == NULL) {
if (_init_notshareableerror(state) < 0) {
goto error;
}
state->PyExc_NotShareableError = exctype;
return 0;
error:
@ -98,5 +201,5 @@ error:
static void
fini_heap_exctypes(exceptions_t *state)
{
Py_CLEAR(state->PyExc_NotShareableError);
_fini_notshareableerror(state);
}