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,
check_parse, skip_if)
from xonsh.contexts import Block
from xonsh.contexts import Block, Functor
#
# helpers
@ -61,7 +61,7 @@ def block_checks_func(name, glbs, body, obsg=None, obsl=None):
#
# tests
# Block tests
#
def test_block_noexec():
@ -231,3 +231,46 @@ def test_block_func_trailing_triple_string():
glbs = {'Block': Block}
check_exec(s, glbs=glbs, locs=None)
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."""
import sys
import builtins
from xonsh.tools import XonshBlockError
@ -9,7 +10,7 @@ class Block(object):
"""
__xonsh_block__ = True
def __init__(self, lines=None):
def __init__(self):
"""
Attributes
----------
@ -35,3 +36,55 @@ class Block(object):
# leave locals as None when it is the same as globals
self.locs = exc_value.locs
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 inspect
import builtins
import warnings
from collections import Mapping
from xonsh import ast
@ -100,6 +101,12 @@ class Execer(object):
tree = self.parse(input, ctx, mode=mode, transform=transform)
if tree is None:
return None # handles comment only input
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