Permalink
Cannot retrieve contributors at this time
370 lines (257 sloc)
13.4 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
peps/pep-0236.txt
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| PEP: 236 | |
| Title: Back to the __future__ | |
| Version: $Revision$ | |
| Last-Modified: $Date$ | |
| Author: Tim Peters <tim.peters@gmail.com> | |
| Status: Final | |
| Type: Standards Track | |
| Content-Type: text/x-rst | |
| Created: 26-Feb-2001 | |
| Python-Version: 2.1 | |
| Post-History: 26-Feb-2001 | |
| Motivation | |
| ========== | |
| From time to time, Python makes an incompatible change to the advertised | |
| semantics of core language constructs, or changes their accidental | |
| (implementation-dependent) behavior in some way. While this is never done | |
| capriciously, and is always done with the aim of improving the language over | |
| the long term, over the short term it's contentious and disrupting. | |
| :pep:`5`, Guidelines for Language Evolution suggests ways to ease the pain, | |
| and this PEP introduces some machinery in support of that. | |
| :pep:`227`, Statically Nested Scopes is the first application, and will be | |
| used as an example here. | |
| Intent | |
| ====== | |
| [Note: This is policy, and so should eventually move into :pep:`5`] | |
| When an incompatible change to core language syntax or semantics is being | |
| made: | |
| 1. The release C that introduces the change does not change the syntax or | |
| semantics by default. | |
| 2. A future release R is identified in which the new syntax or semantics will | |
| be enforced. | |
| 3. The mechanisms described in :pep:`230`, Warning Framework are used to | |
| generate warnings, whenever possible, about constructs or operations whose | |
| meaning may [1]_ change in release R. | |
| 4. The new future_statement (see below) can be explicitly included in a module | |
| M to request that the code in module M use the new syntax or semantics in | |
| the current release C. | |
| So old code continues to work by default, for at least one release, although | |
| it may start to generate new warning messages. Migration to the new syntax or | |
| semantics can proceed during that time, using the future_statement to make | |
| modules containing it act as if the new syntax or semantics were already being | |
| enforced. | |
| Note that there is no need to involve the future_statement machinery in new | |
| features unless they can break existing code; fully backward- compatible | |
| additions can-- and should --be introduced without a corresponding | |
| future_statement. | |
| Syntax | |
| ====== | |
| A future_statement is simply a from/import statement using the reserved module | |
| name ``__future__``:: | |
| future_statement: "from" "__future__" "import" feature ["as" name] | |
| (","feature ["as" name])* | |
| feature: identifier | |
| name: identifier | |
| In addition, all future_statements must appear near the top of the module. The | |
| only lines that can appear before a future_statement are: | |
| + The module docstring (if any). | |
| + Comments. | |
| + Blank lines. | |
| + Other future_statements. | |
| Example:: | |
| """This is a module docstring.""" | |
| # This is a comment, preceded by a blank line and followed by | |
| # a future_statement. | |
| from __future__ import nested_scopes | |
| from math import sin | |
| from __future__ import alabaster_weenoblobs # compile-time error! | |
| # That was an error because preceded by a non-future_statement. | |
| Semantics | |
| ========= | |
| A future_statement is recognized and treated specially at compile time: | |
| changes to the semantics of core constructs are often implemented by | |
| generating different code. It may even be the case that a new feature | |
| introduces new incompatible syntax (such as a new reserved word), in which | |
| case the compiler may need to parse the module differently. Such decisions | |
| cannot be pushed off until runtime. | |
| For any given release, the compiler knows which feature names have been | |
| defined, and raises a compile-time error if a future_statement contains a | |
| feature not known to it [2]_. | |
| The direct runtime semantics are the same as for any ``import`` statement: | |
| there is a standard module ``__future__.py``, described later, and it will be | |
| imported in the usual way at the time the future_statement is executed. | |
| The *interesting* runtime semantics depend on the specific feature(s) | |
| "imported" by the future_statement(s) appearing in the module. | |
| Note that there is nothing special about the statement:: | |
| import __future__ [as name] | |
| That is not a future_statement; it's an ordinary import statement, with no | |
| special semantics or syntax restrictions. | |
| Example | |
| ======= | |
| Consider this code, in file scope.py:: | |
| x = 42 | |
| def f(): | |
| x = 666 | |
| def g(): | |
| print "x is", x | |
| g() | |
| f() | |
| Under 2.0, it prints:: | |
| x is 42 | |
| Nested scopes (:pep:`227`) are being introduced in 2.1. But under 2.1, it still | |
| prints:: | |
| x is 42 | |
| and also generates a warning. | |
| In 2.2, and also in 2.1 *if* ``from __future__ import nested_scopes`` is | |
| included at the top of ``scope.py``, it prints:: | |
| x is 666 | |
| Standard Module __future__.py | |
| ============================= | |
| ``Lib/__future__.py`` is a real module, and serves three purposes: | |
| 1. To avoid confusing existing tools that analyze import statements and expect | |
| to find the modules they're importing. | |
| 2. To ensure that future_statements run under releases prior to 2.1 at least | |
| yield runtime exceptions (the import of ``__future__`` will fail, because | |
| there was no module of that name prior to 2.1). | |
| 3. To document when incompatible changes were introduced, and when they will | |
| be-- or were --made mandatory. This is a form of executable documentation, | |
| and can be inspected programmatically via importing ``__future__`` and | |
| examining its contents. | |
| Each statement in ``__future__.py`` is of the form:: | |
| FeatureName = "_Feature(" OptionalRelease "," MandatoryRelease ")" | |
| where, normally, *OptionalRelease* < *MandatoryRelease*, and both are | |
| 5-tuples of the same form as ``sys.version_info``:: | |
| (PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int | |
| PY_MINOR_VERSION, # the 1; an int | |
| PY_MICRO_VERSION, # the 0; an int | |
| PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string | |
| PY_RELEASE_SERIAL # the 3; an int ) | |
| *OptionalRelease* records the first release in which:: | |
| from __future__ import FeatureName | |
| was accepted. | |
| In the case of *MandatoryReleases* that have not yet occurred, | |
| *MandatoryRelease* predicts the release in which the feature will become part | |
| of the language. | |
| Else *MandatoryRelease* records when the feature became part of the language; | |
| in releases at or after that, modules no longer need:: | |
| from __future__ import FeatureName | |
| to use the feature in question, but may continue to use such imports. | |
| *MandatoryRelease* may also be ``None``, meaning that a planned feature got | |
| dropped. | |
| Instances of ``class _Feature`` have two corresponding methods, | |
| ``.getOptionalRelease()`` and ``.getMandatoryRelease()``. | |
| No feature line will ever be deleted from ``__future__.py``. | |
| Example line:: | |
| nested_scopes = _Feature((2, 1, 0, "beta", 1), (2, 2, 0, "final", 0)) | |
| This means that:: | |
| from __future__ import nested_scopes | |
| will work in all releases at or after 2.1b1, and that nested_scopes are | |
| intended to be enforced starting in release 2.2. | |
| Resolved Problem: Runtime Compilation | |
| ====================================== | |
| Several Python features can compile code during a module's runtime: | |
| 1. The ``exec`` statement. | |
| 2. The ``execfile()`` function. | |
| 3. The ``compile()`` function. | |
| 4. The ``eval()`` function. | |
| 5. The ``input()`` function. | |
| Since a module M containing a future_statement naming feature F explicitly | |
| requests that the current release act like a future release with respect to F, | |
| any code compiled dynamically from text passed to one of these from within M | |
| should probably also use the new syntax or semantics associated with F. The | |
| 2.1 release does behave this way. | |
| This isn't always desired, though. For example, ``doctest.testmod(M)`` | |
| compiles examples taken from strings in M, and those examples should use M's | |
| choices, not necessarily the doctest module's choices. In the 2.1 release, | |
| this isn't possible, and no scheme has yet been suggested for working around | |
| this. NOTE: :pep:`264` later addressed this in a flexible way, by adding | |
| optional arguments to ``compile()``. | |
| In any case, a future_statement appearing "near the top" (see Syntax above) of | |
| text compiled dynamically by an ``exec``, ``execfile()`` or ``compile()`` | |
| applies to the code block generated, but has no further effect on the module | |
| that executes such an ``exec``, ``execfile()`` or ``compile()``. This can't | |
| be used to affect ``eval()`` or ``input()``, however, because they only allow | |
| expression input, and a future_statement is not an expression. | |
| Resolved Problem: Native Interactive Shells | |
| ============================================ | |
| There are two ways to get an interactive shell: | |
| 1. By invoking Python from a command line without a script argument. | |
| 2. By invoking Python from a command line with the ``-i`` switch and with a | |
| script argument. | |
| An interactive shell can be seen as an extreme case of runtime compilation | |
| (see above): in effect, each statement typed at an interactive shell prompt | |
| runs a new instance of ``exec``, ``compile()`` or ``execfile()``. A | |
| future_statement typed at an interactive shell applies to the rest of the | |
| shell session's life, as if the future_statement had appeared at the top of a | |
| module. | |
| Resolved Problem: Simulated Interactive Shells | |
| =============================================== | |
| Interactive shells "built by hand" (by tools such as IDLE and the Emacs | |
| Python-mode) should behave like native interactive shells (see above). | |
| However, the machinery used internally by native interactive shells has not | |
| been exposed, and there isn't a clear way for tools building their own | |
| interactive shells to achieve the desired behavior. | |
| NOTE: :pep:`264` later addressed this, by adding intelligence to the standard | |
| ``codeop.py``. Simulated shells that don't use the standard library shell | |
| helpers can get a similar effect by exploiting the new optional arguments to | |
| ``compile()`` added by :pep:`264`. | |
| Questions and Answers | |
| ===================== | |
| What about a "from __past__" version, to get back *old* behavior? | |
| ----------------------------------------------------------------- | |
| Outside the scope of this PEP. Seems unlikely to the author, though. Write a | |
| PEP if you want to pursue it. | |
| What about incompatibilities due to changes in the Python virtual machine? | |
| -------------------------------------------------------------------------- | |
| Outside the scope of this PEP, although :pep:`5` suggests a grace period | |
| there too, and the future_statement may also have a role to play there. | |
| What about incompatibilities due to changes in Python's C API? | |
| -------------------------------------------------------------- | |
| Outside the scope of this PEP. | |
| I want to wrap future_statements in try/except blocks, so I can use different code depending on which version of Python I'm running. Why can't I? | |
| ------------------------------------------------------------------------------------------------------------------------------------------------- | |
| Sorry! ``try/except`` is a runtime feature; future_statements are primarily | |
| compile-time gimmicks, and your ``try/except`` happens long after the compiler | |
| is done. That is, by the time you do ``try/except``, the semantics in effect | |
| for the module are already a done deal. Since the ``try/except`` wouldn't | |
| accomplish what it *looks* like it should accomplish, it's simply not allowed. | |
| We also want to keep these special statements very easy to find and to | |
| recognize. | |
| Note that you *can* import ``__future__`` directly, and use the information in | |
| it, along with ``sys.version_info``, to figure out where the release you're | |
| running under stands in relation to a given feature's status. | |
| Going back to the nested_scopes example, what if release 2.2 comes along and I still haven't changed my code? How can I keep the 2.1 behavior then? | |
| ---------------------------------------------------------------------------------------------------------------------------------------------------- | |
| By continuing to use 2.1, and not moving to 2.2 until you do change your | |
| code. The purpose of future_statement is to make life easier for people who | |
| keep current with the latest release in a timely fashion. We don't hate you | |
| if you don't, but your problems are much harder to solve, and somebody with | |
| those problems will need to write a PEP addressing them. future_statement is | |
| aimed at a different audience. | |
| Overloading ``import`` sucks. Why not introduce a new statement for this? | |
| -------------------------------------------------------------------------- | |
| Like maybe ``lambda lambda nested_scopes``? That is, unless we introduce a | |
| new keyword, we can't introduce an entirely new statement. But if we | |
| introduce a new keyword, that in itself would break old code. That would be | |
| too ironic to bear. Yes, overloading ``import`` does suck, but not as | |
| energetically as the alternatives -- as is, future_statements are 100% | |
| backward compatible. | |
| Copyright | |
| ========= | |
| This document has been placed in the public domain. | |
| References and Footnotes | |
| ======================== | |
| .. [1] Note that this is *may* and not *will*: better safe than sorry. Of course | |
| spurious warnings won't be generated when avoidable with reasonable cost. | |
| .. [2] This ensures that a future_statement run under a release prior to the | |
| first one in which a given feature is known (but >= 2.1) will raise a | |
| compile-time error rather than silently do a wrong thing. If transported | |
| to a release prior to 2.1, a runtime error will be raised because of the | |
| failure to import ``__future__`` (no such module existed in the standard | |
| distribution before the 2.1 release, and the double underscores make it a | |
| reserved name). | |
| .. | |
| Local Variables: | |
| mode: indented-text | |
| indent-tabs-mode: nil | |
| End: |