Update PEP to cover the deprecation of BaseException.message in Python 2.6.

This commit is contained in:
Brett Cannon 2007-04-19 19:05:14 +00:00
parent e3aab6db4b
commit ba82685d7d
1 changed files with 84 additions and 83 deletions

View File

@ -2,8 +2,7 @@ PEP: 352
Title: Required Superclass for Exceptions
Version: $Revision$
Last-Modified: $Date$
Author: Brett Cannon <brett@python.org>
Guido van Rossum <guido@python.org>
Author: Brett Cannon, Guido van Rossum
Status: Final
Type: Standards Track
Content-Type: text/x-rst
@ -15,16 +14,14 @@ Abstract
========
In Python 2.4 and before, any (classic) class can be raised as an
exception. The plan is to allow new-style classes starting in Python
2.5, but this makes the problem worse -- it would mean *any* class (or
instance) can be raised! (This is not the case in the final version;
only built-in exceptions can be new-style which means you need to
inherit from a built-in exception to have user-defined exceptions also
be new-style) This is a problem because it
prevents any guarantees from being made about the interface of exceptions.
exception. The plan for 2.5 was to allow new-style classes, but this
makes the problem worse -- it would mean *any* class (or
instance) can be raised! This is a problem as it prevents any
guarantees from being made about the interface of exceptions.
This PEP proposes introducing a new superclass that all raised objects
must inherit from. Imposing the restriction will allow a standard
interface for exceptions to exist that can be relied upon.
interface for exceptions to exist that can be relied upon. It also
leads to a known hierarchy for all exceptions to adhere to.
One might counter that requiring a specific base class for a
particular interface is unPythonic. However, in the specific case of
@ -40,13 +37,13 @@ currently stands, all exceptions in the built-in namespace inherit
from Exception. This is a problem since this includes two exceptions
(KeyboardInterrupt and SystemExit) that often need to be excepted from
the application's exception handling: the default behavior of shutting
the interpreter down with resp. Without a traceback is usually more
desirable than whatever the application might do (with the possible
exception of applications that emulate Python's interactive command
loop with ``>>>`` prompt). Changing it so that these two exceptions
inherit from the common superclass instead of Exception will make it
easy for people to write ``except`` clauses that are not overreaching
and not catch exceptions that should propagate up.
the interpreter down without a traceback is usually more desirable than
whatever the application might do (with the possible exception of
applications that emulate Python's interactive command loop with
``>>>`` prompt). Changing it so that these two exceptions inherit
from the common superclass instead of Exception will make it easy for
people to write ``except`` clauses that are not overreaching and not
catch exceptions that should propagate up.
This PEP is based on previous work done for PEP 348 [#pep348]_.
@ -55,8 +52,7 @@ Requiring a Common Superclass
=============================
This PEP proposes introducing a new exception named BaseException that
is a new-style class and has a single attribute, ``message`` (that
will cause the deprecation of the existing ``args`` attribute) Below
is a new-style class and has a single attribute, ``args``. Below
is the code as the exception will work in Python 3.0 (how it will
work in Python 2.x is covered in the `Transition Plan`_ section)::
@ -64,46 +60,36 @@ work in Python 2.x is covered in the `Transition Plan`_ section)::
"""Superclass representing the base of the exception hierarchy.
Provides a 'message' attribute that contains either the single
argument to the constructor or the empty string. This attribute
is used in the string representation for the
exception. This is so that it provides the extra details in the
traceback.
Provides an 'args' attribute that contains all arguments passed
to the constructor. Suggested practice, though, is that only a
single string argument be passed to the constructor.
"""
def __init__(self, message=''):
"""Set the 'message' attribute'"""
self.message = message
def __init__(self, *args):
"""Set the 'args' attribute'"""
self.args = args
def __str__(self):
"""Return the str of 'message'"""
return str(self.message)
"""Return the str of
``args[0] if len(args) == 1 else args``."""
if len(self.args) == 1:
return str(self.args[0])
else:
return str(self.args)
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, repr(self.message))
return "%s(*%s)" % (self.__class__.__name__, repr(self.args))
The ``message`` attribute will contain either the first argument
passed in at instantiation of the object or the empty string if no
arguments were passed in. The attribute is meant to act as a common
location to store any message that is to be passed along
with the exception that goes beyond the location of where the exception
occurred and the exception's type.
No restriction is placed upon what may be passed in for ``message``
No restriction is placed upon what may be passed in for ``args``
for backwards-compatibility reasons. In practice, though, only
strings should be used. This keeps the string representation of the
exception to be a useful message about the exception that is
human-readable. Including programmatic information (e.g., an error
code number) should be stored as a separate attribute in a subclass.
The ``args`` attribute is deprecated. While allowing multiple
arguments to be passed can be helpful, it is in no way essential. It
also does not make it clear which argument is going to be represented
by the ``__str__`` method. Restricting initialization to accepting a
single argument keeps the API simple and clear. This also means
providing a ``__getitem__`` method is unneeded for exceptions and thus
will be deprecated as well.
a single string argument should be used. This keeps the string
representation of the exception to be a useful message about the
exception that is human-readable; this is why the ``__str__`` method
special-cases on length-1 ``args`` value. Including programmatic
information (e.g., an error code number) should be stored as a
separate attribute in a subclass.
The ``raise`` statement will be changed to require that any object
passed to it must inherit from BaseException. This will make sure
@ -183,37 +169,18 @@ Here is BaseException as implemented in the 2.x series::
"""Superclass representing the base of the exception hierarchy.
Provides a 'message' attribute that contains any single argument
passed in during instantiation. If more than one argument is
passed, it is set to the empty string. It is meant to represent
any message (usually some text) that should be printed out with
the traceback. Unfortunately, for backwards-compatibility, the
'args' attribute (discussed below) is used for printing out to
tracebacks.
The 'args' attribute and __getitem__ method are provided for
backwards-compatibility and will be deprecated at some point.
The __getitem__ method is provided for backwards-compatibility
and will be deprecated at some point. The 'message' attribute
is also deprecated.
"""
def __init__(self, *args):
"""Set 'message' and 'args' attribute.
'args' will eventually be deprecated. But it is still used
when printing out tracebacks for backwards-compatibility.
Once 'args' is removed, though, 'message' will be used instead.
"""
"""Set the 'args' attribute."""
self.args = args
self.message = args[0] if args else ''
def __str__(self):
"""Return the str of args[0] or args, depending on length.
Once 'args' has been removed, 'message' will be used
exclusively for the str representation for exceptions.
"""
"""Return the str of args[0] or args, depending on length."""
return str(self.args[0]
if len(self.args) <= 1
else self.args)
@ -231,6 +198,16 @@ Here is BaseException as implemented in the 2.x series::
"""
return self.args[index]
def _get_message(self):
"""Method for 'message' property."""
warnings.warn("the 'message' attribute has been deprecated "
"since Python 2.6")
return self.args[0] if len(args) == 1 else ''
message = property(_get_message)
Deprecation of features in Python 2.9 is optional. This is because it
is not known at this time if Python 2.9 (which is slated to be the
@ -242,7 +219,7 @@ the proposed deprecation warnings for Python 2.9 will be revisited
when development of that version begins to determine if they are still
desired.
* Python 2.5
* Python 2.5 [done]
- all standard exceptions become new-style classes
@ -254,35 +231,56 @@ desired.
* Python 2.6
- deprecate catching string exceptions
- deprecate catching string exceptions [done]
- deprecate ``message`` attribute (see `Retracted Ideas`_)
* Python 2.7
- deprecate raising exceptions that do not inherit from BaseException
- remove ``message`` attribute
* Python 2.8
- deprecate catching exceptions that do not inherit from BaseException
* Python 2.9
- deprecate ``args`` and ``__getitem__`` (optional)
- deprecate ``__getitem__`` (optional)
* Python 3.0
- drop everything that was deprecated above:
+ string exceptions (both raising and catching)
+ string exceptions (both raising and catching) [done]
+ all exceptions must inherit from BaseException
+ all exceptions must inherit from BaseException [done]
+ drop ``args`` and ``__getitem__``
+ drop ``__getitem__``, ``message``
Implementation
==============
Retracted Ideas
===============
A previous version of this PEP that was implemented in Python 2.5
included a 'message' attribute on BaseException. Its purpose was to
begin a transition to BaseException accepting only a single argument.
This was to tighten the interface and to force people to use
attributes in subclasses to carry arbitrary information with an
exception instead of cramming it all into ``args``.
Unfortunately, while implementing the removal of the ``args``
attribute in Python 3.0 at the PyCon 2007 sprint
[#pycon2007-sprint-email]_, it was discovered that the transition was
very painful, especially for C extension modules. It was decided that
it would be better to deprecate the ``message`` attribute in
Python 2.6 (and remove in Python 2.7 and Python 3.0) and consider a
more long-term transition strategy in Python 3.0 to remove
multiple-argument support in BaseException in preference of accepting
only a single argument. Thus the introduction of ``message`` and the
original deprecation of ``args`` has been retracted.
The initial implementation of this PEP has been checked into Python 2.5 .
References
==========
@ -296,6 +294,9 @@ References
.. [#SF_1104669] SF patch #1104669 (new-style exceptions)
http://www.python.org/sf/1104669
.. [#pycon2007-sprint-email] python-3000 email ("How far to go with cleaning up exceptions")
http://mail.python.org/pipermail/python-3000/2007-March/005911.html
Copyright
=========