# Path: paco/assertions.py
# def isiter(x):
#     """
#     Returns `True` if the given value implements an valid iterable
#     interface.
# 
#     Arguments:
#         x (mixed): value to check if it is an iterable.
# 
#     Returns:
#         bool
#     """
#     return hasattr(x, '__iter__') and not isinstance(x, (str, bytes))
# 
# Path: paco/reduce.py
# @overload
# @asyncio.coroutine
# def reduce(coro, iterable, initializer=None, limit=1, right=False, loop=None):
#     """
#     Apply function of two arguments cumulatively to the items of sequence,
#     from left to right, so as to reduce the sequence to a single value.
# 
#     Reduction will be executed sequentially without concurrency,
#     so passed values would be in order.
# 
#     This function is the asynchronous coroutine equivalent to Python standard
#     `functools.reduce()` function.
# 
#     This function is a coroutine.
# 
#     This function can be composed in a pipeline chain with ``|`` operator.
# 
#     Arguments:
#         coro (coroutine function): reducer coroutine binary function.
#         iterable (iterable|asynchronousiterable): an iterable collection
#             yielding coroutines functions.
#         initializer (mixed): initial accumulator value used in
#             the first reduction call.
#         limit (int): max iteration concurrency limit. Use ``0`` for no limit.
#         right (bool): reduce iterable from right to left.
#         loop (asyncio.BaseEventLoop): optional event loop to use.
# 
#     Raises:
#         TypeError: if input arguments are not valid.
# 
#     Returns:
#         mixed: accumulated final reduced value.
# 
#     Usage::
# 
#         async def reducer(acc, num):
#            return acc + num
# 
#         await paco.reduce(reducer, [1, 2, 3, 4, 5], initializer=0)
#         # => 15
# 
#     """
#     assert_corofunction(coro=coro)
#     assert_iter(iterable=iterable)
# 
#     # Reduced accumulator value
#     acc = initializer
# 
#     # If interable is empty, just return the initializer value
#     if len(iterable) == 0:
#         return initializer
# 
#     # Create concurrent executor
#     pool = ConcurrentExecutor(limit=limit, loop=loop)
# 
#     # Reducer partial function for deferred coroutine execution
#     def reducer(element):
#         @asyncio.coroutine
#         def wrapper():
#             nonlocal acc
#             acc = yield from coro(acc, element)
#         return wrapper
# 
#     # Support right reduction
#     if right:
#         iterable.reverse()
# 
#     # Iterate and attach coroutine for defer scheduling
#     for element in iterable:
#         pool.add(reducer(element))
# 
#     # Wait until all coroutines finish
#     yield from pool.run(ignore_empty=True)
# 
#     # Returns final reduced value
#     return acc
# 
# Path: paco/decorator.py
# def generator_consumer(coro):  # pragma: no cover
#     def wrapper(*args, **kw):
# def decorate(fn):
#     def decorator(*args, **kw):
#         def wrapper(coro, *_args, **_kw):
# 
# Path: paco/assertions.py
# def assert_corofunction(**kw):
#     """
#     Asserts if a given values are a coroutine function.
# 
#     Arguments:
#         **kw (mixed): value to check if it is an iterable.
# 
#     Raises:
#         TypeError: if assertion fails.
#     """
#     for name, value in kw.items():
#         if not asyncio.iscoroutinefunction(value):
#             raise TypeError(
#                 'paco: {} must be a coroutine function'.format(name))
# 
# def assert_iter(**kw):
#     """
#     Asserts if a given values implements a valid iterable interface.
# 
#     Arguments:
#         **kw (mixed): value to check if it is an iterable.
# 
#     Raises:
#         TypeError: if assertion fails.
#     """
#     for name, value in kw.items():
#         if not isiter(value):
#             raise TypeError(
#                 'paco: {} must be an iterable object'.format(name))


import asyncio
from .assertions import isiter
from .reduce import reduce
from .decorator import overload
from .assertions import assert_corofunction, assert_iter
        loop (asyncio.BaseEventLoop): optional event loop to use.
        return_exceptions (bool): enable/disable returning exceptions in case
            of error. `collect` param must be True.
        timeout (int|float): timeout can be used to control the maximum number
            of seconds to wait before returning. timeout can be an int or
            float. If timeout is not specified or None, there is no limit to
            the wait time.
        *args (mixed): optional variadic arguments to pass to the
            coroutine iterable function.

    Returns:
        results (list): ordered list of values yielded by coroutines

    Raises:
        TypeError: in case of invalid input arguments.

    Usage::

        async def mul_2(num):
            return num * 2

        await paco.flat_map(mul_2, [1, [2], [3, [4]], [(5,)]])
        # => [2, 4, 6, 8, 10]

        # Pipeline style
        await [1, [2], [3, [4]], [(5,)]] | paco.flat_map(mul_2)
        # => [2, 4, 6, 8, 10]

    """
    assert_corofunction(coro=coro)

# Path: paco/assertions.py
# def isiter(x):
#     """
#     Returns `True` if the given value implements an valid iterable
#     interface.
# 
#     Arguments:
#         x (mixed): value to check if it is an iterable.
# 
#     Returns:
#         bool
#     """
#     return hasattr(x, '__iter__') and not isinstance(x, (str, bytes))
# 
# Path: paco/reduce.py
# @overload
# @asyncio.coroutine
# def reduce(coro, iterable, initializer=None, limit=1, right=False, loop=None):
#     """
#     Apply function of two arguments cumulatively to the items of sequence,
#     from left to right, so as to reduce the sequence to a single value.
# 
#     Reduction will be executed sequentially without concurrency,
#     so passed values would be in order.
# 
#     This function is the asynchronous coroutine equivalent to Python standard
#     `functools.reduce()` function.
# 
#     This function is a coroutine.
# 
#     This function can be composed in a pipeline chain with ``|`` operator.
# 
#     Arguments:
#         coro (coroutine function): reducer coroutine binary function.
#         iterable (iterable|asynchronousiterable): an iterable collection
#             yielding coroutines functions.
#         initializer (mixed): initial accumulator value used in
#             the first reduction call.
#         limit (int): max iteration concurrency limit. Use ``0`` for no limit.
#         right (bool): reduce iterable from right to left.
#         loop (asyncio.BaseEventLoop): optional event loop to use.
# 
#     Raises:
#         TypeError: if input arguments are not valid.
# 
#     Returns:
#         mixed: accumulated final reduced value.
# 
#     Usage::
# 
#         async def reducer(acc, num):
#            return acc + num
# 
#         await paco.reduce(reducer, [1, 2, 3, 4, 5], initializer=0)
#         # => 15
# 
#     """
#     assert_corofunction(coro=coro)
#     assert_iter(iterable=iterable)
# 
#     # Reduced accumulator value
#     acc = initializer
# 
#     # If interable is empty, just return the initializer value
#     if len(iterable) == 0:
#         return initializer
# 
#     # Create concurrent executor
#     pool = ConcurrentExecutor(limit=limit, loop=loop)
# 
#     # Reducer partial function for deferred coroutine execution
#     def reducer(element):
#         @asyncio.coroutine
#         def wrapper():
#             nonlocal acc
#             acc = yield from coro(acc, element)
#         return wrapper
# 
#     # Support right reduction
#     if right:
#         iterable.reverse()
# 
#     # Iterate and attach coroutine for defer scheduling
#     for element in iterable:
#         pool.add(reducer(element))
# 
#     # Wait until all coroutines finish
#     yield from pool.run(ignore_empty=True)
# 
#     # Returns final reduced value
#     return acc
# 
# Path: paco/decorator.py
# def generator_consumer(coro):  # pragma: no cover
#     def wrapper(*args, **kw):
# def decorate(fn):
#     def decorator(*args, **kw):
#         def wrapper(coro, *_args, **_kw):
# 
# Path: paco/assertions.py
# def assert_corofunction(**kw):
#     """
#     Asserts if a given values are a coroutine function.
# 
#     Arguments:
#         **kw (mixed): value to check if it is an iterable.
# 
#     Raises:
#         TypeError: if assertion fails.
#     """
#     for name, value in kw.items():
#         if not asyncio.iscoroutinefunction(value):
#             raise TypeError(
#                 'paco: {} must be a coroutine function'.format(name))
# 
# def assert_iter(**kw):
#     """
#     Asserts if a given values implements a valid iterable interface.
# 
#     Arguments:
#         **kw (mixed): value to check if it is an iterable.
# 
#     Raises:
#         TypeError: if assertion fails.
#     """
#     for name, value in kw.items():
#         if not isiter(value):
#             raise TypeError(
#                 'paco: {} must be an iterable object'.format(name))


# Path: paco/flat_map.py
import asyncio
from .assertions import isiter
from .reduce import reduce
from .decorator import overload
from .assertions import assert_corofunction, assert_iter

        loop (asyncio.BaseEventLoop): optional event loop to use.
        return_exceptions (bool): enable/disable returning exceptions in case
            of error. `collect` param must be True.
        timeout (int|float): timeout can be used to control the maximum number
            of seconds to wait before returning. timeout can be an int or
            float. If timeout is not specified or None, there is no limit to
            the wait time.
        *args (mixed): optional variadic arguments to pass to the
            coroutine iterable function.

    Returns:
        results (list): ordered list of values yielded by coroutines

    Raises:
        TypeError: in case of invalid input arguments.

    Usage::

        async def mul_2(num):
            return num * 2

        await paco.flat_map(mul_2, [1, [2], [3, [4]], [(5,)]])
        # => [2, 4, 6, 8, 10]

        # Pipeline style
        await [1, [2], [3, [4]], [(5,)]] | paco.flat_map(mul_2)
        # => [2, 4, 6, 8, 10]

    """
    assert_corofunction(coro=coro)

    assert_iter(iterable=iterable)