modify execer to allow skipping the part about wrapping with ![]

This commit is contained in:
adam j hartz 2016-05-31 23:50:30 -04:00
parent 5722114623
commit 2b06eee116
2 changed files with 24 additions and 12 deletions

View file

@ -92,7 +92,7 @@ class CtxAwareTransformer(NodeTransformer):
a subprocess.
"""
def __init__(self, parser):
def __init__(self, parser, wrap_subprocs=True):
"""Parameters
----------
parser : xonsh.Parser
@ -104,8 +104,9 @@ class CtxAwareTransformer(NodeTransformer):
self.contexts = []
self.lines = None
self.mode = None
self.wrap_subprocs = wrap_subprocs
def ctxvisit(self, node, inp, ctx, mode='exec'):
def ctxvisit(self, node, inp, ctx, mode='exec', wrap_subprocs=True):
"""Transforms the node in a context-dependent way.
Parameters
@ -122,6 +123,7 @@ class CtxAwareTransformer(NodeTransformer):
node : ast.AST
The transformed node.
"""
self.wrap_subprocs = wrap_subprocs
self.lines = inp.splitlines()
self.contexts = [ctx, set()]
self.mode = mode
@ -146,6 +148,8 @@ class CtxAwareTransformer(NodeTransformer):
def try_subproc_toks(self, node, strip_expr=False):
"""Tries to parse the line of the node as a subprocess."""
if not self.wrap_subprocs:
return node
line = self.lines[node.lineno - 1]
if self.mode == 'eval':
mincol = len(line) - len(line.lstrip())

View file

@ -45,7 +45,7 @@ class Execer(object):
if self.unload:
unload_builtins()
def parse(self, input, ctx, mode='exec'):
def parse(self, input, ctx, mode='exec', wrap_subprocs=True):
"""Parses xonsh code in a context-aware fashion. For context-free
parsing, please use the Parser class directly.
"""
@ -68,7 +68,8 @@ class Execer(object):
# tokens for all of the Python rules. The lazy way implemented here
# is to parse a line a second time with a $() wrapper if it fails
# the first time. This is a context-free phase.
tree, input = self._parse_ctx_free(input, mode=mode)
tree, input = self._parse_ctx_free(input, mode=mode,
wrap_subprocs=wrap_subprocs)
if tree is None:
return None
@ -78,11 +79,12 @@ class Execer(object):
# (ls) is part of the execution context. If it isn't, then we will
# assume that this line is supposed to be a subprocess line, assuming
# it also is valid as a subprocess line.
tree = self.ctxtransformer.ctxvisit(tree, input, ctx, mode=mode)
tree = self.ctxtransformer.ctxvisit(tree, input, ctx, mode=mode,
wrap_subprocs=wrap_subprocs)
return tree
def compile(self, input, mode='exec', glbs=None, locs=None, stacklevel=2,
filename=None):
filename=None, wrap_subprocs=True):
"""Compiles xonsh code into a Python code object, which may then
be execed or evaled.
"""
@ -93,13 +95,14 @@ class Execer(object):
glbs = frame.f_globals if glbs is None else glbs
locs = frame.f_locals if locs is None else locs
ctx = set(dir(builtins)) | set(glbs.keys()) | set(locs.keys())
tree = self.parse(input, ctx, mode=mode)
tree = self.parse(input, ctx, mode=mode, wrap_subprocs=wrap_subprocs)
if tree is None:
return None # handles comment only input
code = compile(tree, filename, mode)
return code
def eval(self, input, glbs=None, locs=None, stacklevel=2):
def eval(self, input, glbs=None, locs=None, stacklevel=2,
wrap_subprocs=True):
"""Evaluates (and returns) xonsh code."""
if isinstance(input, types.CodeType):
code = input
@ -108,12 +111,14 @@ class Execer(object):
glbs=glbs,
locs=locs,
mode='eval',
stacklevel=stacklevel)
stacklevel=stacklevel,
wrap_subprocs=wrap_subprocs)
if code is None:
return None # handles comment only input
return eval(code, glbs, locs)
def exec(self, input, mode='exec', glbs=None, locs=None, stacklevel=2):
def exec(self, input, mode='exec', glbs=None, locs=None, stacklevel=2,
wrap_subprocs=True):
"""Execute xonsh code."""
if isinstance(input, types.CodeType):
code = input
@ -122,12 +127,13 @@ class Execer(object):
glbs=glbs,
locs=locs,
mode=mode,
stacklevel=stacklevel)
stacklevel=stacklevel,
wrap_subprocs=wrap_subprocs)
if code is None:
return None # handles comment only input
return exec(code, glbs, locs)
def _parse_ctx_free(self, input, mode='exec'):
def _parse_ctx_free(self, input, mode='exec', wrap_subprocs=True):
last_error_line = last_error_col = -1
parsed = False
original_error = None
@ -144,6 +150,8 @@ class Execer(object):
else:
raise original_error
except SyntaxError as e:
if not wrap_subprocs:
raise e
if original_error is None:
original_error = e
if (e.loc is None) or (last_error_line == e.loc.lineno and