diff --git a/src/python/jw/pkg/lib/App.py b/src/python/jw/pkg/lib/App.py index 11de4fdf..566c3691 100644 --- a/src/python/jw/pkg/lib/App.py +++ b/src/python/jw/pkg/lib/App.py @@ -1,12 +1,20 @@ # -*- coding: utf-8 -*- -from typing import Any +from __future__ import annotations + +from typing import Any, TYPE_CHECKING import os, sys, argparse, re, asyncio, cProfile +from .AsyncRunner import AsyncRunner from .log import * from .Types import LoadTypes +if TYPE_CHECKING: + from typing import TypeVar + from collections.abc import Awaitable + T = TypeVar("T") + class App: # export def _add_arguments(self, parser): @@ -66,6 +74,7 @@ class App: # export if eloop is None: self.__eloop = asyncio.get_event_loop() self.__own_eloop = True + self.__async_runner: AsyncRunner|None = None self.__parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter, description=description, add_help=False) @@ -138,10 +147,19 @@ class App: # export async def _run(self, args: argparse.Namespace) -> None: return await self.args.func(args) + def call_async(self, awaitable: Awaitable[T], timeout: float | None = None) -> T: + return self.async_runner.call(awaitable, timeout) + @property def eloop(self) -> asyncio.AbstractEventLoop: return self.__eloop + @property + def async_runner(self) -> AsyncRunner: + if self.__async_runner is None: + self.__async_runner = AsyncRunner() + return self.__async_runner + @property def cmdline(self) -> str: if self.__cmdline is None: @@ -159,7 +177,13 @@ class App: # export return self.__parser def run(self, argv=None) -> None: - return self.__eloop.run_until_complete(self.__run(argv)) # type: ignore + try: + ret = self.__eloop.run_until_complete(self.__run(argv)) # type: ignore + finally: + if self.__async_runner: + self.__async_runner.close() + self.__async_runner = None + return ret def run_sub_commands(description = '', name_filter = '^Cmd.*', modules=None, argv=None): # export app = App(description, name_filter, modules)