mirror of https://github.com/python/cpython
bpo-45871: Refactor except matcher validation into a separate function so that it can be reused. Add missing unit test. (GH-29711)
This commit is contained in:
parent
0e1c2f3ef8
commit
4d6c0c0cce
|
@ -2401,6 +2401,21 @@ class SyntaxErrorTests(unittest.TestCase):
|
|||
self.assertRaises(TypeError, SyntaxError, "bad bad", args)
|
||||
|
||||
|
||||
class TestInvalidExceptionMatcher(unittest.TestCase):
|
||||
def test_except_star_invalid_exception_type(self):
|
||||
with self.assertRaises(TypeError):
|
||||
try:
|
||||
raise ValueError
|
||||
except 42:
|
||||
pass
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
try:
|
||||
raise ValueError
|
||||
except (ValueError, 42):
|
||||
pass
|
||||
|
||||
|
||||
class PEP626Tests(unittest.TestCase):
|
||||
|
||||
def lineno_after_raise(self, f, *expected):
|
||||
|
|
|
@ -93,6 +93,7 @@ static int import_all_from(PyThreadState *, PyObject *, PyObject *);
|
|||
static void format_exc_check_arg(PyThreadState *, PyObject *, const char *, PyObject *);
|
||||
static void format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg);
|
||||
static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg);
|
||||
static int check_except_type_valid(PyThreadState *tstate, PyObject* right);
|
||||
static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs);
|
||||
static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int);
|
||||
static int get_exception_handler(PyCodeObject *, int, int*, int*, int*);
|
||||
|
@ -3715,31 +3716,11 @@ check_eval_breaker:
|
|||
}
|
||||
|
||||
TARGET(JUMP_IF_NOT_EXC_MATCH) {
|
||||
const char *cannot_catch_msg = "catching classes that do not "
|
||||
"inherit from BaseException is not "
|
||||
"allowed";
|
||||
PyObject *right = POP();
|
||||
PyObject *left = TOP();
|
||||
if (PyTuple_Check(right)) {
|
||||
Py_ssize_t i, length;
|
||||
length = PyTuple_GET_SIZE(right);
|
||||
for (i = 0; i < length; i++) {
|
||||
PyObject *exc = PyTuple_GET_ITEM(right, i);
|
||||
if (!PyExceptionClass_Check(exc)) {
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
cannot_catch_msg);
|
||||
Py_DECREF(right);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!PyExceptionClass_Check(right)) {
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
cannot_catch_msg);
|
||||
Py_DECREF(right);
|
||||
goto error;
|
||||
}
|
||||
if (check_except_type_valid(tstate, right) < 0) {
|
||||
Py_DECREF(right);
|
||||
goto error;
|
||||
}
|
||||
int res = PyErr_GivenExceptionMatches(left, right);
|
||||
Py_DECREF(right);
|
||||
|
@ -6892,6 +6873,35 @@ import_all_from(PyThreadState *tstate, PyObject *locals, PyObject *v)
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\
|
||||
"BaseException is not allowed"
|
||||
|
||||
static int
|
||||
check_except_type_valid(PyThreadState *tstate, PyObject* right)
|
||||
{
|
||||
if (PyTuple_Check(right)) {
|
||||
Py_ssize_t i, length;
|
||||
length = PyTuple_GET_SIZE(right);
|
||||
for (i = 0; i < length; i++) {
|
||||
PyObject *exc = PyTuple_GET_ITEM(right, i);
|
||||
if (!PyExceptionClass_Check(exc)) {
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
CANNOT_CATCH_MSG);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!PyExceptionClass_Check(right)) {
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
CANNOT_CATCH_MSG);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
check_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue