[Python-checkins] r53605 - in python/trunk: Doc/lib/libexcs.tex Doc/ref/ref4.tex Lib/test/test_pep352.py Misc/NEWS Python/ceval.c

brett.cannon python-checkins at python.org
Tue Jan 30 22:34:38 CET 2007


Author: brett.cannon
Date: Tue Jan 30 22:34:36 2007
New Revision: 53605

Modified:
   python/trunk/Doc/lib/libexcs.tex
   python/trunk/Doc/ref/ref4.tex
   python/trunk/Lib/test/test_pep352.py
   python/trunk/Misc/NEWS
   python/trunk/Python/ceval.c
Log:
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.



Modified: python/trunk/Doc/lib/libexcs.tex
==============================================================================
--- python/trunk/Doc/lib/libexcs.tex	(original)
+++ python/trunk/Doc/lib/libexcs.tex	Tue Jan 30 22:34:36 2007
@@ -10,22 +10,6 @@
 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

Modified: python/trunk/Doc/ref/ref4.tex
==============================================================================
--- python/trunk/Doc/ref/ref4.tex	(original)
+++ python/trunk/Doc/ref/ref4.tex	Tue Jan 30 22:34:36 2007
@@ -203,10 +203,6 @@
 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

Modified: python/trunk/Lib/test/test_pep352.py
==============================================================================
--- python/trunk/Lib/test/test_pep352.py	(original)
+++ python/trunk/Lib/test/test_pep352.py	Tue Jan 30 22:34:36 2007
@@ -2,7 +2,7 @@
 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 @@
 
     """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 @@
             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 @@
         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)

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Tue Jan 30 22:34:36 2007
@@ -12,6 +12,9 @@
 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).

Modified: python/trunk/Python/ceval.c
==============================================================================
--- python/trunk/Python/ceval.c	(original)
+++ python/trunk/Python/ceval.c	Tue Jan 30 22:34:36 2007
@@ -2206,8 +2206,9 @@
 		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 @@
 		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 @@
 		/* 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 @@
 		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:


More information about the Python-checkins mailing list