Issue 23069: IDLE's F5 Run Module doesn't transfer effects of future import (original) (raw)
Future imports in a module aren't transferring to the interactive shell when executing Run Module.
Given the file tmp_future.py
$ cat tmp_future.py from future import division, print_function
print(32 / 5)
Run Python interactively
$ python2.7 -i tmp_future.py 6.4
32 / 5 # this works fine! 6.4
But open the file in IDLE and press F5:
Python 2.7.9 (v2.7.9:648dcafa7e5f, Dec 10 2014, 10:10:46) [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin Type "copyright", "credits" or "license()" for more information.
================================ RESTART ================================
6.4
print(32 / 5) # this is broken! 6
Note, the problem may also apply to IDLE Python 3.4 and 3.5 but it won't affect this example because the future imports have not effect.
I agree that this is broken. I verified that the following works in 2.7.9
from future import division, print_function 32 / 5 6.4 print(2,3,sep='') 23
#13296 was about self.compile.compiler.flags (in ModifiedInterpreter, which inherits .compile... from code.InteractiveInterpreter) not being reset to their original values upon Shell restart. They are now.
This issue is about the same flags not being set by Run Module. This will be tricky to fix, but I think it can be done using the previous flag issue as a hint.
self.compile (in InteractiveInterpreter) = codeop.CommandCompiler(). The docstring for the class says """Instances of this class have call methods identical in signature to compile_command; the difference is that if the instance compiles program text containing a future statement, the instance 'remembers' and compiles all subsequent program texts with the statement in force.""" The call method handles partial or complete single statements.
Run -> Run Module F5, on the other hand, is handled by the ScriptBindind.py extension. ScriptBinding.run_module_event calls .checksyntax(). The latter calls builtin compile(), independent of the shell interpreter.compile, without saving the compile flags.
To save the compile flags, we could use codeop.Compile.call, which calls builtin compile() and then extracts and saves future compile flags from the resulting code object using constants defined in the module.
The next issue is timing. The shell restarts (and resets its flags) only after the file passes compile and tabnanny steps. After the restart, it should be possible to update the shell compile flags with any future flags saved by the Compile() instance.
I have skipped over some details (including the lack of tests for Run Module), but I think that the above outlines a safe solution. As for 3.x, there are changes in 3.4 ScriptBinding.py, but the essential points for this issue seem the same. 3.x should be patched also to be ready for future future imports.