2003-06-09 00:04:31 -04:00
|
|
|
|
PEP: 317
|
|
|
|
|
Title: Eliminate Implicit Exception Instantiation
|
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
|
|
|
|
Author: Steven Taschuk <staschuk@telusplanet.net>
|
2003-06-16 19:46:47 -04:00
|
|
|
|
Status: Rejected
|
2003-06-09 00:04:31 -04:00
|
|
|
|
Type: Standards Track
|
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
|
Created: 06-May-2003
|
|
|
|
|
Python-Version: 2.4
|
2003-06-16 19:46:47 -04:00
|
|
|
|
Post-History: 09-Jun-2003
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
"For clarity in new code, the form ``raise class(argument, ...)``
|
|
|
|
|
is recommended (i.e. make an explicit call to the constructor)."
|
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
-- Guido van Rossum, in 1997 [1]_
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
This PEP proposes the formal deprecation and eventual elimination of
|
|
|
|
|
forms of the ``raise`` statement which implicitly instantiate an
|
|
|
|
|
exception. For example, statements such as ::
|
|
|
|
|
|
|
|
|
|
raise HullBreachError
|
|
|
|
|
raise KitchenError, 'all out of baked beans'
|
|
|
|
|
|
|
|
|
|
must under this proposal be replaced with their synonyms ::
|
|
|
|
|
|
|
|
|
|
raise HullBreachError()
|
|
|
|
|
raise KitchenError('all out of baked beans')
|
|
|
|
|
|
|
|
|
|
Note that these latter statements are already legal, and that this PEP
|
|
|
|
|
does not change their meaning.
|
|
|
|
|
|
|
|
|
|
Eliminating these forms of ``raise`` makes it impossible to use string
|
|
|
|
|
exceptions; accordingly, this PEP also proposes the formal deprecation
|
|
|
|
|
and eventual elimination of string exceptions.
|
|
|
|
|
|
|
|
|
|
Adoption of this proposal breaks backwards compatibility. Under the
|
|
|
|
|
proposed implementation schedule, Python 2.4 will introduce warnings
|
|
|
|
|
about uses of ``raise`` which will eventually become incorrect, and
|
|
|
|
|
Python 3.0 will eliminate them entirely. (It is assumed that this
|
|
|
|
|
transition period -- 2.4 to 3.0 -- will be at least one year long, to
|
2022-01-21 06:03:51 -05:00
|
|
|
|
comply with the guidelines of :pep:`5`.)
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Motivation
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
String Exceptions
|
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
|
|
It is assumed that removing string exceptions will be uncontroversial,
|
2003-06-09 00:43:39 -04:00
|
|
|
|
since it has been intended since at least Python 1.5, when the
|
|
|
|
|
standard exception types were changed to classes [1]_.
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
For the record: string exceptions should be removed because the
|
2003-06-09 00:43:39 -04:00
|
|
|
|
presence of two kinds of exception complicates the language without
|
|
|
|
|
any compensation. Instance exceptions are superior because, for
|
|
|
|
|
example,
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
* the class-instance relationship more naturally expresses the
|
|
|
|
|
relationship between the exception type and value,
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
* they can be organized naturally using superclass-subclass
|
|
|
|
|
relationships, and
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
* they can encapsulate error-reporting behaviour (for example).
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Implicit Instantiation
|
|
|
|
|
----------------------
|
|
|
|
|
|
|
|
|
|
Guido's 1997 essay [1]_ on changing the standard exceptions into
|
|
|
|
|
classes makes clear why ``raise`` can instantiate implicitly:
|
|
|
|
|
|
|
|
|
|
"The raise statement has been extended to allow raising a class
|
|
|
|
|
exception without explicit instantiation. The following forms,
|
2003-06-09 00:43:39 -04:00
|
|
|
|
called the "compatibility forms" of the raise statement [...] The
|
|
|
|
|
motivation for introducing the compatibility forms was to allow
|
2003-06-09 00:04:31 -04:00
|
|
|
|
backward compatibility with old code that raised a standard
|
|
|
|
|
exception."
|
|
|
|
|
|
|
|
|
|
For example, it was desired that pre-1.5 code which used string
|
|
|
|
|
exception syntax such as ::
|
|
|
|
|
|
|
|
|
|
raise TypeError, 'not an int'
|
|
|
|
|
|
|
|
|
|
would work both on versions of Python in which ``TypeError`` was a
|
|
|
|
|
string, and on versions in which it was a class.
|
|
|
|
|
|
|
|
|
|
When no such consideration obtains -- that is, when the desired
|
2003-06-09 00:43:39 -04:00
|
|
|
|
exception type is not a string in any version of the software which
|
|
|
|
|
the code must support -- there is no good reason to instantiate
|
|
|
|
|
implicitly, and it is clearer not to. For example:
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
1. In the code ::
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
try:
|
|
|
|
|
raise MyError, raised
|
|
|
|
|
except MyError, caught:
|
|
|
|
|
pass
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
the syntactic parallel between the ``raise`` and ``except``
|
|
|
|
|
statements strongly suggests that ``raised`` and ``caught`` refer
|
|
|
|
|
to the same object. For string exceptions this actually is the
|
|
|
|
|
case, but for instance exceptions it is not.
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
2. When instantiation is implicit, it is not obvious when it occurs,
|
|
|
|
|
for example, whether it occurs when the exception is raised or when
|
|
|
|
|
it is caught. Since it actually happens at the ``raise``, the code
|
|
|
|
|
should say so.
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
(Note that at the level of the C API, an exception can be "raised"
|
|
|
|
|
and "caught" without being instantiated; this is used as an
|
|
|
|
|
optimization by, for example, ``PyIter_Next``. But in Python, no
|
|
|
|
|
such optimization is or should be available.)
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
3. An implicitly instantiating ``raise`` statement with no arguments,
|
|
|
|
|
such as ::
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
raise MyError
|
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
simply does not do what it says: it does not raise the named
|
|
|
|
|
object.
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
4. The equivalence of ::
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
raise MyError
|
|
|
|
|
raise MyError()
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
conflates classes and instances, creating a possible source of
|
|
|
|
|
confusion for beginners. (Moreover, it is not clear that the
|
|
|
|
|
interpreter could distinguish between a new-style class and an
|
|
|
|
|
instance of such a class, so implicit instantiation may be an
|
|
|
|
|
obstacle to any future plan to let exceptions be new-style
|
|
|
|
|
objects.)
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
In short, implicit instantiation has no advantages other than
|
|
|
|
|
backwards compatibility, and so should be phased out along with what
|
|
|
|
|
it exists to ensure compatibility with, namely, string exceptions.
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Specification
|
|
|
|
|
=============
|
|
|
|
|
|
|
|
|
|
The syntax of ``raise_stmt`` [3]_ is to be changed from ::
|
|
|
|
|
|
|
|
|
|
raise_stmt ::= "raise" [expression ["," expression ["," expression]]]
|
|
|
|
|
|
|
|
|
|
to ::
|
|
|
|
|
|
|
|
|
|
raise_stmt ::= "raise" [expression ["," expression]]
|
|
|
|
|
|
|
|
|
|
If no expressions are present, the ``raise`` statement behaves as it
|
|
|
|
|
does presently: it re-raises the last exception that was active in the
|
|
|
|
|
current scope, and if no exception has been active in the current
|
|
|
|
|
scope, a ``TypeError`` is raised indicating that this is the problem.
|
|
|
|
|
|
|
|
|
|
Otherwise, the first expression is evaluated, producing the *raised
|
|
|
|
|
object*. Then the second expression is evaluated, if present,
|
|
|
|
|
producing the *substituted traceback*. If no second expression is
|
|
|
|
|
present, the substituted traceback is ``None``.
|
|
|
|
|
|
|
|
|
|
The raised object must be an instance. The class of the instance is
|
2003-06-09 00:43:39 -04:00
|
|
|
|
the exception type, and the instance itself is the exception value.
|
|
|
|
|
If the raised object is not an instance -- for example, if it is a
|
|
|
|
|
class or string -- a ``TypeError`` is raised.
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
If the substituted traceback is not ``None``, it must be a traceback
|
|
|
|
|
object, and it is substituted instead of the current location as the
|
|
|
|
|
place where the exception occurred. If it is neither a traceback
|
|
|
|
|
object nor ``None``, a ``TypeError`` is raised.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Backwards Compatibility
|
|
|
|
|
=======================
|
|
|
|
|
|
|
|
|
|
Migration Plan
|
|
|
|
|
--------------
|
|
|
|
|
|
|
|
|
|
Future Statement
|
|
|
|
|
''''''''''''''''
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
Under the :pep:`236` future statement::
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
from __future__ import raise_with_two_args
|
|
|
|
|
|
|
|
|
|
the syntax and semantics of the ``raise`` statement will be as
|
|
|
|
|
described above. This future feature is to appear in Python 2.4; its
|
|
|
|
|
effect is to become standard in Python 3.0.
|
|
|
|
|
|
|
|
|
|
As the examples below illustrate, this future statement is only needed
|
|
|
|
|
for code which uses the substituted traceback argument to ``raise``;
|
|
|
|
|
simple exception raising does not require it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Warnings
|
|
|
|
|
''''''''
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
Three new :pep:`warnings <230>`, all of category ``DeprecationWarning``, are
|
2003-06-09 00:43:39 -04:00
|
|
|
|
to be issued to point out uses of ``raise`` which will become
|
|
|
|
|
incorrect under the proposed changes.
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
The first warning is issued when a ``raise`` statement is executed in
|
2003-06-09 00:43:39 -04:00
|
|
|
|
which the first expression evaluates to a string. The message for
|
|
|
|
|
this warning is::
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
raising strings will be impossible in the future
|
|
|
|
|
|
|
|
|
|
The second warning is issued when a ``raise`` statement is executed in
|
|
|
|
|
which the first expression evaluates to a class. The message for this
|
|
|
|
|
warning is::
|
|
|
|
|
|
|
|
|
|
raising classes will be impossible in the future
|
|
|
|
|
|
|
|
|
|
The third warning is issued when a ``raise`` statement with three
|
|
|
|
|
expressions is compiled. (Not, note, when it is executed; this is
|
|
|
|
|
important because the ``SyntaxError`` which this warning presages will
|
|
|
|
|
occur at compile-time.) The message for this warning is::
|
|
|
|
|
|
|
|
|
|
raising with three arguments will be impossible in the future
|
|
|
|
|
|
|
|
|
|
These warnings are to appear in Python 2.4, and disappear in Python
|
|
|
|
|
3.0, when the conditions which cause them are simply errors.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Examples
|
|
|
|
|
--------
|
|
|
|
|
|
|
|
|
|
Code Using Implicit Instantiation
|
|
|
|
|
'''''''''''''''''''''''''''''''''
|
|
|
|
|
|
|
|
|
|
Code such as ::
|
|
|
|
|
|
|
|
|
|
class MyError(Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
raise MyError, 'spam'
|
|
|
|
|
|
|
|
|
|
will issue a warning when the ``raise`` statement is executed. The
|
|
|
|
|
``raise`` statement should be changed to instantiate explicitly::
|
|
|
|
|
|
|
|
|
|
raise MyError('spam')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Code Using String Exceptions
|
|
|
|
|
''''''''''''''''''''''''''''
|
|
|
|
|
|
|
|
|
|
Code such as ::
|
|
|
|
|
|
|
|
|
|
MyError = 'spam'
|
|
|
|
|
raise MyError, 'eggs'
|
|
|
|
|
|
|
|
|
|
will issue a warning when the ``raise`` statement is executed. The
|
|
|
|
|
exception type should be changed to a class::
|
|
|
|
|
|
|
|
|
|
class MyError(Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
and, as in the previous example, the ``raise`` statement should be
|
|
|
|
|
changed to instantiate explicitly ::
|
|
|
|
|
|
|
|
|
|
raise MyError('eggs')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Code Supplying a Traceback Object
|
|
|
|
|
'''''''''''''''''''''''''''''''''
|
|
|
|
|
|
|
|
|
|
Code such as ::
|
|
|
|
|
|
|
|
|
|
raise MyError, 'spam', mytraceback
|
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
will issue a warning when compiled. The statement should be changed
|
|
|
|
|
to ::
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
raise MyError('spam'), mytraceback
|
|
|
|
|
|
|
|
|
|
and the future statement ::
|
|
|
|
|
|
|
|
|
|
from __future__ import raise_with_two_args
|
|
|
|
|
|
2003-06-09 00:43:39 -04:00
|
|
|
|
should be added at the top of the module. Note that adding this
|
|
|
|
|
future statement also turns the other two warnings into errors, so the
|
|
|
|
|
changes described in the previous examples must also be applied.
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
The special case ::
|
|
|
|
|
|
|
|
|
|
raise sys.exc_type, sys.exc_info, sys.exc_traceback
|
|
|
|
|
|
|
|
|
|
(which is intended to re-raise a previous exception) should be changed
|
|
|
|
|
simply to ::
|
|
|
|
|
|
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A Failure of the Plan
|
|
|
|
|
'''''''''''''''''''''
|
|
|
|
|
|
|
|
|
|
It may occur that a ``raise`` statement which raises a string or
|
2003-06-09 00:43:39 -04:00
|
|
|
|
implicitly instantiates is not executed in production or testing
|
|
|
|
|
during the phase-in period for this PEP. In that case, it will not
|
|
|
|
|
issue any warnings, but will instead suddenly fail one day in Python
|
|
|
|
|
3.0 or a subsequent version. (The failure is that the wrong exception
|
|
|
|
|
gets raised, namely a ``TypeError`` complaining about the arguments to
|
2003-06-09 00:04:31 -04:00
|
|
|
|
``raise``, instead of the exception intended.)
|
|
|
|
|
|
|
|
|
|
Such cases can be made rarer by prolonging the phase-in period; they
|
|
|
|
|
cannot be made impossible short of issuing at compile-time a warning
|
|
|
|
|
for every ``raise`` statement.
|
|
|
|
|
|
|
|
|
|
|
2003-06-16 19:46:47 -04:00
|
|
|
|
Rejection
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
If this PEP were accepted, nearly all existing Python code would need
|
|
|
|
|
to be reviewed and probably revised; even if all the above arguments
|
|
|
|
|
in favour of explicit instantiation are accepted, the improvement in
|
|
|
|
|
clarity is too minor to justify the cost of doing the revision and the
|
|
|
|
|
risk of new bugs introduced thereby.
|
|
|
|
|
|
|
|
|
|
This proposal has therefore been rejected [6]_.
|
|
|
|
|
|
|
|
|
|
Note that string exceptions are slated for removal independently of
|
|
|
|
|
this proposal; what is rejected is the removal of implicit exception
|
|
|
|
|
instantiation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Summary of Discussion
|
|
|
|
|
=====================
|
|
|
|
|
|
|
|
|
|
A small minority of respondents were in favour of the proposal, but
|
|
|
|
|
the dominant response was that any such migration would be costly
|
|
|
|
|
out of proportion to the putative benefit. As noted above, this
|
|
|
|
|
point is sufficient in itself to reject the PEP.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
New-Style Exceptions
|
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
|
|
Implicit instantiation might conflict with future plans to allow
|
|
|
|
|
instances of new-style classes to be used as exceptions. In order to
|
|
|
|
|
decide whether to instantiate implicitly, the ``raise`` machinery must
|
|
|
|
|
determine whether the first argument is a class or an instance -- but
|
|
|
|
|
with new-style classes there is no clear and strong distinction.
|
|
|
|
|
|
|
|
|
|
Under this proposal, the problem would be avoided because the
|
|
|
|
|
exception would already have been instantiated. However, there are
|
|
|
|
|
two plausible alternative solutions:
|
|
|
|
|
|
|
|
|
|
1. Require exception types to be subclasses of ``Exception``, and
|
|
|
|
|
instantiate implicitly if and only if ::
|
|
|
|
|
|
|
|
|
|
issubclass(firstarg, Exception)
|
|
|
|
|
|
|
|
|
|
2. Instantiate implicitly if and only if ::
|
|
|
|
|
|
|
|
|
|
isinstance(firstarg, type)
|
|
|
|
|
|
|
|
|
|
Thus eliminating implicit instantiation entirely is not necessary to
|
|
|
|
|
solve this problem.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ugliness of Explicit Instantiation
|
|
|
|
|
----------------------------------
|
|
|
|
|
|
|
|
|
|
Some respondents felt that the explicitly instantiating syntax is
|
|
|
|
|
uglier, especially in cases when no arguments are supplied to the
|
|
|
|
|
exception constructor::
|
|
|
|
|
|
|
|
|
|
raise TypeError()
|
|
|
|
|
|
|
|
|
|
The problem is particularly acute when the exception instance itself
|
|
|
|
|
is not of interest, that is, when the only relevant point is the
|
|
|
|
|
exception type::
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# ... deeply nested search loop ...
|
|
|
|
|
raise Found
|
|
|
|
|
except Found:
|
|
|
|
|
# ...
|
|
|
|
|
|
|
|
|
|
In such cases the symmetry between ``raise`` and ``except`` can be
|
|
|
|
|
more expressive of the intent of the code.
|
|
|
|
|
|
|
|
|
|
Guido opined that the implicitly instantiating syntax is "a tad
|
|
|
|
|
prettier" even for cases with a single argument, since it has less
|
|
|
|
|
punctuation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Performance Penalty of Warnings
|
|
|
|
|
-------------------------------
|
|
|
|
|
|
|
|
|
|
Experience with deprecating ``apply()`` shows that use of the warning
|
|
|
|
|
framework can incur a significant performance penalty.
|
|
|
|
|
|
|
|
|
|
Code which instantiates explicitly would not be affected, since the
|
|
|
|
|
run-time checks necessary to determine whether to issue a warning are
|
|
|
|
|
exactly those which are needed to determine whether to instantiate
|
|
|
|
|
implicitly in the first place. That is, such statements are already
|
|
|
|
|
incurring the cost of these checks.
|
|
|
|
|
|
|
|
|
|
Code which instantiates implicitly would incur a large cost: timing
|
|
|
|
|
trials indicate that issuing a warning (whether it is suppressed or
|
|
|
|
|
not) takes about five times more time than simply instantiating,
|
|
|
|
|
raising, and catching an exception.
|
|
|
|
|
|
|
|
|
|
This penalty is mitigated by the fact that ``raise`` statements are
|
|
|
|
|
rarely on performance-critical execution paths.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Traceback Argument
|
|
|
|
|
------------------
|
|
|
|
|
|
|
|
|
|
As the proposal stands, it would be impossible to use the traceback
|
|
|
|
|
argument to ``raise`` conveniently with all 2.x versions of Python.
|
|
|
|
|
|
|
|
|
|
For compatibility with versions < 2.4, the three-argument form must be
|
|
|
|
|
used; but this form would produce warnings with versions >= 2.4.
|
|
|
|
|
Those warnings could be suppressed, but doing so is awkward because
|
|
|
|
|
the relevant type of warning is issued at compile-time.
|
|
|
|
|
|
|
|
|
|
If this PEP were still under consideration, this objection would be
|
|
|
|
|
met by extending the phase-in period. For example, warnings could
|
|
|
|
|
first be issued in 3.0, and become errors in some later release.
|
|
|
|
|
|
|
|
|
|
|
2003-06-09 00:04:31 -04:00
|
|
|
|
References
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
.. [1] "Standard Exception Classes in Python 1.5", Guido van Rossum.
|
|
|
|
|
http://www.python.org/doc/essays/stdexceptions.html
|
|
|
|
|
|
|
|
|
|
.. [3] "Python Language Reference", Guido van Rossum.
|
2008-10-02 08:51:05 -04:00
|
|
|
|
http://docs.python.org/reference/simple_stmts.html#raise
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
2003-06-16 19:46:47 -04:00
|
|
|
|
.. [6] Guido van Rossum, 11 June 2003 post to ``python-dev``.
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2003-June/036176.html
|
2003-06-16 19:46:47 -04:00
|
|
|
|
|
2003-06-09 00:04:31 -04:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
End:
|