|
8 | 8 | AsyncIterator, |
9 | 9 | Awaitable, |
10 | 10 | Callable, |
| 11 | + Container, |
11 | 12 | Generator, |
12 | 13 | Iterable, |
13 | 14 | Iterator, |
|
18 | 19 | from enum import StrEnum |
19 | 20 | from functools import partial, partialmethod, singledispatchmethod, update_wrapper |
20 | 21 | from inspect import ( |
| 22 | + BoundArguments, |
21 | 23 | Signature, |
22 | 24 | isasyncgenfunction, |
23 | 25 | isclass, |
@@ -739,28 +741,32 @@ def mod(name: str | None = None, /) -> Module: |
739 | 741 | class Dependencies: |
740 | 742 | lazy_mapping: Lazy[Mapping[str, Injectable[Any]]] |
741 | 743 |
|
742 | | - def __iter__(self) -> Iterator[tuple[str, Any]]: |
743 | | - for name, injectable in self.items(): |
| 744 | + def iter(self, exclude: Container[str]) -> Iterator[tuple[str, Any]]: |
| 745 | + for name, injectable in self.items(exclude): |
744 | 746 | with suppress(SkipInjectable): |
745 | 747 | yield name, injectable.get_instance() |
746 | 748 |
|
747 | | - async def __aiter__(self) -> AsyncIterator[tuple[str, Any]]: |
748 | | - for name, injectable in self.items(): |
| 749 | + async def aiter(self, exclude: Container[str]) -> AsyncIterator[tuple[str, Any]]: |
| 750 | + for name, injectable in self.items(exclude): |
749 | 751 | with suppress(SkipInjectable): |
750 | 752 | yield name, await injectable.aget_instance() |
751 | 753 |
|
752 | 754 | @property |
753 | 755 | def are_resolved(self) -> bool: |
754 | 756 | return self.lazy_mapping.is_set |
755 | 757 |
|
756 | | - async def aget_arguments(self) -> dict[str, Any]: |
757 | | - return {key: value async for key, value in self} |
| 758 | + async def aget_arguments(self, *, exclude: Container[str]) -> dict[str, Any]: |
| 759 | + return {key: value async for key, value in self.aiter(exclude)} |
758 | 760 |
|
759 | | - def get_arguments(self) -> dict[str, Any]: |
760 | | - return dict(self) |
| 761 | + def get_arguments(self, *, exclude: Container[str]) -> dict[str, Any]: |
| 762 | + return dict(self.iter(exclude)) |
761 | 763 |
|
762 | | - def items(self) -> Iterator[tuple[str, Injectable[Any]]]: |
763 | | - return iter((~self.lazy_mapping).items()) |
| 764 | + def items(self, exclude: Container[str]) -> Iterator[tuple[str, Injectable[Any]]]: |
| 765 | + return ( |
| 766 | + (name, injectable) |
| 767 | + for name, injectable in (~self.lazy_mapping).items() |
| 768 | + if name not in exclude |
| 769 | + ) |
764 | 770 |
|
765 | 771 | @classmethod |
766 | 772 | def from_iterable(cls, iterable: Iterable[tuple[str, Injectable[Any]]]) -> Self: |
@@ -863,16 +869,18 @@ async def abind( |
863 | 869 | args: Iterable[Any] = (), |
864 | 870 | kwargs: Mapping[str, Any] | None = None, |
865 | 871 | ) -> Arguments: |
866 | | - additional_arguments = await self.__dependencies.aget_arguments() |
867 | | - return self.__bind(args, kwargs, additional_arguments) |
| 872 | + bound = self.__bind(args, kwargs) |
| 873 | + dependencies = await self.__dependencies.aget_arguments(exclude=bound.arguments) |
| 874 | + return self.__build_arguments(bound, dependencies) |
868 | 875 |
|
869 | 876 | def bind( |
870 | 877 | self, |
871 | 878 | args: Iterable[Any] = (), |
872 | 879 | kwargs: Mapping[str, Any] | None = None, |
873 | 880 | ) -> Arguments: |
874 | | - additional_arguments = self.__dependencies.get_arguments() |
875 | | - return self.__bind(args, kwargs, additional_arguments) |
| 881 | + bound = self.__bind(args, kwargs) |
| 882 | + dependencies = self.__dependencies.get_arguments(exclude=bound.arguments) |
| 883 | + return self.__build_arguments(bound, dependencies) |
876 | 884 |
|
877 | 885 | async def acall(self, /, *args: P.args, **kwargs: P.kwargs) -> T: |
878 | 886 | with self.__lock: |
@@ -925,23 +933,25 @@ def __bind( |
925 | 933 | self, |
926 | 934 | args: Iterable[Any], |
927 | 935 | kwargs: Mapping[str, Any] | None, |
928 | | - additional_arguments: dict[str, Any] | None, |
929 | | - ) -> Arguments: |
| 936 | + ) -> BoundArguments: |
930 | 937 | if kwargs is None: |
931 | 938 | kwargs = {} |
932 | 939 |
|
933 | | - if not additional_arguments: |
934 | | - return Arguments(args, kwargs) |
935 | | - |
936 | | - bound = self.signature.bind_partial(*args, **kwargs) |
937 | | - bound.arguments = bound.arguments | additional_arguments | bound.arguments |
938 | | - return Arguments(bound.args, bound.kwargs) |
| 940 | + return self.signature.bind_partial(*args, **kwargs) |
939 | 941 |
|
940 | 942 | def __run_tasks(self) -> None: |
941 | 943 | while tasks := self.__tasks: |
942 | 944 | task = tasks.popleft() |
943 | 945 | task() |
944 | 946 |
|
| 947 | + @staticmethod |
| 948 | + def __build_arguments( |
| 949 | + bound: BoundArguments, |
| 950 | + additional_arguments: dict[str, Any], |
| 951 | + ) -> Arguments: |
| 952 | + bound.arguments = bound.arguments | additional_arguments |
| 953 | + return Arguments(bound.args, bound.kwargs) |
| 954 | + |
945 | 955 |
|
946 | 956 | class InjectedFunction[**P, T](HiddenCaller[P, T], ABC): |
947 | 957 | __slots__ = ("__dict__", "__injection_metadata__") |
|
0 commit comments