66import re
77from collections import defaultdict
88from collections .abc import AsyncIterator , Awaitable , Callable , Mapping
9- from typing import IO , Any , Literal , NewType , cast , get_args
9+ from typing import IO , Any , Generic , Literal , NewType , TypeVar , cast , get_args
1010
1111import httpx
1212import httpx_sse
@@ -52,7 +52,14 @@ def default_message(self) -> str:
5252 return f"SSE loop stopped (first error: { self .first_error } , last error: { self .last_error } )"
5353
5454
55- class Futures [Tk , Tv ]:
55+ Tk = TypeVar ("Tk" )
56+ Tv = TypeVar ("Tv" )
57+ Tok = TypeVar ("Tok" , bound = "OKResult" )
58+ Tko = TypeVar ("Tko" , bound = "ErrorResult" )
59+ TokWithImage = TypeVar ("TokWithImage" , bound = "OKResultWithImage" )
60+
61+
62+ class Futures (Generic [Tk , Tv ]):
5663 _event_loop : asyncio .AbstractEventLoop | None
5764
5865 @property
@@ -140,7 +147,10 @@ def success(self) -> None:
140147 self .failures = 0
141148
142149
143- class TimeoutableAsyncIterator [T ](AsyncIterator [T ]):
150+ T = TypeVar ("T" )
151+
152+
153+ class TimeoutableAsyncIterator (AsyncIterator [T ], Generic [T ]):
144154 def __init__ (self , iterator : AsyncIterator [T ], timeout : float ) -> None :
145155 self .iterator = iterator
146156 self .timeout = timeout
@@ -187,7 +197,7 @@ def reset(self) -> None:
187197 self .active = asyncio .get_running_loop ().create_future ()
188198
189199 @staticmethod
190- def async_return [ T ] (x : T ) -> Callable [[], Awaitable [T ]]:
200+ def async_return (x : T ) -> Callable [[], Awaitable [T ]]:
191201 async def f () -> T :
192202 return x
193203
@@ -613,11 +623,11 @@ async def get_image(
613623 response = await self .request ("GET" , f"state/image/{ state_id } " , params = params )
614624 return response .content
615625
616- async def _run_one [ Tin , Tout ] (
626+ async def _run_one (
617627 self ,
618- co : Callable [["EditorAPIContext" , Tin ], Awaitable [Tout ]],
619- params : Tin ,
620- ) -> Tout :
628+ co : Callable [["EditorAPIContext" , Any ], Awaitable [Any ]],
629+ params : Any ,
630+ ) -> Any :
621631 # This wraps the coroutine in the SSE loop.
622632 # This is mostly useful if you use synchronous Python,
623633 # otherwise you can call the functions directly.
@@ -630,11 +640,11 @@ async def _run_one[Tin, Tout](
630640 finally :
631641 await self .sse_stop ()
632642
633- def run_one_sync [ Tin , Tout ] (
643+ def run_one_sync (
634644 self ,
635- co : Callable [["EditorAPIContext" , Tin ], Awaitable [Tout ]],
636- params : Tin ,
637- ) -> Tout :
645+ co : Callable [["EditorAPIContext" , Any ], Awaitable [Any ]],
646+ params : Any ,
647+ ) -> Any :
638648 try :
639649 loop = asyncio .get_event_loop ()
640650 except RuntimeError :
@@ -1032,7 +1042,7 @@ async def _create_state(
10321042 status = await self .ctx .sse_await (state_id , timeout = timeout )
10331043 return state_id , status
10341044
1035- async def _response [ Tok : OKResult , Tko : ErrorResult ] (
1045+ async def _response (
10361046 self ,
10371047 st : StateID ,
10381048 ok : bool ,
@@ -1047,22 +1057,21 @@ async def _response[Tok: OKResult, Tko: ErrorResult](
10471057 assert meta ["status" ] == "ko"
10481058 return t_ko (state_id = st , meta = meta )
10491059
1050- async def _response_with_image [ Tok : OKResultWithImage , Tko : ErrorResult ] (
1060+ async def _response_with_image (
10511061 self ,
10521062 st : StateID ,
10531063 ok : bool ,
1054- t_ok : type [Tok ] = OKResultWithImage ,
1064+ t_ok : type [TokWithImage ] = OKResultWithImage ,
10551065 t_ko : type [Tko ] = ErrorResult ,
10561066 params : ImageOutParams | None = None ,
1057- ) -> Tok | Tko :
1067+ ) -> TokWithImage | Tko :
10581068 if ok :
10591069 if params is None :
10601070 params = ImageOutParams ()
1061- async with asyncio .TaskGroup () as tg :
1062- meta_f = tg .create_task (self .ctx .get_meta (st ))
1063- image_f = tg .create_task (self .ctx .get_image (st , params .image_format , params .resolution ))
1064- meta = meta_f .result ()
1065- image = image_f .result ()
1071+ meta , image = await asyncio .gather (
1072+ self .ctx .get_meta (st ),
1073+ self .ctx .get_image (st , params .image_format , params .resolution ),
1074+ )
10661075 assert meta ["status" ] == "ok"
10671076 return t_ok (state_id = st , meta = meta , image = image )
10681077 else :
0 commit comments