human
Complete the below
def async_run_until_complete(astep_func=None, loop=None, timeout=None, async_context=None, should_close=False):

    ''''Provides a function decorator for async-steps (coroutines).
    Provides an async event loop and runs the async-step until completion
    (or timeout, if specified).
    .. code-block:: python
    from behave import step
    from behave.api.async_step import async_run_until_complete
    import asyncio
    @step("an async step is executed")
    @async_run_until_complete
    async def astep_impl(context)
    await asycio.sleep(0.1)
    @step("an async step is executed")
    @async_run_until_complete(timeout=1.2)
    async def astep_impl2(context)
    # -- NOTE: Wrapped event loop waits with timeout=1.2 seconds.
    await asycio.sleep(0.3)
    Parameters:
    astep_func: Async step function (coroutine)
    loop (asyncio.EventLoop):   Event loop to use or None.
    timeout (int, float):       Timeout to wait for async-step completion.
    async_context (name):       Async_context name or object to use.
    should_close (bool):        Indicates if event lopp should be closed.
    .. note::
    * If :param:`loop` is None, the default event loop will be used
    or a new event loop is created.
    * If :param:`timeout` is provided, the event loop waits only the
    specified time.
    * :param:`async_context` is only used, if :param:`loop` is None.
    * If :param:`async_context` is a name, it will be used to retrieve
    the real async_context object from the context.'
    '''

=====
Give me a the Python program you requested?
assistant
#Here is the Python program you requested.
    @functools.wraps(astep_func)
    def step_decorator(astep_func, context, *args, **kwargs):
        loop = kwargs.pop('_loop', None)
        timeout = kwargs.pop('_timeout', None)
        async_context = kwargs.pop('_async_context', None)
        should_close = kwargs.pop('_should_close', None)
        if isinstance(loop, string_types):
            loop = getattr(context, loop, None)
        elif async_context:
            if isinstance(async_context, string_types):
                name = async_context
                async_context = use_or_create_async_context(context, name)
                loop = async_context.loop
            else:
                assert isinstance(async_context, AsyncContext)
                loop = async_context.loop
        if (loop is None):
            loop = (asyncio.get_event_loop() or asyncio.new_event_loop())
        try:
            if (timeout is None):
                loop.run_until_complete(astep_func(context, *args, **kwargs))
            else:
                task = loop.create_task(astep_func(context, *args, **kwargs))
                (done, pending) = loop.run_until_complete(asyncio.wait([task], timeout=timeout))
                assert (not pending), ('TIMEOUT-OCCURED:    timeout=%s' % timeout)
        finally:
            if (loop and should_close):
                loop.close()
    if (astep_func is None):
        def wrapped_decorator1(astep_func):
            @functools.wraps(astep_func)
            def wrapped_decorator2(context, *args, **kwargs):
                return step_decorator(astep_func, context, _loop=loop, _timeout=timeout, _async_context=async_context, _should_close=should_close, *args, **kwargs)
            assert callable(astep_func)
            return wrapped_decorator2
        return wrapped_decorator1
    else:
        assert callable(astep_func)
        @functools.wraps(astep_func)
        def wrapped_decorator(context, *args, **kwargs):
            return step_decorator(astep_func, context, *args, **kwargs)
        return wrapped_decorator