Latest update from Ethan, marking PEP 409 as accepted.
This commit is contained in:
parent
5b1a3f5b4e
commit
7506ff282f
89
pep-0409.txt
89
pep-0409.txt
|
@ -3,17 +3,18 @@ Title: Suppressing exception context
|
||||||
Version: $Revision$
|
Version: $Revision$
|
||||||
Last-Modified: $Date$
|
Last-Modified: $Date$
|
||||||
Author: Ethan Furman <ethan@stoneleaf.us>
|
Author: Ethan Furman <ethan@stoneleaf.us>
|
||||||
Status: Draft
|
Status: Accepted
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
Content-Type: text/x-rst
|
Content-Type: text/x-rst
|
||||||
Created: 26-Jan-2012
|
Created: 26-Jan-2012
|
||||||
Post-History: 30-Aug-2002, 01-Feb-2012, 03-Feb-2012
|
Post-History: 30-Aug-2002, 01-Feb-2012, 03-Feb-2012
|
||||||
|
Resolution: http://mail.python.org/pipermail/python-dev/2012-February/116136.html
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
========
|
========
|
||||||
|
|
||||||
One of the open issues from PEP 3134 is suppressing context: currently
|
One of the open issues from PEP 3134 is suppressing context: currently
|
||||||
there is no way to do it. This PEP proposes one.
|
there is no way to do it. This PEP proposes one.
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,14 +23,14 @@ Rationale
|
||||||
|
|
||||||
There are two basic ways to generate exceptions:
|
There are two basic ways to generate exceptions:
|
||||||
|
|
||||||
1. Python does it (buggy code, missing resources, ending loops, etc.)
|
1) Python does it (buggy code, missing resources, ending loops, etc.)
|
||||||
|
|
||||||
2. manually (with a raise statement)
|
2) manually (with a raise statement)
|
||||||
|
|
||||||
When writing libraries, or even just custom classes, it can become
|
When writing libraries, or even just custom classes, it can become
|
||||||
necessary to raise exceptions; moreover it can be useful, even
|
necessary to raise exceptions; moreover it can be useful, even
|
||||||
necessary, to change from one exception to another. To take an
|
necessary, to change from one exception to another. To take an example
|
||||||
example from my dbf module::
|
from my dbf module::
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = int(value)
|
value = int(value)
|
||||||
|
@ -74,58 +75,55 @@ I proprose going with the second option::
|
||||||
|
|
||||||
raise NewException from None
|
raise NewException from None
|
||||||
|
|
||||||
It has the advantage of using the existing pattern of explicitly
|
It has the advantage of using the existing pattern of explicitly setting
|
||||||
setting the cause::
|
the cause::
|
||||||
|
|
||||||
raise KeyError() from NameError()
|
raise KeyError() from NameError()
|
||||||
|
|
||||||
but because the cause is ``None`` the previous context is not
|
but because the cause is ``None`` the previous context is not displayed
|
||||||
displayed by the default exception printing routines.
|
by the default exception printing routines.
|
||||||
|
|
||||||
|
|
||||||
Implementation Discussion
|
Implementation Discussion
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
Currently, ``None`` is the default for both ``__context__`` and
|
Currently, ``None`` is the default for both ``__context__`` and ``__cause__``.
|
||||||
``__cause__``. In order to support ``raise ... from None`` (which
|
In order to support ``raise ... from None`` (which would set ``__cause__`` to
|
||||||
would set ``__cause__`` to ``None``) we need a different default value
|
``None``) we need a different default value for ``__cause__``. Several ideas
|
||||||
for ``__cause__``. Several ideas were put forth on how to implement
|
were put forth on how to implement this at the language level:
|
||||||
this at the language level:
|
|
||||||
|
|
||||||
* Overwrite the previous exception information (side-stepping the
|
* Overwrite the previous exception information (side-stepping the issue and
|
||||||
issue and leaving ``__cause__`` at ``None``).
|
leaving ``__cause__`` at ``None``).
|
||||||
|
|
||||||
Rejected as this can seriously hinder debugging due to `poor error
|
Rejected as this can seriously hinder debugging due to
|
||||||
messages`_.
|
`poor error messages`_.
|
||||||
|
|
||||||
* Use one of the boolean values in ``__cause__``: ``False`` would be
|
* Use one of the boolean values in ``__cause__``: ``False`` would be the
|
||||||
the default value, and would be replaced when ``from ...`` was used
|
default value, and would be replaced when ``from ...`` was used with the
|
||||||
with the explicity chained exception or ``None``.
|
explicity chained exception or ``None``.
|
||||||
|
|
||||||
Rejected as this encourages the use of two different objects types
|
Rejected as this encourages the use of two different objects types for
|
||||||
for ``__cause__`` with one of them (boolean) not allowed to have the
|
``__cause__`` with one of them (boolean) not allowed to have the full range
|
||||||
full range of possible values (``True`` would never be used).
|
of possible values (``True`` would never be used).
|
||||||
|
|
||||||
* Create a special exception class, ``__NoException__``.
|
* Create a special exception class, ``__NoException__``.
|
||||||
|
|
||||||
Rejected as possibly confusing, possibly being mistakenly raised by
|
Rejected as possibly confusing, possibly being mistakenly raised by users,
|
||||||
users, and not being a truly unique value as ``None``, ``True``, and
|
and not being a truly unique value as ``None``, ``True``, and ``False`` are.
|
||||||
``False`` are.
|
|
||||||
|
|
||||||
* Use ``Ellipsis`` as the default value (the ``...`` singleton).
|
* Use ``Ellipsis`` as the default value (the ``...`` singleton).
|
||||||
|
|
||||||
Accepted. There are no other possible values; it cannot be raised
|
Accepted. There are no other possible values; it cannot be raised as it is
|
||||||
as it is not an exception; it has the connotation of 'fill in the
|
not an exception; it has the connotation of 'fill in the rest...' as in
|
||||||
rest...' as in ``__cause__`` is not set, look in ``__context__`` for
|
``__cause__`` is not set, look in ``__context__`` for it.
|
||||||
it.
|
|
||||||
|
|
||||||
|
|
||||||
Language Details
|
Language Details
|
||||||
================
|
================
|
||||||
|
|
||||||
To support ``from None``, ``__context__`` will stay as it is, but
|
To support ``from None``, ``__context__`` will stay as it is, but
|
||||||
``__cause__`` will start out as ``Ellipsis`` and will change to
|
``__cause__`` will start out as ``Ellipsis`` and will change to ``None``
|
||||||
``None`` when the ``raise ... from None`` method is used.
|
when the ``raise ... from None`` method is used.
|
||||||
|
|
||||||
============================================ ================== =======================================
|
============================================ ================== =======================================
|
||||||
form __context__ __cause__
|
form __context__ __cause__
|
||||||
|
@ -137,20 +135,26 @@ reraise from ``None`` | ``ChainedException`` previous exception ``None`` | exp
|
||||||
|
|
||||||
The default exception printing routine will then:
|
The default exception printing routine will then:
|
||||||
|
|
||||||
* If ``__cause__`` is ``Ellipsis`` the ``__context__`` (if any) will
|
* If ``__cause__`` is ``Ellipsis`` the ``__context__`` (if any) will be
|
||||||
be printed.
|
|
||||||
|
|
||||||
* If ``__cause__`` is ``None`` the ``__context__`` will not be
|
|
||||||
printed.
|
printed.
|
||||||
|
|
||||||
* If ``__cause__`` is anything else, ``__cause__`` will be printed.
|
* If ``__cause__`` is ``None`` the ``__context__`` will not be printed.
|
||||||
|
|
||||||
|
* if ``__cause__`` is anything else, ``__cause__`` will be printed.
|
||||||
|
|
||||||
|
In both of the latter cases the exception chain will stop being followed.
|
||||||
|
|
||||||
|
Because the default value for ``__cause__`` is now ``Ellipsis``::
|
||||||
|
|
||||||
|
raise Exception from Ellipsis
|
||||||
|
|
||||||
|
is allowed and will (re)set ``__cause__`` to ``Ellipsis``.
|
||||||
|
|
||||||
|
|
||||||
Patches
|
Patches
|
||||||
=======
|
=======
|
||||||
|
|
||||||
There is a patch for CPython implementing this attached to `Issue
|
There is a patch for CPython implementing this attached to `Issue 6210`_.
|
||||||
6210`_.
|
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
@ -171,7 +175,7 @@ Copyright
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
..
|
..
|
||||||
Local Variables:
|
Local Variables:
|
||||||
mode: indented-text
|
mode: indented-text
|
||||||
|
@ -180,3 +184,4 @@ This document has been placed in the public domain.
|
||||||
fill-column: 70
|
fill-column: 70
|
||||||
coding: utf-8
|
coding: utf-8
|
||||||
End:
|
End:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue