# Path: paco/generator.py
# @asyncio.coroutine
# def consume(generator):  # pragma: no cover
#     """
#     Helper function to consume a synchronous or asynchronous generator.
# 
#     Arguments:
#         generator (generator|asyncgenerator): generator to consume.
# 
#     Returns:
#         list
#     """
#     # If synchronous generator, just consume and return as list
#     if hasattr(generator, '__next__'):
#         return list(generator)
# 
#     if not PY_35:
#         raise RuntimeError(
#             'paco: asynchronous iterator protocol not supported')
# 
#     # If asynchronous generator, consume it generator protocol manually
#     buf = []
#     while True:
#         try:
#             buf.append((yield from generator.__anext__()))
#         except StopAsyncIteration:  # noqa
#             break
# 
#     return buf
# 
# 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))


import asyncio
import functools
from inspect import isfunction, getargspec
from .generator import consume
from .assertions import isiter
# -*- coding: utf-8 -*-

# Yielded iterable error
IterableError = TypeError('pipeline yielded a non iterable object')


class PipeOverloader(object):
    """
    Pipe operator overloader object wrapping a given fn.
    """
    def __init__(self, fn, args, kw):
        self.__fn = fn
        self.__args = args
        self.__kw = kw

    @asyncio.coroutine
    def __await_coro(self, coro):
        return (yield from self.__trigger((yield from coro)))

    @asyncio.coroutine
    def __consume_generator(self, iterable):
        return (yield from self.__trigger((yield from consume(iterable))))

    def __trigger(self, iterable):

# Path: paco/generator.py
# @asyncio.coroutine
# def consume(generator):  # pragma: no cover
#     """
#     Helper function to consume a synchronous or asynchronous generator.
# 
#     Arguments:
#         generator (generator|asyncgenerator): generator to consume.
# 
#     Returns:
#         list
#     """
#     # If synchronous generator, just consume and return as list
#     if hasattr(generator, '__next__'):
#         return list(generator)
# 
#     if not PY_35:
#         raise RuntimeError(
#             'paco: asynchronous iterator protocol not supported')
# 
#     # If asynchronous generator, consume it generator protocol manually
#     buf = []
#     while True:
#         try:
#             buf.append((yield from generator.__anext__()))
#         except StopAsyncIteration:  # noqa
#             break
# 
#     return buf
# 
# 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/pipe.py
import asyncio
import functools
from inspect import isfunction, getargspec
from .generator import consume
from .assertions import isiter

# -*- coding: utf-8 -*-

# Yielded iterable error
IterableError = TypeError('pipeline yielded a non iterable object')


class PipeOverloader(object):
    """
    Pipe operator overloader object wrapping a given fn.
    """
    def __init__(self, fn, args, kw):
        self.__fn = fn
        self.__args = args
        self.__kw = kw

    @asyncio.coroutine
    def __await_coro(self, coro):
        return (yield from self.__trigger((yield from coro)))

    @asyncio.coroutine
    def __consume_generator(self, iterable):
        return (yield from self.__trigger((yield from consume(iterable))))

    def __trigger(self, iterable):

        if not isiter(iterable):