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:
Brett Cannon 2007-02-26 21:10:16 +00:00
parent 6baa4c4cc6
commit f74225d63b
3 changed files with 35 additions and 46 deletions

View File

@ -158,34 +158,17 @@ class UsageTests(unittest.TestCase):
# Raising a string raises TypeError. # Raising a string raises TypeError.
self.raise_fails("spam") 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): def test_catch_string(self):
# Catching a string should trigger a DeprecationWarning. # Catching a string is bad.
with guard_warnings_filter(): self.catch_fails("spam")
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")
def test_main(): def test_main():
run_unittest(ExceptionClassTests, UsageTests) run_unittest(ExceptionClassTests, UsageTests)

View File

@ -28,6 +28,8 @@ TO DO
Core and Builtins Core and Builtins
----------------- -----------------
- Objects listed in an 'except' clause must inherit from BaseException.
- PEP 3106: dict.iterkeys(), .iteritems(), .itervalues() are now gone; - PEP 3106: dict.iterkeys(), .iteritems(), .itervalues() are now gone;
and .keys(), .items(), .values() return dict views. and .keys(), .items(), .values() return dict views.

View File

@ -1571,7 +1571,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
why == WHY_CONTINUE) why == WHY_CONTINUE)
retval = POP(); retval = POP();
} }
else if (PyExceptionClass_Check(v) || PyString_Check(v)) { else if (PyExceptionClass_Check(v)) {
w = POP(); w = POP();
u = POP(); u = POP();
PyErr_Restore(v, w, u); 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 * static PyObject *
cmp_outcome(int op, register PyObject *v, register PyObject *w) 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); length = PyTuple_Size(w);
for (i = 0; i < length; i += 1) { for (i = 0; i < length; i += 1) {
PyObject *exc = PyTuple_GET_ITEM(w, i); PyObject *exc = PyTuple_GET_ITEM(w, i);
if (PyString_Check(exc)) { if (!can_catch_exc(exc)) {
int ret_val; return NULL;
ret_val = PyErr_WarnEx(
PyExc_DeprecationWarning,
"catching of string "
"exceptions is "
"deprecated", 1);
if (ret_val == -1)
return NULL;
} }
} }
} }
else { else {
if (PyString_Check(w)) { if (!can_catch_exc(w)) {
int ret_val; return NULL;
ret_val = PyErr_WarnEx(
PyExc_DeprecationWarning,
"catching of string "
"exceptions is deprecated",
1);
if (ret_val == -1)
return NULL;
} }
} }
res = PyErr_GivenExceptionMatches(v, w); res = PyErr_GivenExceptionMatches(v, w);