Author: Armin Rigo <[email protected]>
Branch:
Changeset: r84808:ca9508369e5a
Date: 2016-05-29 16:23 +0200
http://bitbucket.org/pypy/pypy/changeset/ca9508369e5a/
Log: Issue #2311: grab the __future__ flags imported in the main script,
in '-c', or in PYTHON_STARTUP, and expose them to the '-i' console
we get afterwards
diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py
--- a/lib_pypy/_pypy_interact.py
+++ b/lib_pypy/_pypy_interact.py
@@ -6,7 +6,7 @@
irc_header = "And now for something completely different"
-def interactive_console(mainmodule=None, quiet=False):
+def interactive_console(mainmodule=None, quiet=False, future_flags=0):
# set sys.{ps1,ps2} just before invoking the interactive interpreter. This
# mimics what CPython does in pythonrun.c
if not hasattr(sys, 'ps1'):
@@ -37,15 +37,17 @@
raise ImportError
from pyrepl.simple_interact import run_multiline_interactive_console
except ImportError:
- run_simple_interactive_console(mainmodule)
+ run_simple_interactive_console(mainmodule, future_flags=future_flags)
else:
- run_multiline_interactive_console(mainmodule)
+ run_multiline_interactive_console(mainmodule,
future_flags=future_flags)
-def run_simple_interactive_console(mainmodule):
+def run_simple_interactive_console(mainmodule, future_flags=0):
import code
if mainmodule is None:
import __main__ as mainmodule
console = code.InteractiveConsole(mainmodule.__dict__, filename='<stdin>')
+ if future_flags:
+ console.compile.compiler.flags |= future_flags
# some parts of code.py are copied here because it seems to be impossible
# to start an interactive console without printing at least one line
# of banner
diff --git a/lib_pypy/pyrepl/simple_interact.py
b/lib_pypy/pyrepl/simple_interact.py
--- a/lib_pypy/pyrepl/simple_interact.py
+++ b/lib_pypy/pyrepl/simple_interact.py
@@ -43,11 +43,13 @@
return short
return text
-def run_multiline_interactive_console(mainmodule=None):
+def run_multiline_interactive_console(mainmodule=None, future_flags=0):
import code
if mainmodule is None:
import __main__ as mainmodule
console = code.InteractiveConsole(mainmodule.__dict__, filename='<stdin>')
+ if future_flags:
+ console.compile.compiler.flags |= future_flags
def more_lines(unicodetext):
# ooh, look at the hack:
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -603,6 +603,11 @@
((inspect or (readenv and real_getenv('PYTHONINSPECT')))
and sys.stdin.isatty()))
+ try:
+ from _ast import PyCF_ACCEPT_NULL_BYTES
+ except ImportError:
+ PyCF_ACCEPT_NULL_BYTES = 0
+ future_flags = [0]
success = True
try:
@@ -613,7 +618,9 @@
@hidden_applevel
def run_it():
- exec run_command in mainmodule.__dict__
+ co_cmd = compile(run_command, '<module>', 'exec')
+ exec co_cmd in mainmodule.__dict__
+ future_flags[0] = co_cmd.co_flags
success = run_toplevel(run_it)
elif run_module:
# handle the "-m" command
@@ -625,11 +632,6 @@
# handle the case where no command/filename/module is specified
# on the command-line.
- try:
- from _ast import PyCF_ACCEPT_NULL_BYTES
- except ImportError:
- PyCF_ACCEPT_NULL_BYTES = 0
-
# update sys.path *after* loading site.py, in case there is a
# "site.py" file in the script's directory. Only run this if we're
# executing the interactive prompt, if we're running a script we
@@ -656,6 +658,7 @@
'exec',
PyCF_ACCEPT_NULL_BYTES)
exec co_python_startup in mainmodule.__dict__
+ future_flags[0] = co_python_startup.co_flags
mainmodule.__file__ = python_startup
run_toplevel(run_it)
try:
@@ -673,6 +676,7 @@
co_stdin = compile(sys.stdin.read(), '<stdin>', 'exec',
PyCF_ACCEPT_NULL_BYTES)
exec co_stdin in mainmodule.__dict__
+ future_flags[0] = co_stdin.co_flags
mainmodule.__file__ = '<stdin>'
success = run_toplevel(run_it)
else:
@@ -702,7 +706,20 @@
args = (runpy._run_module_as_main, '__main__', False)
else:
# no. That's the normal path, "pypy stuff.py".
- args = (execfile, filename, mainmodule.__dict__)
+ # This includes the logic from execfile(), tweaked
+ # to grab the future_flags at the end.
+ @hidden_applevel
+ def run_it():
+ f = file(filename, 'rU')
+ try:
+ source = f.read()
+ finally:
+ f.close()
+ co_main = compile(source.rstrip()+"\n", filename,
+ 'exec', PyCF_ACCEPT_NULL_BYTES)
+ exec co_main in mainmodule.__dict__
+ future_flags[0] = co_main.co_flags
+ args = (run_it,)
success = run_toplevel(*args)
except SystemExit as e:
@@ -715,12 +732,20 @@
# start a prompt if requested
if inspect_requested():
try:
+ import __future__
from _pypy_interact import interactive_console
pypy_version_info = getattr(sys, 'pypy_version_info',
sys.version_info)
irc_topic = pypy_version_info[3] != 'final' or (
readenv and os.getenv('PYPY_IRC_TOPIC'))
+ flags = 0
+ for fname in __future__.all_feature_names:
+ if future_flags[0] & getattr(__future__, fname).compiler_flag:
+ flags |= feature.compiler_flag
+ kwds = {}
+ if flags:
+ kwds['future_flags'] = flags
success = run_toplevel(interactive_console, mainmodule,
- quiet=not irc_topic)
+ quiet=not irc_topic, **kwds)
except SystemExit as e:
status = e.code
else:
diff --git a/pypy/interpreter/test/test_app_main.py
b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -76,6 +76,11 @@
print 'Goodbye2' # should not be reached
""")
+script_with_future = getscript("""
+ from __future__ import division
+ from __future__ import print_function
+ """)
+
class TestParseCommandLine:
def check_options(self, options, sys_argv, **expected):
@@ -445,6 +450,31 @@
finally:
os.environ['PYTHONSTARTUP'] = old
+ def test_future_in_executed_script(self):
+ child = self.spawn(['-i', script_with_future])
+ child.expect('>>> ')
+ child.sendline('x=1; print(x/2, 3/4)')
+ child.expect('0.5 0.75')
+
+ def test_future_in_python_startup(self, monkeypatch):
+ monkeypatch.setenv('PYTHONSTARTUP', script_with_future)
+ child = self.spawn([])
+ child.expect('>>> ')
+ child.sendline('x=1; print(x/2, 3/4)')
+ child.expect('0.5 0.75')
+
+ def test_future_in_cmd(self):
+ child = self.spawn(['-i', '-c', 'from __future__ import division'])
+ child.expect('>>> ')
+ child.sendline('x=1; x/2; 3/4')
+ child.expect('0.5')
+ child.expect('0.75')
+
+ def test_cmd_co_name(self):
+ child = self.spawn(['-c',
+ 'import sys; print sys._getframe(0).f_code.co_name'])
+ child.expect('<module>')
+
def test_ignore_python_inspect(self):
os.environ['PYTHONINSPECT_'] = '1'
try:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit