summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrett Cannon <bcannon@gmail.com>2007-01-30 21:34:36 (GMT)
committerBrett Cannon <bcannon@gmail.com>2007-01-30 21:34:36 (GMT)
commit129bd52146c2380a4887c6bbf066113a195c60da (patch)
tree9f4a250df8167eae4bb877cb2a3e85bb83b32b0b
parenta05153683c0712ff62d3bdcc33c879dd49ed7ddc (diff)
downloadcpython-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.tex16
-rw-r--r--Doc/ref/ref4.tex4
-rw-r--r--Lib/test/test_pep352.py62
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/ceval.c47
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)
diff --git a/Misc/NEWS b/Misc/NEWS
index 7dc2bc3..fd760aa 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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: