Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Parse user code to AST using compiler flags. #784

Merged
merged 2 commits into from

2 participants

@takluyver
Owner

Closes gh-777.

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 Owner
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
Owner

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

@takluyver takluyver merged commit ca3e756 into from
@takluyver
Owner

Rebased and merged. Thanks, Fernando.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
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.