suppress syntax warnings thrown by compile

This commit is contained in:
Anthony Scopatz 2016-06-05 20:01:26 -04:00
parent bb5c420446
commit 67b6d2abe9
3 changed files with 107 additions and 4 deletions

View file

@ -4,7 +4,7 @@ from nose.tools import assert_equal, assert_is, assert_is_not
from tools import (mock_xonsh_env, execer_setup, check_exec, check_eval, from tools import (mock_xonsh_env, execer_setup, check_exec, check_eval,
check_parse, skip_if) check_parse, skip_if)
from xonsh.contexts import Block from xonsh.contexts import Block, Functor
# #
# helpers # helpers
@ -61,7 +61,7 @@ def block_checks_func(name, glbs, body, obsg=None, obsl=None):
# #
# tests # Block tests
# #
def test_block_noexec(): def test_block_noexec():
@ -231,3 +231,46 @@ def test_block_func_trailing_triple_string():
glbs = {'Block': Block} glbs = {'Block': Block}
check_exec(s, glbs=glbs, locs=None) check_exec(s, glbs=glbs, locs=None)
yield from block_checks_func('rtn', glbs, body, FUNC_OBSG, FUNC_OBSL) yield from block_checks_func('rtn', glbs, body, FUNC_OBSG, FUNC_OBSL)
#
# Functor tests
#
X2_WITH = ('x = 1\n'
'with Functor() as f:\n'
'{body}'
'x += 1\n'
'{calls}\n'
)
def test_functor_oneline_onecall_class():
body = (' global x\n'
' x += 42\n')
calls = 'f()'
s = X2_WITH.format(body=body, calls=calls)
glbs = {'Functor': Functor}
check_exec(s, glbs=glbs, locs=None)
yield from block_checks_glb('f', glbs, body, {'x': 44})
def test_functor_oneline_onecall_func():
body = (' global x\n'
' x += 42\n')
calls = 'f.func()'
s = X2_WITH.format(body=body, calls=calls)
glbs = {'Functor': Functor}
check_exec(s, glbs=glbs, locs=None)
yield from block_checks_glb('f', glbs, body, {'x': 44})
def test_functor_oneline_onecall_both():
body = (' global x\n'
' x += 42\n')
calls = 'f()\nf.func()'
s = X2_WITH.format(body=body, calls=calls)
glbs = {'Functor': Functor}
check_exec(s, glbs=glbs, locs=None)
yield from block_checks_glb('f', glbs, body, {'x': 86})

View file

@ -1,4 +1,5 @@
"""Context management tools for xonsh.""" """Context management tools for xonsh."""
import sys
import builtins import builtins
from xonsh.tools import XonshBlockError from xonsh.tools import XonshBlockError
@ -9,7 +10,7 @@ class Block(object):
""" """
__xonsh_block__ = True __xonsh_block__ = True
def __init__(self, lines=None): def __init__(self):
""" """
Attributes Attributes
---------- ----------
@ -35,3 +36,55 @@ class Block(object):
# leave locals as None when it is the same as globals # leave locals as None when it is the same as globals
self.locs = exc_value.locs self.locs = exc_value.locs
return True return True
class Functor(Block):
"""This is a context manager that turns the block into a callable
object, bound to the execution context it was created in.
"""
def __init__(self):
"""
Attributes
----------
func : function
The underlying function object. This defaults to none and is set
after the the block is exited.
"""
super().__init__()
self.func = None
def __enter__(self):
super().__enter__()
self.func = None
return self
def __exit__(self, exc_type, exc_value, traceback):
rtn = super().__exit__(exc_type, exc_value, traceback)
if not rtn:
return rtn
body = '\n'.join(self.lines)
uid = hash(body) + sys.maxsize # should always be a positive int
name = '__xonsh_functor_{uid}__'.format(uid=uid)
fstr = 'def {name}():\n{body}\n'
fstr = fstr.format(name=name, body=body)
glbs = self.glbs
locs = self.locs
#locs = glbs if self.locs is None else self.locs
execer = builtins.__xonsh_execer__
execer.exec(fstr, glbs=glbs, locs=locs)
if locs is not None and name in locs:
func = locs[name]
elif name in glbs:
func = glbs[name]
else:
raise exc_value
self.func = func
return rtn
def __call__(self, *args, **kwargs):
"""Dispatches to func."""
if self.func is None:
msg = "{} block with 'None' func not callable"
raise AttributeError(msg.formst(self.__class__.__name__))
return self.func(*args, **kwargs)

View file

@ -5,6 +5,7 @@ import sys
import types import types
import inspect import inspect
import builtins import builtins
import warnings
from collections import Mapping from collections import Mapping
from xonsh import ast from xonsh import ast
@ -100,7 +101,13 @@ class Execer(object):
tree = self.parse(input, ctx, mode=mode, transform=transform) tree = self.parse(input, ctx, mode=mode, transform=transform)
if tree is None: if tree is None:
return None # handles comment only input return None # handles comment only input
code = compile(tree, filename, mode) if transform:
with warnings.catch_warnings():
# we do some funky things with blocks that cause warnings
warnings.simplefilter('ignore', SyntaxWarning)
code = compile(tree, filename, mode)
else:
code = compile(tree, filename, mode)
return code return code
def eval(self, input, glbs=None, locs=None, stacklevel=2, def eval(self, input, glbs=None, locs=None, stacklevel=2,