[Python-ideas] Making it easy to prepare for PEP479

Chris Angelico rosuav at gmail.com
Mon May 18 18:45:19 CEST 2015


On Tue, May 19, 2015 at 2:18 AM, Steven D'Aprano <steve at pearwood.info> wrote:
>> The way to make this work would be two-fold. Firstly, an incorrect
>> __future__ directive would have to no longer be a SyntaxError; and
>> secondly, __future__ directives would have to be permitted after a try
>> statement (currently, they're not allowed to follow anything, so the
>> 'try' would have to be special-cased to be allowed in).
>
> It's not enough to merely change the wording of the error from
> SyntaxError to something else. You have to change when it occurs: it can
> no longer be raised at compile time, but has to happen at run time. That
> means that __future__ imports have to have compile to something which
> runs at run time, instead of just being a directive to the compiler.

Precisely. I'm not saying that the incorrect future directive would be
some other sort of error instead of SyntaxError - for this to be
possible, it would have to *not be an error at all* at compile time,
leaving the faulty directive unannounced until it gets to the second
step (actual run-time importing of the __future__ module) to catch
errors. (Hence the side effect that "from __future__ import
all_feature_names" would actually not be an error; to the compiler,
it's an unknown future directive and thus ignored, and to the
run-time, it's a perfectly valid way to grab the list of features.)

> As for the changes necessary to the compiler, I have no idea how
> extensive they would be, but my guess is "extremely".

Actually, not much. Since it's just the nerfing of one error, it can
be done fairly easily - as proof of concept, I just commented out
lines 50 through 54 of future.c (the "else" block that raises an
error) and compiled:

rosuav at sikorsky:~/cpython$ cat futuredemo.py
from __future__ import generator_stop
from __future__ import all_feature_names
from __future__ import oops
rosuav at sikorsky:~/cpython$ ./python futuredemo.py
Traceback (most recent call last):
  File "futuredemo.py", line 3, in <module>
    from __future__ import oops
ImportError: cannot import name 'oops'

> Also, consider that once you are allowing __future__ directives to occur
> after a try statement, expect there to be a lot more pressure to allow
> it after any arbitrary code. After all, I might want to write:
>
> if sys.version != '3.7' and read_config('config.ini')['allow_jabberwocky']:
>     from __future__ import jabberwocky
>
> so you're opening the doors to a LOT more complexity.

Yes, now that is a much bigger concern. I did say that the "try:" part
of a try block would have to be deemed not-code, as a special case.
Simply nerfing that error (in compile.c and future.c) does make for a
viable proof-of-concept, though, so it's still nothing that requires
extensive changes to the compiler.  However...

> Which, as far as I am concerned, is a good thing, because it makes the
> chances of this actually happening to be somewhere between Buckley's and
> none *wink*

... this I agree with. I don't think the feature is all that useful,
and while it might well not be all that hard to implement, it would
complicate things somewhat, and that's not good. (It also may end up
being quite hard, and more so depending on the complexity of the
definition of what's allowed prior to a __future__ directive.) I can
imagine, for instance, a special case given to this precise structure:

try: from __future__ import feature
except: pass

which would then be an "optional future import"; but again, how often
is it even useful, much less necessary?

ChrisA


More information about the Python-ideas mailing list