[Python-checkins] peps: Update from Ethan.

georg.brandl python-checkins at python.org
Fri Feb 3 09:34:37 CET 2012


http://hg.python.org/peps/rev/d995704c931c
changeset:   4032:d995704c931c
user:        Georg Brandl <georg at python.org>
date:        Fri Feb 03 09:34:26 2012 +0100
summary:
  Update from Ethan.

files:
  pep-0409.txt |  128 +++++++++++++++++++++++++++++++-------
  1 files changed, 102 insertions(+), 26 deletions(-)


diff --git a/pep-0409.txt b/pep-0409.txt
--- a/pep-0409.txt
+++ b/pep-0409.txt
@@ -7,8 +7,7 @@
 Type: Standards Track
 Content-Type: text/x-rst
 Created: 26-Jan-2012
-Python-Version: 3.3
-Post-History: 2012-01-27
+Post-History: 30-Aug-2002, 01-Feb-2012, 03-Feb-2012
 
 
 Abstract
@@ -18,48 +17,50 @@
 there is no way to do it.  This PEP proposes one.
 
 
-Motivation
-==========
+Rationale
+=========
 
-There are two basic ways to generate exceptions: 1) Python does it
-(buggy code, missing resources, ending loops, etc.); and, 2) manually
-(with a raise statement).
+There are two basic ways to generate exceptions:
+
+1. Python does it (buggy code, missing resources, ending loops, etc.)
+
+2. manually (with a raise statement)
 
 When writing libraries, or even just custom classes, it can become
 necessary to raise exceptions; moreover it can be useful, even
 necessary, to change from one exception to another.  To take an
 example from my dbf module::
 
-     try:
-         value = int(value)
-     except Exception:
-         raise DbfError(...)
+    try:
+        value = int(value)
+    except Exception:
+        raise DbfError(...)
 
-Whatever the original exception was (ValueError, TypeError, or
+Whatever the original exception was (``ValueError``, ``TypeError``, or
 something else) is irrelevant.  The exception from this point on is a
-DbfError, and the original exception is of no value.  However, if this
-exception is printed, we would currently see both.
+``DbfError``, and the original exception is of no value.  However, if
+this exception is printed, we would currently see both.
 
 
 Alternatives
 ============
-
 Several possibilities have been put forth:
 
-- ``raise as NewException()``
+* ``raise as NewException()``
 
-  Reuses the 'as' keyword; can be confusing since we are not really reraising
-  the originating exception
+  Reuses the ``as`` keyword; can be confusing since we are not really
+  reraising the originating exception
 
-- ``raise NewException() from None``
+* ``raise NewException() from None``
 
-  Follows existing syntax of explicitly declaring the originating exception
+  Follows existing syntax of explicitly declaring the originating
+  exception
 
-- ``exc = NewException(); exc.__context__ = None; raise exc``
+* ``exc = NewException(); exc.__context__ = None; raise exc``
 
   Very verbose way of the previous method
 
-- ``raise NewException.no_context(...)``
+* ``raise NewException.no_context(...)``
 
   Make context suppression a class method.
 
@@ -78,15 +79,91 @@
 
     raise KeyError() from NameError()
 
-but because the 'cause' is None the previous context is discarded.
-There is a patch to this effect attached to issue 6210 [#issue6210]_.
+but because the cause is ``None`` the previous context is not
+displayed by the default exception printing routines.
+
+
+Implementation Discussion
+=========================
+
+Currently, ``None`` is the default for both ``__context__`` and
+``__cause__``.  In order to support ``raise ... from None`` (which
+would set ``__cause__`` to ``None``) we need a different default value
+for ``__cause__``.  Several ideas were put forth on how to implement
+this at the language level:
+
+* Overwrite the previous exception information (side-stepping the
+  issue and leaving ``__cause__`` at ``None``).
+
+  Rejected as this can seriously hinder debugging due to `poor error
+  messages`_.
+
+* Use one of the boolean values in ``__cause__``: ``False`` would be
+  the default value, and would be replaced when ``from ...`` was used
+  with the explicity chained exception or ``None``.
+
+  Rejected as this encourages the use of two different objects types
+  for ``__cause__`` with one of them (boolean) not allowed to have the
+  full range of possible values (``True`` would never be used).
+
+* Create a special exception class, ``__NoException__``.
+
+  Rejected as possibly confusing, possibly being mistakenly raised by
+  users, and not being a truly unique value as ``None``, ``True``, and
+  ``False`` are.
+
+* Use ``Ellipsis`` as the default value (the ``...`` singleton).
+
+  Accepted.  There are no other possible values; it cannot be raised
+  as it is not an exception; it has the connotation of 'fill in the
+  rest...' as in ``__cause__`` is not set, look in ``__context__`` for
+  it.
+
+
+Language Details
+================
+
+To support ``from None``, ``__context__`` will stay as it is, but
+``__cause__`` will start out as ``Ellipsis`` and will change to
+``None`` when the ``raise ... from None`` method is used.
+
+============================================  ==================  =======================================
+form                                          __context__         __cause__
+============================================  ==================  =======================================
+raise                                         ``None``            ``Ellipsis``
+reraise                                       previous exception  ``Ellipsis``
+reraise from ``None`` | ``ChainedException``  previous exception  ``None`` | explicitly chained exception
+============================================  ==================  =======================================
+
+The default exception printing routine will then:
+
+* If ``__cause__`` is ``Ellipsis`` the ``__context__`` (if any) will
+  be printed.
+
+* If ``__cause__`` is ``None`` the ``__context__`` will not be
+  printed.
+
+* If ``__cause__`` is anything else, ``__cause__`` will be printed.
+
+
+Patches
+=======
+
+There is a patch for CPython implementing this attached to `Issue
+6210`_.
 
 
 References
 ==========
 
-.. [#issue6210]
+Discussion and refinements in this `thread on python-dev`_.
+
+.. _poor error messages:
+   http://bugs.python.org/msg152294
+.. _issue 6210:
    http://bugs.python.org/issue6210
+.. _Thread on python-dev:
+   http://mail.python.org/pipermail/python-dev/2012-January/115838.html
 
 
 Copyright
@@ -95,7 +172,6 @@
 This document has been placed in the public domain.
 
 
-
 ..
    Local Variables:
    mode: indented-text

-- 
Repository URL: http://hg.python.org/peps


More information about the Python-checkins mailing list