Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 976bcb2

Browse files
gh-76785: Raise InterpreterError, Not RuntimeError (gh-117489)
I had meant to switch everything to InterpreterError when I added it a while back. At the time I missed a few key spots. As part of this, I've added print-the-exception to _PyXI_InitTypes() and fixed an error case in `_PyStaticType_InitBuiltin().
1 parent 7ecd55d commit 976bcb2

File tree

8 files changed

+40
-23
lines changed

8 files changed

+40
-23
lines changed

Lib/test/support/interpreters/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def __getattr__(name):
4343
{formatted}
4444
""".strip()
4545

46-
class ExecutionFailed(RuntimeError):
46+
class ExecutionFailed(InterpreterError):
4747
"""An unhandled exception happened during execution.
4848
4949
This is raised from Interpreter.exec() and Interpreter.call().
@@ -158,7 +158,7 @@ def close(self):
158158
"""Finalize and destroy the interpreter.
159159
160160
Attempting to destroy the current interpreter results
161-
in a RuntimeError.
161+
in an InterpreterError.
162162
"""
163163
return _interpreters.destroy(self._id)
164164

Lib/test/test__xxsubinterpreters.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def clean_up_interpreters():
8080
continue
8181
try:
8282
interpreters.destroy(id)
83-
except RuntimeError:
83+
except interpreters.InterpreterError:
8484
pass # already destroyed
8585

8686

@@ -464,11 +464,11 @@ def test_all(self):
464464

465465
def test_main(self):
466466
main, = interpreters.list_all()
467-
with self.assertRaises(RuntimeError):
467+
with self.assertRaises(interpreters.InterpreterError):
468468
interpreters.destroy(main)
469469

470470
def f():
471-
with self.assertRaises(RuntimeError):
471+
with self.assertRaises(interpreters.InterpreterError):
472472
interpreters.destroy(main)
473473

474474
t = threading.Thread(target=f)
@@ -496,7 +496,7 @@ def test_from_current(self):
496496
import _xxsubinterpreters as _interpreters
497497
try:
498498
_interpreters.destroy({id})
499-
except RuntimeError:
499+
except interpreters.InterpreterError:
500500
pass
501501
""")
502502

@@ -531,7 +531,7 @@ def test_still_running(self):
531531
self.assertTrue(interpreters.is_running(interp),
532532
msg=f"Interp {interp} should be running before destruction.")
533533

534-
with self.assertRaises(RuntimeError,
534+
with self.assertRaises(interpreters.InterpreterError,
535535
msg=f"Should not be able to destroy interp {interp} while it's still running."):
536536
interpreters.destroy(interp)
537537
self.assertTrue(interpreters.is_running(interp))
@@ -676,7 +676,7 @@ def test_fork(self):
676676

677677
def test_already_running(self):
678678
with _running(self.id):
679-
with self.assertRaises(RuntimeError):
679+
with self.assertRaises(interpreters.InterpreterError):
680680
interpreters.run_string(self.id, 'print("spam")')
681681

682682
def test_does_not_exist(self):

Lib/test/test_interpreters/test_api.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -364,11 +364,11 @@ def test_all(self):
364364

365365
def test_main(self):
366366
main, = interpreters.list_all()
367-
with self.assertRaises(RuntimeError):
367+
with self.assertRaises(interpreters.InterpreterError):
368368
main.close()
369369

370370
def f():
371-
with self.assertRaises(RuntimeError):
371+
with self.assertRaises(interpreters.InterpreterError):
372372
main.close()
373373

374374
t = threading.Thread(target=f)
@@ -389,7 +389,7 @@ def test_from_current(self):
389389
interp = interpreters.Interpreter({interp.id})
390390
try:
391391
interp.close()
392-
except RuntimeError:
392+
except interpreters.InterpreterError:
393393
print('failed')
394394
"""))
395395
self.assertEqual(out.strip(), 'failed')
@@ -424,7 +424,7 @@ def test_still_running(self):
424424
main, = interpreters.list_all()
425425
interp = interpreters.create()
426426
with _running(interp):
427-
with self.assertRaises(RuntimeError):
427+
with self.assertRaises(interpreters.InterpreterError):
428428
interp.close()
429429
self.assertTrue(interp.is_running())
430430

@@ -1103,7 +1103,7 @@ def test_create(self):
11031103
self.assert_ns_equal(config, default)
11041104

11051105
with self.subTest('arg: \'empty\''):
1106-
with self.assertRaises(RuntimeError):
1106+
with self.assertRaises(interpreters.InterpreterError):
11071107
# The "empty" config isn't viable on its own.
11081108
_interpreters.create('empty')
11091109

Modules/_xxsubinterpretersmodule.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ interp_create(PyObject *self, PyObject *args, PyObject *kwds)
612612
// XXX Move the chained exception to interpreters.create()?
613613
PyObject *exc = PyErr_GetRaisedException();
614614
assert(exc != NULL);
615-
PyErr_SetString(PyExc_RuntimeError, "interpreter creation failed");
615+
PyErr_SetString(PyExc_InterpreterError, "interpreter creation failed");
616616
_PyErr_ChainExceptions1(exc);
617617
return NULL;
618618
}
@@ -664,7 +664,7 @@ interp_destroy(PyObject *self, PyObject *args, PyObject *kwds)
664664
return NULL;
665665
}
666666
if (interp == current) {
667-
PyErr_SetString(PyExc_RuntimeError,
667+
PyErr_SetString(PyExc_InterpreterError,
668668
"cannot destroy the current interpreter");
669669
return NULL;
670670
}
@@ -673,7 +673,7 @@ interp_destroy(PyObject *self, PyObject *args, PyObject *kwds)
673673
/* XXX We *could* support destroying a running interpreter but
674674
aren't going to worry about it for now. */
675675
if (is_running_main(interp)) {
676-
PyErr_Format(PyExc_RuntimeError, "interpreter running");
676+
PyErr_Format(PyExc_InterpreterError, "interpreter running");
677677
return NULL;
678678
}
679679

@@ -693,7 +693,7 @@ PyDoc_STRVAR(destroy_doc,
693693
\n\
694694
Destroy the identified interpreter.\n\
695695
\n\
696-
Attempting to destroy the current interpreter results in a RuntimeError.\n\
696+
Attempting to destroy the current interpreter raises InterpreterError.\n\
697697
So does an unrecognized ID.");
698698

699699

Objects/typeobject.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7963,6 +7963,7 @@ _PyStaticType_InitBuiltin(PyInterpreterState *interp, PyTypeObject *self)
79637963
res = type_ready(self, !ismain);
79647964
END_TYPE_LOCK()
79657965
if (res < 0) {
7966+
_PyStaticType_ClearWeakRefs(interp, self);
79667967
static_builtin_state_clear(interp, self);
79677968
}
79687969
return res;

Python/crossinterp.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ _PyXI_ApplyErrorCode(_PyXI_errcode code, PyInterpreterState *interp)
845845
return 0;
846846
case _PyXI_ERR_OTHER:
847847
// XXX msg?
848-
PyErr_SetNone(PyExc_RuntimeError);
848+
PyErr_SetNone(PyExc_InterpreterError);
849849
break;
850850
case _PyXI_ERR_NO_MEMORY:
851851
PyErr_NoMemory();
@@ -856,11 +856,11 @@ _PyXI_ApplyErrorCode(_PyXI_errcode code, PyInterpreterState *interp)
856856
_PyInterpreterState_FailIfRunningMain(interp);
857857
break;
858858
case _PyXI_ERR_MAIN_NS_FAILURE:
859-
PyErr_SetString(PyExc_RuntimeError,
859+
PyErr_SetString(PyExc_InterpreterError,
860860
"failed to get __main__ namespace");
861861
break;
862862
case _PyXI_ERR_APPLY_NS_FAILURE:
863-
PyErr_SetString(PyExc_RuntimeError,
863+
PyErr_SetString(PyExc_InterpreterError,
864864
"failed to apply namespace to __main__");
865865
break;
866866
case _PyXI_ERR_NOT_SHAREABLE:
@@ -935,7 +935,7 @@ _PyXI_ApplyError(_PyXI_error *error)
935935
if (error->uncaught.type.name != NULL || error->uncaught.msg != NULL) {
936936
// __context__ will be set to a proxy of the propagated exception.
937937
PyObject *exc = PyErr_GetRaisedException();
938-
_PyXI_excinfo_Apply(&error->uncaught, PyExc_RuntimeError);
938+
_PyXI_excinfo_Apply(&error->uncaught, PyExc_InterpreterError);
939939
PyObject *exc2 = PyErr_GetRaisedException();
940940
PyException_SetContext(exc, exc2);
941941
PyErr_SetRaisedException(exc);
@@ -1671,6 +1671,7 @@ PyStatus
16711671
_PyXI_InitTypes(PyInterpreterState *interp)
16721672
{
16731673
if (init_exceptions(interp) < 0) {
1674+
PyErr_PrintEx(0);
16741675
return _PyStatus_ERR("failed to initialize an exception type");
16751676
}
16761677
return _PyStatus_OK();

Python/crossinterp_exceptions.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ static PyTypeObject _PyExc_InterpreterError = {
55
PyVarObject_HEAD_INIT(NULL, 0)
66
.tp_name = "interpreters.InterpreterError",
77
.tp_doc = PyDoc_STR("A cross-interpreter operation failed"),
8+
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
9+
//.tp_traverse = ((PyTypeObject *)PyExc_BaseException)->tp_traverse,
10+
//.tp_clear = ((PyTypeObject *)PyExc_BaseException)->tp_clear,
811
//.tp_base = (PyTypeObject *)PyExc_BaseException,
912
};
1013
PyObject *PyExc_InterpreterError = (PyObject *)&_PyExc_InterpreterError;
@@ -15,6 +18,9 @@ static PyTypeObject _PyExc_InterpreterNotFoundError = {
1518
PyVarObject_HEAD_INIT(NULL, 0)
1619
.tp_name = "interpreters.InterpreterNotFoundError",
1720
.tp_doc = PyDoc_STR("An interpreter was not found"),
21+
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
22+
//.tp_traverse = ((PyTypeObject *)PyExc_BaseException)->tp_traverse,
23+
//.tp_clear = ((PyTypeObject *)PyExc_BaseException)->tp_clear,
1824
.tp_base = &_PyExc_InterpreterError,
1925
};
2026
PyObject *PyExc_InterpreterNotFoundError = (PyObject *)&_PyExc_InterpreterNotFoundError;
@@ -55,16 +61,25 @@ _get_not_shareable_error_type(PyInterpreterState *interp)
5561
static int
5662
init_exceptions(PyInterpreterState *interp)
5763
{
64+
PyTypeObject *base = (PyTypeObject *)PyExc_BaseException;
65+
5866
// builtin static types
59-
_PyExc_InterpreterError.tp_base = (PyTypeObject *)PyExc_BaseException;
67+
68+
_PyExc_InterpreterError.tp_base = base;
69+
_PyExc_InterpreterError.tp_traverse = base->tp_traverse;
70+
_PyExc_InterpreterError.tp_clear = base->tp_clear;
6071
if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterError) < 0) {
6172
return -1;
6273
}
74+
75+
_PyExc_InterpreterNotFoundError.tp_traverse = base->tp_traverse;
76+
_PyExc_InterpreterNotFoundError.tp_clear = base->tp_clear;
6377
if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterNotFoundError) < 0) {
6478
return -1;
6579
}
6680

6781
// heap types
82+
6883
// We would call _init_not_shareable_error_type() here too,
6984
// but that leads to ref leaks
7085

Python/pystate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ int
10731073
_PyInterpreterState_FailIfRunningMain(PyInterpreterState *interp)
10741074
{
10751075
if (interp->threads.main != NULL) {
1076-
PyErr_SetString(PyExc_RuntimeError,
1076+
PyErr_SetString(PyExc_InterpreterError,
10771077
"interpreter already running");
10781078
return -1;
10791079
}

0 commit comments

Comments
 (0)