mirror of https://github.com/python/cpython
You can no longer catch non-BaseException objects; TypeError is raised if such
an object is listed in an 'except' clause.
This commit is contained in:
parent
6baa4c4cc6
commit
f74225d63b
|
@ -158,34 +158,17 @@ class UsageTests(unittest.TestCase):
|
|||
# Raising a string raises TypeError.
|
||||
self.raise_fails("spam")
|
||||
|
||||
def test_catch_non_BaseException(self):
|
||||
# Tryinng to catch an object that does not inherit from BaseException
|
||||
# is not allowed.
|
||||
class NonBaseException(object):
|
||||
pass
|
||||
self.catch_fails(NonBaseException)
|
||||
self.catch_fails(NonBaseException())
|
||||
|
||||
def test_catch_string(self):
|
||||
# Catching a string should trigger a DeprecationWarning.
|
||||
with guard_warnings_filter():
|
||||
warnings.resetwarnings()
|
||||
warnings.filterwarnings("error")
|
||||
str_exc = "spam"
|
||||
try:
|
||||
try:
|
||||
raise StandardError
|
||||
except str_exc:
|
||||
pass
|
||||
except DeprecationWarning:
|
||||
pass
|
||||
except StandardError:
|
||||
self.fail("catching a string exception did not raise "
|
||||
"DeprecationWarning")
|
||||
# Make sure that even if the string exception is listed in a tuple
|
||||
# that a warning is raised.
|
||||
try:
|
||||
try:
|
||||
raise StandardError
|
||||
except (AssertionError, str_exc):
|
||||
pass
|
||||
except DeprecationWarning:
|
||||
pass
|
||||
except StandardError:
|
||||
self.fail("catching a string exception specified in a tuple did "
|
||||
"not raise DeprecationWarning")
|
||||
# Catching a string is bad.
|
||||
self.catch_fails("spam")
|
||||
|
||||
def test_main():
|
||||
run_unittest(ExceptionClassTests, UsageTests)
|
||||
|
|
|
@ -28,6 +28,8 @@ TO DO
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Objects listed in an 'except' clause must inherit from BaseException.
|
||||
|
||||
- PEP 3106: dict.iterkeys(), .iteritems(), .itervalues() are now gone;
|
||||
and .keys(), .items(), .values() return dict views.
|
||||
|
||||
|
|
|
@ -1571,7 +1571,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
why == WHY_CONTINUE)
|
||||
retval = POP();
|
||||
}
|
||||
else if (PyExceptionClass_Check(v) || PyString_Check(v)) {
|
||||
else if (PyExceptionClass_Check(v)) {
|
||||
w = POP();
|
||||
u = POP();
|
||||
PyErr_Restore(v, w, u);
|
||||
|
@ -3916,6 +3916,24 @@ assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Return a true value if the exception is allowed to be in an 'except' clause,
|
||||
otherwise return a false value.
|
||||
*/
|
||||
static int
|
||||
can_catch_exc(PyObject *exc)
|
||||
{
|
||||
if (!(PyExceptionClass_Check(exc) || PyExceptionInstance_Check(exc))) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"catching an object must be a class or "
|
||||
"instance of BaseException");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
cmp_outcome(int op, register PyObject *v, register PyObject *w)
|
||||
{
|
||||
|
@ -3944,28 +3962,14 @@ cmp_outcome(int op, register PyObject *v, register PyObject *w)
|
|||
length = PyTuple_Size(w);
|
||||
for (i = 0; i < length; i += 1) {
|
||||
PyObject *exc = PyTuple_GET_ITEM(w, i);
|
||||
if (PyString_Check(exc)) {
|
||||
int ret_val;
|
||||
ret_val = PyErr_WarnEx(
|
||||
PyExc_DeprecationWarning,
|
||||
"catching of string "
|
||||
"exceptions is "
|
||||
"deprecated", 1);
|
||||
if (ret_val == -1)
|
||||
return NULL;
|
||||
if (!can_catch_exc(exc)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (PyString_Check(w)) {
|
||||
int ret_val;
|
||||
ret_val = PyErr_WarnEx(
|
||||
PyExc_DeprecationWarning,
|
||||
"catching of string "
|
||||
"exceptions is deprecated",
|
||||
1);
|
||||
if (ret_val == -1)
|
||||
return NULL;
|
||||
if (!can_catch_exc(w)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
res = PyErr_GivenExceptionMatches(v, w);
|
||||
|
|
Loading…
Reference in New Issue