from .util import subvals
def unary_to_nary(unary_operator):
@wraps(unary_operator)
def nary_operator(fun, argnum=0, *nary_op_args, **nary_op_kwargs):
assert type(argnum) in (int, tuple, list), argnum
@wrap_nary_f(fun, unary_operator, argnum)
def nary_f(*args, **kwargs):
@wraps(fun)
def unary_f(x):
if isinstance(argnum, int):
subargs = subvals(args, [(argnum, x)])
else:
subargs = subvals(args, zip(argnum, x))
return fun(*subargs, **kwargs)
if isinstance(argnum, int):
x = args[argnum]
else:
x = tuple(args[i] for i in argnum)
return unary_operator(unary_f, x, *nary_op_args, **nary_op_kwargs)
return nary_f
return nary_operator
def wraps(fun, namestr="{fun}", docstr="{doc}", **kwargs):
def _wraps(f):
try:
f.__name__ = namestr.format(fun=get_name(fun), **kwargs)
f.__doc__ = docstr.format(fun=get_name(fun), doc=get_doc(fun), **kwargs)
finally:
return f
return _wraps
def wrap_nary_f(fun, op, argnum):
namestr = "{op}_of_{fun}_wrt_argnum_{argnum}"
docstr = """\
{op} of function {fun} with respect to argument number {argnum}. Takes the
same arguments as {fun} but returns the {op}.
"""
return wraps(fun, namestr, docstr, op=get_name(op), argnum=argnum)
get_name = lambda f: getattr(f, '__name__', '[unknown name]')
get_doc = lambda f: getattr(f, '__doc__' , '')