async def asolve(
self,
/,
*args: Any,
stack: AsyncExitStack,
cache_dependencies: Dict[
Union[
Callable[P, T],
Callable[P, Awaitable[T]],
],
T,
],
dependency_overrides: Optional[
Dict[
Union[
Callable[P, T],
Callable[P, Awaitable[T]],
],
Union[
Callable[P, T],
Callable[P, Awaitable[T]],
],
]
] = None,
nested: bool = False,
**kwargs: Any,
) -> T:
cast_gen = self._solve(
*args,
cache_dependencies=cache_dependencies,
dependency_overrides=dependency_overrides,
**kwargs,
)
try:
args, kwargs, _ = next(cast_gen) # type: ignore[assignment]
except StopIteration as e:
cached_value: T = e.value
return cached_value
# Heat cache and solve extra dependencies
dep_to_solve: List[Callable[..., Awaitable[Any]]] = []
try:
async with anyio.create_task_group() as tg:
for dep, subdep in self.sorted_dependencies:
solve = partial(
dep.asolve,
*args,
stack=stack,
cache_dependencies=cache_dependencies,
dependency_overrides=dependency_overrides,
nested=True,
**kwargs,
)
if not subdep:
tg.start_soon(solve)
else:
dep_to_solve.append(solve)
except ExceptionGroup as exgr:
for ex in exgr.exceptions:
raise ex from None
for i in dep_to_solve:
await i()
# Always get from cache
for dep in self.extra_dependencies:
await dep.asolve(
*args,
stack=stack,
cache_dependencies=cache_dependencies,
dependency_overrides=dependency_overrides,
nested=True,
**kwargs,
)
for dep_arg, dep in self.dependencies.items():
kwargs[dep_arg] = await dep.asolve(
stack=stack,
cache_dependencies=cache_dependencies,
dependency_overrides=dependency_overrides,
nested=True,
**kwargs,
)
custom_to_solve: List[CustomField] = []
try:
async with anyio.create_task_group() as tg:
for custom in self.custom_fields.values():
if custom.field:
tg.start_soon(run_async, custom.use_field, kwargs)
else:
custom_to_solve.append(custom)
except ExceptionGroup as exgr:
for ex in exgr.exceptions:
raise ex from None
for j in custom_to_solve:
kwargs = await run_async(j.use, **kwargs)
final_args, final_kwargs, call = cast_gen.send(kwargs)
if self.is_generator and nested:
response = await solve_generator_async(
*final_args,
call=call,
stack=stack,
**final_kwargs,
)
else:
response = await run_async(call, *final_args, **final_kwargs)
try:
cast_gen.send(response)
except StopIteration as e:
value: T = e.value
if not self.cast or nested or not self.is_generator:
return value
else:
return async_map(self._cast_response, value) # type: ignore[return-value, arg-type]
raise AssertionError("unreachable")