Example #1
0
def basic_config(level: Union[int, str] = LogLevel.default(),
                 log_format: Union[str, LogFormat] = LogFormat.default(),
                 buffered: bool = True,
                 buffer_size: int = 1024,
                 flush_interval: Union[int, float] = 0.2,
                 loop: asyncio.AbstractEventLoop = None,
                 **kwargs: Any) -> None:
    loop = loop or asyncio.get_event_loop()
    unhandled_hook = UnhandledLoopHook()

    def wrap_handler(handler: logging.Handler) -> logging.Handler:
        nonlocal buffer_size, buffered, loop, unhandled_hook

        unhandled_hook.set_handler(handler)

        if buffered:
            return wrap_logging_handler(
                handler=handler,
                buffer_size=buffer_size,
                flush_interval=flush_interval,
                loop=loop,
            )
        return handler

    aiomisc_log.basic_config(level=level,
                             log_format=log_format,
                             handler_wrapper=wrap_handler,
                             **kwargs)

    loop.set_exception_handler(unhandled_hook)
Example #2
0
def loop(
    request,
    services,
    loop_debug,
    default_context,
    entrypoint_kwargs,
    thread_pool_size,
    thread_pool_executor,
    loop: asyncio.AbstractEventLoop,
    caplog: pytest.LogCaptureFixture,
):
    from aiomisc.context import get_context
    from aiomisc.entrypoint import entrypoint

    if LOG_LEVEL:
        LOG_LEVEL.set(logging.getLogger().getEffectiveLevel())

    pool = thread_pool_executor(thread_pool_size)
    loop.set_default_executor(pool)

    get_marker = request.node.get_closest_marker
    forbid_loop_getter_marker = get_marker("forbid_get_event_loop")
    catch_unhandled_marker = get_marker("catch_loop_exceptions")

    exceptions = list()
    if catch_unhandled_marker:
        loop.set_exception_handler(lambda l, c: exceptions.append(c))

    try:
        with entrypoint(*services, loop=loop, **entrypoint_kwargs):

            ctx = get_context(loop)

            for key, value in default_context.items():
                ctx[key] = value

            if forbid_loop_getter_marker:
                asyncio.get_event_loop.side_effect = partial(
                    pytest.fail,
                    "get_event_loop is forbidden",
                )

            yield loop

            if exceptions:
                logging.error(
                    "Unhandled exceptions found:\n\n\t%s",
                    "\n\t".join(("Message: {m}\n\t"
                                 "Future: {f}\n\t"
                                 "Exception: {e}").format(
                                     m=e["message"],
                                     f=repr(e.get("future")),
                                     e=repr(e.get("exception")),
                                 ) for e in exceptions),
                )
                pytest.fail("Unhandled exceptions found. See logs.")
    finally:
        asyncio.get_event_loop.side_effect = get_event_loop
        del loop
Example #3
0
def test_asyncio_run_sync_no_asyncio_run(
    asyncio_event_loop: asyncio.AbstractEventLoop,
) -> None:
    """Test that the thread pool shutdown callback does not raise an exception."""

    def exception_handler(loop: object, context: Any = None) -> None:
        exceptions.append(context["exception"])

    exceptions: List[BaseException] = []
    asyncio_event_loop.set_exception_handler(exception_handler)
    asyncio_event_loop.run_until_complete(to_thread.run_sync(time.sleep, 0))
    assert not exceptions
Example #4
0
def ignore_aiohttp_ssl_error(loop: AbstractEventLoop):
    original_handler = loop.get_exception_handler()

    def ignore_ssl_error(loop: AbstractEventLoop, context: Dict):
        # Ignore SSLError from `aiohttp` module. It is known as a bug.
        if isinstance(context["exception"], ssl.SSLError):
            return

        if original_handler is not None:
            original_handler(loop, context)
        else:
            loop.default_exception_handler(context)

    loop.set_exception_handler(ignore_ssl_error)
Example #5
0
def setup_event_loop(event_loop: AbstractEventLoop) -> None:
    event_loop.set_exception_handler(ignore_exception)
def _setup_exception_handler(loop: asyncio.AbstractEventLoop,
                             debug: bool) -> None:
    if debug:
        return
    loop.set_exception_handler(_exception_handler)
Example #7
0
def run(
    func: Optional[Awaitable[None]] = None,
    *,
    finalize: Optional[Awaitable[None]] = None,
    loop: AbstractEventLoop = None,
):
    """ Configure the event loop to react to signals and exceptions then
    run the provided coroutine and loop forever.

    Shutdown the event loop when a signal or exception is received or the
    supplied function explicitly requests the loop to stop.

    This function provides some of the common boilerplate typically needed
    when running asyncio applications. It registers signal handlers that
    listen for SIGINT and SIGTERM that will stop the event loop and trigger
    application shutdown actions. It registers a global exception handler
    that will stop the loop and trigger application shutdown actions. This
    helps catch a common problem that occurs in asyncio applications in
    which an exception occurs in a task that was spun off but is not
    reported until the event loop is stopped. This approach allows users
    to be notified about these issues as soon as possible.

    :param func: A coroutine to run before looping forever. This coroutine
      is typically the "main" coroutine from which all other work is spawned.
      The event loop will continue to run after the supplied coroutine
      completes.

    :param finalize: An optional coroutine to run when shutting down. Use this
      to perform any graceful cleanup activities such as finalising log files,
      disconnecting from services such as databases, etc.

    :param loop: An optional event loop to run. If not supplied the default
      event loop is used (i.e., whatever ``asyncio.get_event_loop()`` returns.

    """
    logger.debug("Application runner starting")

    if func:
        if not (inspect.isawaitable(func)
                or inspect.iscoroutinefunction(func)):
            raise Exception("func must be a coroutine or a coroutine function "
                            f"that takes no arguments, got {func}")

    if finalize:
        if not (inspect.isawaitable(finalize)
                or inspect.iscoroutinefunction(finalize)):
            raise Exception(
                "finalize must be a coroutine or a coroutine function "
                f"that takes no arguments, got {finalize}")

    # Use a supplied loop or the default event loop. If the loop is closed
    # (which can happen in unit tests) then create a new event loop.
    loop = loop or asyncio.get_event_loop()
    if loop.is_closed():
        loop = asyncio.new_event_loop()

    def signal_handler(loop, sig):
        logger.info(f"Caught {sig.name}, stopping.")
        loop.call_soon(loop.stop)

    loop.add_signal_handler(SIGINT, signal_handler, loop, SIGINT)
    loop.add_signal_handler(SIGTERM, signal_handler, loop, SIGTERM)

    def exception_handler(loop, context):
        exc_msg = context["message"]
        exc = context["exception"]
        logger.exception(f"Caught exception: {exc_msg}", exc_info=exc)
        loop.call_soon(loop.stop)

    loop.set_exception_handler(exception_handler)

    try:
        if func:
            if inspect.iscoroutinefunction(func):
                func = func()  # type: ignore
            assert func is not None
            loop.create_task(func)
        loop.run_forever()
    finally:
        logger.debug("Application shutdown sequence starting")
        if finalize:
            if inspect.iscoroutinefunction(finalize):
                finalize = finalize()  # type: ignore
            assert finalize is not None
            loop.run_until_complete(finalize)

        # Shutdown any outstanding tasks that are left running
        pending_tasks = all_tasks(loop=loop)
        if pending_tasks:
            logger.debug(f"Cancelling {len(pending_tasks)} pending tasks.")
            for task in pending_tasks:
                logger.debug(f"Cancelling task: {task}")
                task.cancel()
            try:
                loop.run_until_complete(asyncio.gather(*pending_tasks))
            except asyncio.CancelledError:
                pass

        loop.run_until_complete(loop.shutdown_asyncgens())

        logger.debug("Application shutdown sequence complete")

        loop.close()

        logger.debug("Application runner stopped")
Example #8
0
async def brute_basic(http_target_factory,
                      combo_factory=None,
                      username_factory=None,
                      password_factory=None,
                      pool_size: int = 100,
                      timeout: float = 5.0,
                      output: str = None,
                      loop: asyncio.AbstractEventLoop = None,
                      verbose: bool = False):
    loop = loop or asyncio.get_event_loop()
    tasks = target_tasks(
        http_target_factory,
        combo_factory,
        username_factory,
        password_factory,
    )

    def def_handler(_loop, ctx):
        loop.default_exception_handler(ctx)

    old_handler = loop.get_exception_handler() or def_handler

    def new_handler(_loop, ctx):
        exc = ctx.get("exception")
        ignore = (
            ssl.SSLError,
            asyncio.CancelledError,
        )
        if isinstance(exc, ignore):
            return
        old_handler(_loop, ctx)

    loop.set_exception_handler(new_handler)

    try:
        async with AioPool(pool_size) as pool:
            suc_files = [sys.stdout]
            err_files = [sys.stderr]

            if output:
                f = open(output, "a+")
                suc_files.append(f)

            kwargs = dict(timeout=timeout*1.5, get_result=getres.pair)

            async for (val, err) in pool.itermap(worker, tasks, **kwargs):
                if err:
                    print("ERROR")
                    print(err)
                    continue
                result, (url, username, password) = val
                if result is True:
                    print(C.GRN, file=sys.stdout, end="")
                    for file in suc_files:
                        print("{} {}:{}".format(url, username, password),
                              file=file, flush=True)
                    print(C.RST, file=sys.stdout, end="", flush=True)
                elif verbose:
                    print(C.RED, file=sys.stderr, end="")
                    for file in err_files:
                        print("Failure {} {}:{}".format(url, username, password),
                              file=file, flush=True)
                    print(C.RST, file=sys.stderr, end="", flush=True)
    finally:
        loop.set_exception_handler(old_handler)