# Path: paco/timeout.py
# @decorate
# def timeout(coro, timeout=None, loop=None):
#     """
#     Wraps a given coroutine function, that when executed, if it takes more
#     than the given timeout in seconds to execute, it will be canceled and
#     raise an `asyncio.TimeoutError`.
# 
#     This function is equivalent to Python standard
#     `asyncio.wait_for()` function.
# 
#     This function can be used as decorator.
# 
#     Arguments:
#         coro (coroutinefunction|coroutine): coroutine to wrap.
#         timeout (int|float): max wait timeout in seconds.
#         loop (asyncio.BaseEventLoop): optional event loop to use.
# 
#     Raises:
#         TypeError: if coro argument is not a coroutine function.
# 
#     Returns:
#         coroutinefunction: wrapper coroutine function.
# 
#     Usage::
# 
#         await paco.timeout(coro, timeout=10)
# 
#     """
#     @asyncio.coroutine
#     def _timeout(coro):
#         return (yield from asyncio.wait_for(coro, timeout, loop=loop))
# 
#     @asyncio.coroutine
#     def wrapper(*args, **kw):
#         return (yield from _timeout(coro(*args, **kw)))
# 
#     return _timeout(coro) if asyncio.iscoroutine(coro) else wrapper
# 
# class TimeoutLimit(object):
#     """
#     Timeout limit context manager.
# 
#     Useful in cases when you want to apply timeout logic around block
#     of code or in cases when asyncio.wait_for is not suitable.
# 
#     Originally based on: https://github.com/aio-libs/async-timeout
# 
#     Arguments:
#         timeout (int): value in seconds or None to disable timeout logic.
#         loop (asyncio.BaseEventLoop): asyncio compatible event loop.
# 
#     Usage::
# 
#         with paco.TimeoutLimit(0.1):
#             await paco.wait(task1, task2)
#     """
# 
#     def __init__(self, timeout, loop=None):
#         self._timeout = timeout
#         self._loop = loop or asyncio.get_event_loop()
#         self._task = None
#         self._cancelled = False
#         self._cancel_handler = None
# 
#     def __enter__(self):
#         self._task = asyncio.Task.current_task(loop=self._loop)
#         if self._task is None:
#             raise RuntimeError('paco: timeout context manager should '
#                                'be used inside a task')
#         if self._timeout is not None:
#             self._cancel_handler = self._loop.call_later(
#                 self._timeout, self.cancel)
#         return self
# 
#     def __exit__(self, exc_type, exc_val, exc_tb):
#         if exc_type is asyncio.CancelledError and self._cancelled:
#             self._cancel_handler = None
#             self._task = None
#             raise asyncio.TimeoutError from None
#         if self._timeout is not None:
#             self._cancel_handler.cancel()
#             self._cancel_handler = None
#         self._task = None
# 
#     def cancel(self):
#         """
#         Cancels current task running task in the context manager.
#         """
#         self._cancelled = self._task.cancel()
# 
# Path: paco/run.py
# def run(coro, loop=None):
#     """
#     Convenient shortcut alias to ``loop.run_until_complete``.
# 
#     Arguments:
#         coro (coroutine): coroutine object to schedule.
#         loop (asyncio.BaseEventLoop): optional event loop to use.
#             Defaults to: ``asyncio.get_event_loop()``.
# 
#     Returns:
#         mixed: returned value by coroutine.
# 
#     Usage::
# 
#         async def mul_2(num):
#             return num * 2
# 
#         paco.run(mul_2(4))
#         # => 8
# 
#     """
#     loop = loop or asyncio.get_event_loop()
#     return loop.run_until_complete(coro)
# 
# Path: tests/helpers.py
# def run_in_loop(coro, *args, **kw):
#     loop = asyncio.get_event_loop()
#     if asyncio.iscoroutinefunction(coro) or isfunction(coro):
#         coro = coro(*args, **kw)
#     return loop.run_until_complete(coro)


import time
import pytest
import asyncio
from paco import timeout, TimeoutLimit, run
from .helpers import run_in_loop
    from asyncio import ensure_future
try:
except ImportError:
    ensure_future = asyncio.async


@asyncio.coroutine
def coro(delay=1):
    yield from asyncio.sleep(delay)


def test_timeout():
    task = timeout(coro, timeout=1)
    now = time.time()
    run_in_loop(task, delay=0.2)
    assert time.time() - now >= 0.2


def test_timeout_exceeded():
    task = timeout(coro, timeout=0.2)
    now = time.time()

    with pytest.raises(asyncio.TimeoutError):
        run_in_loop(task, delay=1)

    assert time.time() - now >= 0.2


def test_timeout_decorator():
    task = timeout(timeout=1)(coro)
    now = time.time()

# Path: paco/timeout.py
# @decorate
# def timeout(coro, timeout=None, loop=None):
#     """
#     Wraps a given coroutine function, that when executed, if it takes more
#     than the given timeout in seconds to execute, it will be canceled and
#     raise an `asyncio.TimeoutError`.
# 
#     This function is equivalent to Python standard
#     `asyncio.wait_for()` function.
# 
#     This function can be used as decorator.
# 
#     Arguments:
#         coro (coroutinefunction|coroutine): coroutine to wrap.
#         timeout (int|float): max wait timeout in seconds.
#         loop (asyncio.BaseEventLoop): optional event loop to use.
# 
#     Raises:
#         TypeError: if coro argument is not a coroutine function.
# 
#     Returns:
#         coroutinefunction: wrapper coroutine function.
# 
#     Usage::
# 
#         await paco.timeout(coro, timeout=10)
# 
#     """
#     @asyncio.coroutine
#     def _timeout(coro):
#         return (yield from asyncio.wait_for(coro, timeout, loop=loop))
# 
#     @asyncio.coroutine
#     def wrapper(*args, **kw):
#         return (yield from _timeout(coro(*args, **kw)))
# 
#     return _timeout(coro) if asyncio.iscoroutine(coro) else wrapper
# 
# class TimeoutLimit(object):
#     """
#     Timeout limit context manager.
# 
#     Useful in cases when you want to apply timeout logic around block
#     of code or in cases when asyncio.wait_for is not suitable.
# 
#     Originally based on: https://github.com/aio-libs/async-timeout
# 
#     Arguments:
#         timeout (int): value in seconds or None to disable timeout logic.
#         loop (asyncio.BaseEventLoop): asyncio compatible event loop.
# 
#     Usage::
# 
#         with paco.TimeoutLimit(0.1):
#             await paco.wait(task1, task2)
#     """
# 
#     def __init__(self, timeout, loop=None):
#         self._timeout = timeout
#         self._loop = loop or asyncio.get_event_loop()
#         self._task = None
#         self._cancelled = False
#         self._cancel_handler = None
# 
#     def __enter__(self):
#         self._task = asyncio.Task.current_task(loop=self._loop)
#         if self._task is None:
#             raise RuntimeError('paco: timeout context manager should '
#                                'be used inside a task')
#         if self._timeout is not None:
#             self._cancel_handler = self._loop.call_later(
#                 self._timeout, self.cancel)
#         return self
# 
#     def __exit__(self, exc_type, exc_val, exc_tb):
#         if exc_type is asyncio.CancelledError and self._cancelled:
#             self._cancel_handler = None
#             self._task = None
#             raise asyncio.TimeoutError from None
#         if self._timeout is not None:
#             self._cancel_handler.cancel()
#             self._cancel_handler = None
#         self._task = None
# 
#     def cancel(self):
#         """
#         Cancels current task running task in the context manager.
#         """
#         self._cancelled = self._task.cancel()
# 
# Path: paco/run.py
# def run(coro, loop=None):
#     """
#     Convenient shortcut alias to ``loop.run_until_complete``.
# 
#     Arguments:
#         coro (coroutine): coroutine object to schedule.
#         loop (asyncio.BaseEventLoop): optional event loop to use.
#             Defaults to: ``asyncio.get_event_loop()``.
# 
#     Returns:
#         mixed: returned value by coroutine.
# 
#     Usage::
# 
#         async def mul_2(num):
#             return num * 2
# 
#         paco.run(mul_2(4))
#         # => 8
# 
#     """
#     loop = loop or asyncio.get_event_loop()
#     return loop.run_until_complete(coro)
# 
# Path: tests/helpers.py
# def run_in_loop(coro, *args, **kw):
#     loop = asyncio.get_event_loop()
#     if asyncio.iscoroutinefunction(coro) or isfunction(coro):
#         coro = coro(*args, **kw)
#     return loop.run_until_complete(coro)


# Path: tests/timeout_test.py
import time
import pytest
import asyncio
from paco import timeout, TimeoutLimit, run
from .helpers import run_in_loop
    from asyncio import ensure_future

try:
except ImportError:
    ensure_future = asyncio.async


@asyncio.coroutine
def coro(delay=1):
    yield from asyncio.sleep(delay)


def test_timeout():
    task = timeout(coro, timeout=1)
    now = time.time()
    run_in_loop(task, delay=0.2)
    assert time.time() - now >= 0.2


def test_timeout_exceeded():
    task = timeout(coro, timeout=0.2)
    now = time.time()

    with pytest.raises(asyncio.TimeoutError):
        run_in_loop(task, delay=1)

    assert time.time() - now >= 0.2


def test_timeout_decorator():
    task = timeout(timeout=1)(coro)
    now = time.time()

    run_in_loop(task, delay=0.2)