import asyncio
import functools


def schedule_coroutine(delay, coro_func, *args, **kwargs):
    """
    Creates a coroutine out of the provided coroutine function coro_func and
    the provided args and kwargs, then schedules the coroutine to be called
    on the running event loop after delay seconds (delay can be float or int).

    Returns asyncio.Task on which cancel() can be called to cancel the running
    of the coroutine.

    The coro_func parameter should not be a coroutine, but rather a coroutine
    function (a function defined with async).  The reason for this is we want
    to defer creation of the actual coroutine until we're ready to schedule it
    with "ensure_future".  Otherwise every time we cancel a TimerTask
    returned by "call_later", python prints "RuntimeWarning: coroutine
    '<coro-name>' was never awaited".
    """
    # See method above for comment on "get_event_loop()" vs "get_running_loop()".
    loop = asyncio.get_event_loop()
    coro_partial = functools.partial(coro_func, *args, **kwargs)
    return loop.call_later(delay, lambda: asyncio.ensure_future(coro_partial()))