From f74225d63b84a4d3b508fd5657cfe2596633876a Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Mon, 26 Feb 2007 21:10:16 +0000 Subject: You can no longer catch non-BaseException objects; TypeError is raised if such an object is listed in an 'except' clause. --- Lib/test/test_pep352.py | 37 ++++++++++--------------------------- Misc/NEWS | 2 ++ Python/ceval.c | 42 +++++++++++++++++++++++------------------- 3 files changed, 35 insertions(+), 46 deletions(-) diff --git a/Lib/test/test_pep352.py b/Lib/test/test_pep352.py index 15f1101..2a6bac1 100644 --- a/Lib/test/test_pep352.py +++ b/Lib/test/test_pep352.py @@ -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) diff --git a/Misc/NEWS b/Misc/NEWS index c20793e..91e1f02 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -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. diff --git a/Python/ceval.c b/Python/ceval.c index 5f1b873..86dcea2 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -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); -- cgit v0.12