Other situations like this (was RE: [Python-Dev] Nested scopes resolution -- you can breathe again!)

Tim Peters tim.one@home.com
Fri, 23 Feb 2001 00:30:27 -0500


[Guido]
> We also believe that the magical import mechanism is useful
> enough to be reused for other situations like this; Tim will
> draft a PEP to describe in excruciating detail.

[Jeremy Hylton]
> ...
> I'm happy to hear that Tim will draft this PEP.  He didn't mention it
> at lunch today or I would have given him a big hug (or bought him a
> Coke).

Guido's msg was the first I heard of it too.  I think this is the same
process by which I got assigned to change Windows imports:  the issue came
up, and I opened my mouth <-0.9 wink>.

> As Tim knows, I think the PEP needs to say something about whether
> these magic imports create name bindings and what objects are
> bound to the names.
>
> Will we need an __nested_scopes__.py in the Lib directory?

Offhand, I suggest to create a real Lib/__future__.py, and let import code
get generated as always.  The purpose of __future__.py is to record release
info in an *obvious* place to look for it (BTW, best I can tell, sys.version
isn't documented anywhere, so this serves that purpose too <wink>):

------------------------------------------------------------------
"""__future__:  Record of phased-in incompatible language changes.

Each line is of the form:

    FeatureName = ReleaseInfo

ReleaseInfo is a pair of the form:

    (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
    )

In the case of MandatoryReleases that have not yet occurred,
MandatoryRelease predicts the release in which the feature will become a
permanent part of the language.

Else MandatoryRelease records when the feature became a permanent 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.

In releases before OptionalRelease, an import from __future__ of FeatureName
will raise an exception.

MandatoryRelease may also be None, meaning that a planned feature got
dropped.

No line is ever to be deleted from this file.
"""

nested_scopes = (2, 1, 0, "beta", 1), (2, 2, 0, "final", 0)
-----------------------------------------------------------------

While this is 100% intended to serve a documentation purpose, I also intend
to use it in my own code, like so (none of which is special to the compiler
except for the first line):

from __future__ import nested_scopes
import sys
assert sys.version_info < nested_scopes[1], "delete this section!"
# Note that the assert above also triggers if MandatoryRelease is None,
# i.e. if the feature got dropped (under 2.1 rules, None is smaller than
# anything else <wink>).
del sys, nested_scopes

Other rules:

# Legal only at module scope, before all non-comment occurrences of
# name, and only when name is known to the compiler.
from __future__ import name

# Ditto.  name2 has no special meaning.
from __future__ import name as name2

The purpose of the next two is to allow programmatic manipulation of the
info in __future__.py (generate help msgs, build a histogram of adoption
dates for incompatible changes by decade over the previous two centuries,
whatever).

# Legal anywhere, but no special meaning.
import __future__
import __future__ as name