PEP: 415
Title: Implement context suppression with exception attributes
Version: $Revision$
Last-Modified: $Date$
Author: Benjamin Peterson <benjamin@python.org>
BDFL-Delegate: Nick Coghlan
Status: Final
Type: Standards Track
Content-Type: text/x-rst
Created: 26-Feb-2012
Python-Version: 3.3
Post-History: 26-Feb-2012
Replaces: 409
Resolution: https://mail.python.org/pipermail/python-dev/2012-May/119467.html


Abstract
========

PEP 409 introduced support for the ``raise exc from None`` construct to
allow the display of the exception context to be explicitly suppressed.
This PEP retains the language level changes already implemented in PEP 409,
but replaces the underlying implementation mechanism with a simpler approach
based on a new ``__suppress_context__`` attribute on all ``BaseException``
instances.


PEP Acceptance
==============

This PEP was accepted by Nick Coghlan on the 14th of May, 2012.


Rationale
=========

PEP 409 changes ``__cause__`` to be ``Ellipsis`` by default. Then if
``__cause__`` is set to ``None`` by ``raise exc from None``, no context or cause
will be printed should the exception be uncaught.

The main problem with this scheme is it complicates the role of
``__cause__``. ``__cause__`` should indicate the cause of the exception not
whether ``__context__`` should be printed or not. This use of ``__cause__`` is
also not easily extended in the future. For example, we may someday want to
allow the programmer to select which of ``__context__`` and ``__cause__`` will
be printed. The PEP 409 implementation is not amenable to this.

The use of ``Ellipsis`` is a hack. Before PEP 409, ``Ellipsis`` was used
exclusively in extended slicing. Extended slicing has nothing to do with
exceptions, so it's not clear to someone inspecting an exception object why
``__cause__`` should be set to ``Ellipsis``. Using ``Ellipsis`` by default for
``__cause__`` makes it asymmetrical with ``__context__``.


Proposal
========

A new attribute on ``BaseException``, ``__suppress_context__``, will
be introduced. Whenever ``__cause__`` is set, ``__suppress_context__``
will be set to ``True``. In particular, ``raise exc from cause``
syntax will set ``exc.__suppress_context__`` to ``True``. Exception
printing code will check for that attribute to determine whether
context and cause will be printed. ``__cause__`` will return to its
original purpose and values.

There is precedence for ``__suppress_context__`` with the
``print_line_and_file`` exception attribute.

To summarize, ``raise exc from cause`` will be equivalent to::

    exc.__cause__ = cause
    raise exc

where ``exc.__cause__ = cause`` implicitly sets
``exc.__suppress_context__``.


Patches
=======

There is a patch on `Issue 14133`_.


References
==========

.. _issue 14133:
   http://bugs.python.org/issue14133


Copyright
=========

This document has been placed in the public domain.


..
   Local Variables:
   mode: indented-text
   indent-tabs-mode: nil
   sentence-end-double-space: t
   fill-column: 70
   coding: utf-8
   End:
