diff options
author | Brett Cannon <bcannon@gmail.com> | 2007-01-30 21:34:36 (GMT) |
---|---|---|
committer | Brett Cannon <bcannon@gmail.com> | 2007-01-30 21:34:36 (GMT) |
commit | 129bd52146c2380a4887c6bbf066113a195c60da (patch) | |
tree | 9f4a250df8167eae4bb877cb2a3e85bb83b32b0b | |
parent | a05153683c0712ff62d3bdcc33c879dd49ed7ddc (diff) | |
download | cpython-129bd52146c2380a4887c6bbf066113a195c60da.zip cpython-129bd52146c2380a4887c6bbf066113a195c60da.tar.gz cpython-129bd52146c2380a4887c6bbf066113a195c60da.tar.bz2 |
No more raising of string exceptions!
The next step of PEP 352 (for 2.6) causes raising a string exception to trigger
a TypeError. Trying to catch a string exception raises a DeprecationWarning.
References to string exceptions has been removed from the docs since they are
now just an error.
-rw-r--r-- | Doc/lib/libexcs.tex | 16 | ||||
-rw-r--r-- | Doc/ref/ref4.tex | 4 | ||||
-rw-r--r-- | Lib/test/test_pep352.py | 62 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Python/ceval.c | 47 |
5 files changed, 76 insertions, 56 deletions
diff --git a/Doc/lib/libexcs.tex b/Doc/lib/libexcs.tex index 6d2a3c5..b793fd3 100644 --- a/Doc/lib/libexcs.tex +++ b/Doc/lib/libexcs.tex @@ -10,22 +10,6 @@ module never needs to be imported explicitly: the exceptions are provided in the built-in namespace as well as the \module{exceptions} module. -\begin{notice} -In past versions of Python string exceptions were supported. In -Python 1.5 and newer versions, all standard exceptions have been -converted to class objects and users are encouraged to do the same. -String exceptions will raise a \code{DeprecationWarning} in Python 2.5 and -newer. -In future versions, support for string exceptions will be removed. - -Two distinct string objects with the same value are considered different -exceptions. This is done to force programmers to use exception names -rather than their string value when specifying exception handlers. -The string value of all built-in exceptions is their name, but this is -not a requirement for user-defined exceptions or exceptions defined by -library modules. -\end{notice} - For class exceptions, in a \keyword{try}\stindex{try} statement with an \keyword{except}\stindex{except} clause that mentions a particular class, that clause also handles any exception classes derived from diff --git a/Doc/ref/ref4.tex b/Doc/ref/ref4.tex index 12a2b92..f38b948 100644 --- a/Doc/ref/ref4.tex +++ b/Doc/ref/ref4.tex @@ -203,10 +203,6 @@ Exceptions can also be identified by strings, in which case the value can be raised along with the identifying string which can be passed to the handler. -\deprecated{2.5}{String exceptions should not be used in new code. -They will not be supported in a future version of Python. Old code -should be rewritten to use class exceptions instead.} - \begin{notice}[warning] Messages to exceptions are not part of the Python API. Their contents may change from one version of Python to the next without warning and should not diff --git a/Lib/test/test_pep352.py b/Lib/test/test_pep352.py index b2322b0..4ce25d6 100644 --- a/Lib/test/test_pep352.py +++ b/Lib/test/test_pep352.py @@ -2,7 +2,7 @@ import unittest import __builtin__ import exceptions import warnings -from test.test_support import run_unittest +from test.test_support import run_unittest, guard_warnings_filter import os from platform import system as platform_system @@ -113,13 +113,8 @@ class UsageTests(unittest.TestCase): """Test usage of exceptions""" - def setUp(self): - self._filters = warnings.filters[:] - - def tearDown(self): - warnings.filters = self._filters[:] - def test_raise_classic(self): + # Raising a classic class is okay (for now). class ClassicClass: pass try: @@ -136,6 +131,10 @@ class UsageTests(unittest.TestCase): self.fail("unable to raise class class instance") def test_raise_new_style_non_exception(self): + # You cannot raise a new-style class that does not inherit from + # BaseException; the ability was not possible until BaseException's + # introduction so no need to support new-style objects that do not + # inherit from it. class NewStyleClass(object): pass try: @@ -143,35 +142,52 @@ class UsageTests(unittest.TestCase): except TypeError: pass except: - self.fail("unable to raise new-style class") + self.fail("able to raise new-style class") try: raise NewStyleClass() except TypeError: pass except: - self.fail("unable to raise new-style class instance") + self.fail("able to raise new-style class instance") def test_raise_string(self): - warnings.resetwarnings() - warnings.filterwarnings("error") + # Raising a string raises TypeError. try: raise "spam" - except DeprecationWarning: + except TypeError: pass except: - self.fail("raising a string did not cause a DeprecationWarning") + self.fail("was able to raise a string exception") def test_catch_string(self): - # Test will be pertinent when catching exceptions raises a - # DeprecationWarning - warnings.filterwarnings("ignore", "raising") - str_exc = "spam" - try: - raise str_exc - except str_exc: - pass - except: - self.fail("catching a string exception failed") + # 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") + def test_main(): run_unittest(ExceptionClassTests, UsageTests) @@ -12,6 +12,9 @@ What's New in Python 2.6 alpha 1? Core and builtins ----------------- +- PEP 352: Raising a string exception now triggers a TypeError. Attempting to + catch a string exception raises DeprecationWarning. + - Bug #1377858: Fix the segfaulting of the interpreter when an object created a weakref on itself during a __del__ call for new-style classes (classic classes still have the bug). diff --git a/Python/ceval.c b/Python/ceval.c index 67eefba..ffdc75b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2206,8 +2206,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: - /* NOTE: If you add any new block-setup opcodes that are not try/except/finally - handlers, you may need to update the PyGen_NeedsFinalizing() function. */ + /* NOTE: If you add any new block-setup opcodes that are + not try/except/finally handlers, you may need to + update the PyGen_NeedsFinalizing() function. */ PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, STACK_LEVEL()); @@ -3069,15 +3070,7 @@ do_raise(PyObject *type, PyObject *value, PyObject *tb) Py_DECREF(tmp); } - if (PyString_CheckExact(type)) { - /* Raising builtin string is deprecated but still allowed -- - * do nothing. Raising an instance of a new-style str - * subclass is right out. */ - if (PyErr_Warn(PyExc_DeprecationWarning, - "raising a string exception is deprecated")) - goto raise_error; - } - else if (PyExceptionClass_Check(type)) + if (PyExceptionClass_Check(type)) PyErr_NormalizeException(&type, &value, &tb); else if (PyExceptionInstance_Check(type)) { @@ -3099,8 +3092,7 @@ do_raise(PyObject *type, PyObject *value, PyObject *tb) /* Not something you can raise. You get an exception anyway, just not what you specified :-) */ PyErr_Format(PyExc_TypeError, - "exceptions must be classes, instances, or " - "strings (deprecated), not %s", + "exceptions must be classes or instances, not %s", type->ob_type->tp_name); goto raise_error; } @@ -3985,6 +3977,35 @@ cmp_outcome(int op, register PyObject *v, register PyObject *w) res = !res; break; case PyCmp_EXC_MATCH: + if (PyTuple_Check(w)) { + Py_ssize_t i, length; + 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; + } + } + } + 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; + } + } res = PyErr_GivenExceptionMatches(v, w); break; default: |