# 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
        """
        Function either continues curring of the arguments
        or executes function if desired arguments have being collected.
        If function curried is variadic then execution without arguments
        will finish curring and trigger the function
        """
        # Merge call arguments with accumulated ones
        _args, _kw = merge_args(acc, args, kw)

        # Get current function call accumulated arity
        current_arity = len(args)

        # Count keyword params as arity to satisfy, if required
        if not ignore_kwargs:
            current_arity += len(kw)

        # 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):

# 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

        """
        Function either continues curring of the arguments
        or executes function if desired arguments have being collected.
        If function curried is variadic then execution without arguments
        will finish curring and trigger the function
        """
        # Merge call arguments with accumulated ones
        _args, _kw = merge_args(acc, args, kw)

        # Get current function call accumulated arity
        current_arity = len(args)

        # Count keyword params as arity to satisfy, if required
        if not ignore_kwargs:
            current_arity += len(kw)

        # 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):