# Path: aiosmtplib/compat.py
# PY36_OR_LATER = sys.version_info[:2] >= (3, 6)
# 
# def all_tasks(loop: asyncio.AbstractEventLoop = None):
#     if PY37_OR_LATER:
#         return asyncio.all_tasks(loop=loop)
# 
#     return asyncio.Task.all_tasks(loop=loop)  # type: ignore


import asyncio
from typing import Any, Awaitable, Optional
from .compat import PY36_OR_LATER, all_tasks
) -> Any:
    if loop is None:
        loop = asyncio.get_event_loop()

    if loop.is_running():
        raise RuntimeError("Event loop is already running.")

    result = loop.create_future()

    try:
        loop.run_until_complete(_await_with_future(coro, result))
    finally:
        shutdown_loop(loop)

    return result.result()


async def _await_with_future(coro: Awaitable, future: asyncio.Future) -> None:
    try:
        result = await coro
    except Exception as exc:
        future.set_exception(exc)
    else:
        future.set_result(result)


def shutdown_loop(loop: asyncio.AbstractEventLoop, timeout: float = 1.0) -> None:
    """
    Do the various dances to gently shutdown an event loop.
    """

# Path: aiosmtplib/compat.py
# PY36_OR_LATER = sys.version_info[:2] >= (3, 6)
# 
# def all_tasks(loop: asyncio.AbstractEventLoop = None):
#     if PY37_OR_LATER:
#         return asyncio.all_tasks(loop=loop)
# 
#     return asyncio.Task.all_tasks(loop=loop)  # type: ignore


# Path: aiosmtplib/sync.py
import asyncio
from typing import Any, Awaitable, Optional
from .compat import PY36_OR_LATER, all_tasks

) -> Any:
    if loop is None:
        loop = asyncio.get_event_loop()

    if loop.is_running():
        raise RuntimeError("Event loop is already running.")

    result = loop.create_future()

    try:
        loop.run_until_complete(_await_with_future(coro, result))
    finally:
        shutdown_loop(loop)

    return result.result()


async def _await_with_future(coro: Awaitable, future: asyncio.Future) -> None:
    try:
        result = await coro
    except Exception as exc:
        future.set_exception(exc)
    else:
        future.set_result(result)


def shutdown_loop(loop: asyncio.AbstractEventLoop, timeout: float = 1.0) -> None:
    """
    Do the various dances to gently shutdown an event loop.
    """

    tasks = all_tasks(loop=loop)