mirror of https://github.com/python/cpython
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.
This commit is contained in:
parent
a05153683c
commit
129bd52146
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue