mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 08:24:40 +01:00
have functor
This commit is contained in:
parent
67b6d2abe9
commit
037b9e002b
2 changed files with 104 additions and 7 deletions
|
@ -274,3 +274,67 @@ def test_functor_oneline_onecall_both():
|
|||
yield from block_checks_glb('f', glbs, body, {'x': 86})
|
||||
|
||||
|
||||
XA_WITH = ('x = [1]\n'
|
||||
'with Functor() as f:\n'
|
||||
'{body}'
|
||||
'x.append(2)\n'
|
||||
'{calls}\n'
|
||||
)
|
||||
|
||||
def test_functor_oneline_append():
|
||||
body = ' x.append(3)\n'
|
||||
calls = 'f()\n'
|
||||
s = XA_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': [1, 2, 3]})
|
||||
|
||||
|
||||
def test_functor_return():
|
||||
body = ' x = 42\n'
|
||||
t = ('res = 0\n'
|
||||
'with Functor(rtn="x") as f:\n'
|
||||
'{body}\n'
|
||||
'res = f()\n')
|
||||
s = t.format(body=body)
|
||||
glbs = {'Functor': Functor}
|
||||
check_exec(s, glbs=glbs, locs=None)
|
||||
yield from block_checks_glb('f', glbs, body, {'res': 42})
|
||||
|
||||
|
||||
def test_functor_args():
|
||||
body = ' x = 42 + a\n'
|
||||
t = ('res = 0\n'
|
||||
'with Functor(args=("a",), rtn="x") as f:\n'
|
||||
'{body}\n'
|
||||
'res = f(2)\n')
|
||||
s = t.format(body=body)
|
||||
glbs = {'Functor': Functor}
|
||||
check_exec(s, glbs=glbs, locs=None)
|
||||
yield from block_checks_glb('f', glbs, body, {'res': 44})
|
||||
|
||||
|
||||
def test_functor_kwargs():
|
||||
body = ' x = 42 + a + b\n'
|
||||
t = ('res = 0\n'
|
||||
'with Functor(kwargs={{"a": 1, "b": 12}}, rtn="x") as f:\n'
|
||||
'{body}\n'
|
||||
'res = f(b=6)\n')
|
||||
s = t.format(body=body)
|
||||
glbs = {'Functor': Functor}
|
||||
check_exec(s, glbs=glbs, locs=None)
|
||||
yield from block_checks_glb('f', glbs, body, {'res': 49})
|
||||
|
||||
|
||||
def test_functor_fullsig():
|
||||
body = ' x = 42 + a + b + c\n'
|
||||
t = ('res = 0\n'
|
||||
'with Functor(args=("c",), kwargs={{"a": 1, "b": 12}}, rtn="x") as f:\n'
|
||||
'{body}\n'
|
||||
'res = f(55)\n')
|
||||
s = t.format(body=body)
|
||||
glbs = {'Functor': Functor}
|
||||
check_exec(s, glbs=glbs, locs=None)
|
||||
yield from block_checks_glb('f', glbs, body, {'res': 110})
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Context management tools for xonsh."""
|
||||
import sys
|
||||
import builtins
|
||||
from collections.abc import Mapping
|
||||
|
||||
from xonsh.tools import XonshBlockError
|
||||
|
||||
|
@ -43,8 +44,17 @@ class Functor(Block):
|
|||
object, bound to the execution context it was created in.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, args=(), kwargs=None, rtn=''):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
args : Sequence of str, optional
|
||||
A tuple of argument names for the functor.
|
||||
kwargs : Mapping of str to values or list of item tuples, optional
|
||||
Keyword argument names and values, if available.
|
||||
rtn : str, optional
|
||||
Name of object to return, if available.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
func : function
|
||||
|
@ -53,6 +63,14 @@ class Functor(Block):
|
|||
"""
|
||||
super().__init__()
|
||||
self.func = None
|
||||
self.args = args
|
||||
if kwargs is None:
|
||||
self.kwargs = []
|
||||
elif isinstance(kwargs, Mapping):
|
||||
self.kwargs = sorted(kwargs.items())
|
||||
else:
|
||||
self.kwargs = kwargs
|
||||
self.rtn = rtn
|
||||
|
||||
def __enter__(self):
|
||||
super().__enter__()
|
||||
|
@ -60,14 +78,27 @@ class Functor(Block):
|
|||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
rtn = super().__exit__(exc_type, exc_value, traceback)
|
||||
if not rtn:
|
||||
return rtn
|
||||
res = super().__exit__(exc_type, exc_value, traceback)
|
||||
if not res:
|
||||
return res
|
||||
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)
|
||||
# construct signature string
|
||||
sig = rtn = ''
|
||||
sig = ', '.join(self.args)
|
||||
kwstr = ', '.join([k + '=None' for k, _ in self.kwargs])
|
||||
if len(kwstr) > 0:
|
||||
sig = kwstr if len(sig) == 0 else sig + ', ' + kwstr
|
||||
# construct return string
|
||||
rtn = str(self.rtn)
|
||||
if len(rtn) > 0:
|
||||
line0 = self.lines[0]
|
||||
ws = line0[:-len(line0.lstrip())]
|
||||
rtn = ws + 'return ' + rtn + '\n'
|
||||
# construct function string
|
||||
fstr = 'def {name}({sig}):\n{body}\n{rtn}'
|
||||
fstr = fstr.format(name=name, sig=sig, body=body, rtn=rtn)
|
||||
glbs = self.glbs
|
||||
locs = self.locs
|
||||
#locs = glbs if self.locs is None else self.locs
|
||||
|
@ -79,8 +110,10 @@ class Functor(Block):
|
|||
func = glbs[name]
|
||||
else:
|
||||
raise exc_value
|
||||
if len(self.kwargs) > 0:
|
||||
func.__defaults__ = tuple(v for _, v in self.kwargs)
|
||||
self.func = func
|
||||
return rtn
|
||||
return res
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
"""Dispatches to func."""
|
||||
|
|
Loading…
Add table
Reference in a new issue