Skip to content

Loading…

Parse user code to AST using compiler flags. #784

Merged
merged 2 commits into from

2 participants

@takluyver
IPython member

Closes gh-777.

@fperez fperez commented on an outdated diff
IPython/core/compilerop.py
@@ -77,6 +78,16 @@ class CachingCompiler(codeop.Compile):
# stdlib that call it outside our control go through our codepath
# (otherwise we'd lose our tracebacks).
linecache.checkcache = self.check_cache
+
+ def ast_parse(self, source, filename='<unknown>', symbol='exec'):
+ """Parse code to an AST with the current compiler flags active."""
@fperez IPython member
fperez added a note

Indicate in the docstring that all arguments are the same as those passed to the builtin compile() call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@fperez
IPython member

Other than my tiny inline comment, this looks perfect. Once that's fixed, go ahead and merge. Thanks!

@takluyver takluyver merged commit ca3e756 into ipython:master
@takluyver
IPython member

Rebased and merged. Thanks, Fernando.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Showing with 26 additions and 1 deletion.
  1. +14 −0 IPython/core/compilerop.py
  2. +1 −1 IPython/core/interactiveshell.py
  3. +11 −0 IPython/core/tests/test_interactiveshell.py
View
14 IPython/core/compilerop.py
@@ -28,6 +28,7 @@
from __future__ import print_function
# Stdlib imports
+from ast import PyCF_ONLY_AST
import codeop
import hashlib
import linecache
@@ -77,6 +78,19 @@ def __init__(self):
# stdlib that call it outside our control go through our codepath
# (otherwise we'd lose our tracebacks).
linecache.checkcache = self.check_cache
+
+ def ast_parse(self, source, filename='<unknown>', symbol='exec'):
+ """Parse code to an AST with the current compiler flags active.
+
+ Arguments are exactly the same as ast.parse (in the standard library),
+ and are passed to the built-in compile function."""
+ return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
+
+ def reset_compiler_flags(self):
+ """Reset compiler flags to default state."""
+ # This value is copied from codeop.Compile.__init__, so if that ever
+ # changes, it will need to be updated.
+ self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
@property
def compiler_flags(self):
View
2 IPython/core/interactiveshell.py
@@ -2281,7 +2281,7 @@ def run_cell(self, raw_cell, store_history=True):
with self.display_trap:
try:
- code_ast = ast.parse(cell, filename=cell_name)
+ code_ast = self.compile.ast_parse(cell, filename=cell_name)
except IndentationError:
self.showindentationerror()
self.execution_count += 1
View
11 IPython/core/tests/test_interactiveshell.py
@@ -122,3 +122,14 @@ def __repr__(self):
import IPython.core.formatters
f = IPython.core.formatters.PlainTextFormatter()
f([Spam(),Spam()])
+
+ def test_future_flags(self):
+ """Check that future flags are used for parsing code (gh-777)"""
+ ip = get_ipython()
+ ip.run_cell('from __future__ import print_function')
+ try:
+ ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
+ assert 'prfunc_return_val' in ip.user_ns
+ finally:
+ # Reset compiler flags so we don't mess up other tests.
+ ip.compile.reset_compiler_flags()
Something went wrong with that request. Please try again.