# Path: paco/wraps.py
# def wraps(fn):
#     """
#     Wraps a given function as coroutine function.
# 
#     This function can be used as decorator.
# 
#     Arguments:
#         fn (function): function object to wrap.
# 
#     Returns:
#         coroutinefunction: wrapped function as coroutine.
# 
#     Usage::
# 
#         def mul_2(num):
#             return num * 2
# 
#         # Use as function wrapper
#         coro = paco.wraps(mul_2)
#         await coro(2)
#         # => 4
# 
#         # Use as decorator
#         @paco.wraps
#         def mul_2(num):
#             return num * 2
# 
#         await mul_2(2)
#         # => 4
# 
#     """
#     return asyncio.coroutine(fn)
# 
# Path: paco/assertions.py
# def isfunc(x):
#     """
#     Returns `True` if the given value is a function or method object.
# 
#     Arguments:
#         x (mixed): value to check.
# 
#     Returns:
#         bool
#     """
#     return any([
#         inspect.isfunction(x) and not asyncio.iscoroutinefunction(x),
#         inspect.ismethod(x) and not asyncio.iscoroutinefunction(x)
#     ])
# 
# def iscallable(x):
#     """
#     Returns `True` if the given value is a callable primitive object.
# 
#     Arguments:
#         x (mixed): value to check.
# 
#     Returns:
#         bool
#     """
#     return any([
#         isfunc(x),
#         asyncio.iscoroutinefunction(x)
#     ])


import inspect
import functools
from .wraps import wraps
from .assertions import isfunc, iscallable
        # Decrease function arity to satisfy
        arity -= current_arity

        # Use user-defined custom arity evaluator strategy, if present
        currify = evaluator and evaluator(acc, fn)

        # If arity is not satisfied, return recursive partial function
        if currify is not False and arity > 0:
            return functools.partial(currier, arity, (_args, _kw), fn)

        # If arity is satisfied, instanciate coroutine and return it
        return fn(*_args, **_kw)

    def wrapper(fn, *args, **kw):
        if not iscallable(fn):
            raise TypeError('paco: first argument must a coroutine function, '
                            'a function or a method.')

        # Infer function arity, if required
        arity = (arity_or_fn if isinstance(arity_or_fn, int)
                 else infer_arity(fn))

        # Wraps function as coroutine function, if needed.
        fn = wraps(fn) if isfunc(fn) else fn

        # Otherwise return recursive currier function
        return currier(arity, (args, kw), fn, *args, **kw) if arity > 0 else fn

    # Return currier function or decorator wrapper
    return (wrapper(arity_or_fn, *args, **kw)

# Path: paco/wraps.py
# def wraps(fn):
#     """
#     Wraps a given function as coroutine function.
# 
#     This function can be used as decorator.
# 
#     Arguments:
#         fn (function): function object to wrap.
# 
#     Returns:
#         coroutinefunction: wrapped function as coroutine.
# 
#     Usage::
# 
#         def mul_2(num):
#             return num * 2
# 
#         # Use as function wrapper
#         coro = paco.wraps(mul_2)
#         await coro(2)
#         # => 4
# 
#         # Use as decorator
#         @paco.wraps
#         def mul_2(num):
#             return num * 2
# 
#         await mul_2(2)
#         # => 4
# 
#     """
#     return asyncio.coroutine(fn)
# 
# Path: paco/assertions.py
# def isfunc(x):
#     """
#     Returns `True` if the given value is a function or method object.
# 
#     Arguments:
#         x (mixed): value to check.
# 
#     Returns:
#         bool
#     """
#     return any([
#         inspect.isfunction(x) and not asyncio.iscoroutinefunction(x),
#         inspect.ismethod(x) and not asyncio.iscoroutinefunction(x)
#     ])
# 
# def iscallable(x):
#     """
#     Returns `True` if the given value is a callable primitive object.
# 
#     Arguments:
#         x (mixed): value to check.
# 
#     Returns:
#         bool
#     """
#     return any([
#         isfunc(x),
#         asyncio.iscoroutinefunction(x)
#     ])


# Path: paco/curry.py
import inspect
import functools
from .wraps import wraps
from .assertions import isfunc, iscallable

        # Decrease function arity to satisfy
        arity -= current_arity

        # Use user-defined custom arity evaluator strategy, if present
        currify = evaluator and evaluator(acc, fn)

        # If arity is not satisfied, return recursive partial function
        if currify is not False and arity > 0:
            return functools.partial(currier, arity, (_args, _kw), fn)

        # If arity is satisfied, instanciate coroutine and return it
        return fn(*_args, **_kw)

    def wrapper(fn, *args, **kw):
        if not iscallable(fn):
            raise TypeError('paco: first argument must a coroutine function, '
                            'a function or a method.')

        # Infer function arity, if required
        arity = (arity_or_fn if isinstance(arity_or_fn, int)
                 else infer_arity(fn))

        # Wraps function as coroutine function, if needed.
        fn = wraps(fn) if isfunc(fn) else fn

        # Otherwise return recursive currier function
        return currier(arity, (args, kw), fn, *args, **kw) if arity > 0 else fn

    # Return currier function or decorator wrapper
    return (wrapper(arity_or_fn, *args, **kw)

            if iscallable(arity_or_fn)