Skip to content

Commit 01fdd3c

Browse files
Use Self type for Container (#58)
* Use `Self` type for `Container` * Fix typos and formatting --------- Co-authored-by: Roberto Prevato <roberto.prevato@gmail.com>
1 parent 8bea9fe commit 01fdd3c

1 file changed

Lines changed: 61 additions & 30 deletions

File tree

rodi/__init__.py

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
Callable,
1111
ClassVar,
1212
DefaultDict,
13+
Iterator,
1314
Mapping,
1415
Protocol,
1516
Type,
@@ -46,8 +47,8 @@ def __contains__(self, item) -> bool:
4647

4748

4849
def inject(
49-
globalsns: Optional[Dict[str, Any]] = None,
50-
localns: Optional[Dict[str, Any]] = None,
50+
globalsns: dict[str, Any] | None = None,
51+
localns: dict[str, Any] | None = None,
5152
) -> Callable[[T], T]:
5253
"""
5354
Marks a class or a function as injected. This method is only necessary if the class
@@ -860,6 +861,9 @@ def __call__(self, context, activating_type):
860861
return self.factory(context)
861862

862863

864+
_ContainerSelf = TypeVar("_ContainerSelf", bound="Container")
865+
866+
863867
class Container(ContainerProtocol):
864868
"""
865869
Configuration class for a collection of services.
@@ -872,7 +876,7 @@ def __init__(
872876
*,
873877
strict: bool = False,
874878
scope_cls: Type[ActivationScope] | None = None,
875-
):
879+
) -> None:
876880
self._map: dict[Type, Callable] = {}
877881
self._aliases: DefaultDict[str, set[Type]] = defaultdict(set)
878882
self._exact_aliases: dict[str, Type] = {}
@@ -886,18 +890,18 @@ def provider(self) -> Services:
886890
self._provider = self.build_provider()
887891
return self._provider
888892

889-
def __iter__(self):
893+
def __iter__(self) -> Iterator[tuple[Type, Callable]]:
890894
yield from self._map.items()
891895

892-
def __contains__(self, key):
896+
def __contains__(self, key: object) -> bool:
893897
return key in self._map
894898

895899
def bind_types(
896-
self,
900+
self: _ContainerSelf,
897901
obj_type: Any,
898902
concrete_type: Any = None,
899903
life_style: ServiceLifeStyle = ServiceLifeStyle.TRANSIENT,
900-
):
904+
) -> _ContainerSelf:
901905
try:
902906
assert issubclass(concrete_type, obj_type), (
903907
f"Cannot register {class_name(obj_type)} for abstract class "
@@ -910,13 +914,13 @@ def bind_types(
910914
return self
911915

912916
def register(
913-
self,
917+
self: _ContainerSelf,
914918
obj_type: Any,
915919
sub_type: Any = None,
916920
instance: Any = None,
917921
*args,
918922
**kwargs,
919-
) -> "Container":
923+
) -> _ContainerSelf:
920924
"""
921925
Registers a type in this container.
922926
"""
@@ -942,7 +946,11 @@ def resolve(
942946
"""
943947
return self.provider.get(obj_type, scope=scope)
944948

945-
def add_alias(self, name: str, desired_type: Type):
949+
def add_alias(
950+
self: _ContainerSelf,
951+
name: str,
952+
desired_type: Type,
953+
) -> _ContainerSelf:
946954
"""
947955
Adds an alias to the set of inferred aliases.
948956
@@ -957,7 +965,7 @@ def add_alias(self, name: str, desired_type: Type):
957965
self._aliases[name].add(desired_type)
958966
return self
959967

960-
def add_aliases(self, values: AliasesTypeHint):
968+
def add_aliases(self: _ContainerSelf, values: AliasesTypeHint) -> _ContainerSelf:
961969
"""
962970
Adds aliases to the set of inferred aliases.
963971
@@ -968,7 +976,12 @@ def add_aliases(self, values: AliasesTypeHint):
968976
self.add_alias(key, value)
969977
return self
970978

971-
def set_alias(self, name: str, desired_type: Type, override: bool = False):
979+
def set_alias(
980+
self: _ContainerSelf,
981+
name: str,
982+
desired_type: Type,
983+
override: bool = False,
984+
) -> _ContainerSelf:
972985
"""
973986
Sets an exact alias for a desired type.
974987
@@ -984,7 +997,11 @@ def set_alias(self, name: str, desired_type: Type, override: bool = False):
984997
self._exact_aliases[name] = desired_type
985998
return self
986999

987-
def set_aliases(self, values: AliasesTypeHint, override: bool = False):
1000+
def set_aliases(
1001+
self: _ContainerSelf,
1002+
values: AliasesTypeHint,
1003+
override: bool = False,
1004+
) -> _ContainerSelf:
9881005
"""Sets many exact aliases for desired types.
9891006
9901007
:param values: mapping object (parameter name: class)
@@ -1013,8 +1030,8 @@ def _bind(self, key: Type, value: Any) -> None:
10131030
self._aliases[to_standard_param_name(key_name)].add(key)
10141031

10151032
def add_instance(
1016-
self, instance: Any, declared_class: Type | None = None
1017-
) -> "Container":
1033+
self: _ContainerSelf, instance: Any, declared_class: Type | None = None
1034+
) -> _ContainerSelf:
10181035
"""
10191036
Registers an exact instance, optionally by declared class.
10201037
@@ -1030,8 +1047,8 @@ def add_instance(
10301047
return self
10311048

10321049
def add_singleton(
1033-
self, base_type: Type, concrete_type: Type | None = None
1034-
) -> "Container":
1050+
self: _ContainerSelf, base_type: Type, concrete_type: Type | None = None
1051+
) -> _ContainerSelf:
10351052
"""
10361053
Registers a type by base type, to be instantiated with singleton lifetime.
10371054
If a single type is given, the method `add_exact_singleton` is used.
@@ -1047,8 +1064,10 @@ def add_singleton(
10471064
return self.bind_types(base_type, concrete_type, ServiceLifeStyle.SINGLETON)
10481065

10491066
def add_scoped(
1050-
self, base_type: Type, concrete_type: Type | None = None
1051-
) -> "Container":
1067+
self: _ContainerSelf,
1068+
base_type: Type,
1069+
concrete_type: Type | None = None,
1070+
) -> _ContainerSelf:
10521071
"""
10531072
Registers a type by base type, to be instantiated with scoped lifetime.
10541073
If a single type is given, the method `add_exact_scoped` is used.
@@ -1064,8 +1083,10 @@ def add_scoped(
10641083
return self.bind_types(base_type, concrete_type, ServiceLifeStyle.SCOPED)
10651084

10661085
def add_transient(
1067-
self, base_type: Type, concrete_type: Type | None = None
1068-
) -> "Container":
1086+
self: _ContainerSelf,
1087+
base_type: Type,
1088+
concrete_type: Type | None = None,
1089+
) -> _ContainerSelf:
10691090
"""
10701091
Registers a type by base type, to be instantiated with transient lifetime.
10711092
If a single type is given, the method `add_exact_transient` is used.
@@ -1080,7 +1101,9 @@ def add_transient(
10801101

10811102
return self.bind_types(base_type, concrete_type, ServiceLifeStyle.TRANSIENT)
10821103

1083-
def _add_exact_singleton(self, concrete_type: Type) -> "Container":
1104+
def _add_exact_singleton(
1105+
self: _ContainerSelf, concrete_type: Type
1106+
) -> _ContainerSelf:
10841107
"""
10851108
Registers an exact type, to be instantiated with singleton lifetime.
10861109
@@ -1094,7 +1117,7 @@ def _add_exact_singleton(self, concrete_type: Type) -> "Container":
10941117
)
10951118
return self
10961119

1097-
def _add_exact_scoped(self, concrete_type: Type) -> "Container":
1120+
def _add_exact_scoped(self: _ContainerSelf, concrete_type: Type) -> _ContainerSelf:
10981121
"""
10991122
Registers an exact type, to be instantiated with scoped lifetime.
11001123
@@ -1107,7 +1130,9 @@ def _add_exact_scoped(self, concrete_type: Type) -> "Container":
11071130
)
11081131
return self
11091132

1110-
def _add_exact_transient(self, concrete_type: Type) -> "Container":
1133+
def _add_exact_transient(
1134+
self: _ContainerSelf, concrete_type: Type
1135+
) -> _ContainerSelf:
11111136
"""
11121137
Registers an exact type, to be instantiated with transient lifetime.
11131138
@@ -1122,20 +1147,26 @@ def _add_exact_transient(self, concrete_type: Type) -> "Container":
11221147
return self
11231148

11241149
def add_singleton_by_factory(
1125-
self, factory: FactoryCallableType, return_type: Type | None = None
1126-
) -> "Container":
1150+
self: _ContainerSelf,
1151+
factory: FactoryCallableType,
1152+
return_type: Type | None = None,
1153+
) -> _ContainerSelf:
11271154
self.register_factory(factory, return_type, ServiceLifeStyle.SINGLETON)
11281155
return self
11291156

11301157
def add_transient_by_factory(
1131-
self, factory: FactoryCallableType, return_type: Type | None = None
1132-
) -> "Container":
1158+
self: _ContainerSelf,
1159+
factory: FactoryCallableType,
1160+
return_type: Type | None = None,
1161+
) -> _ContainerSelf:
11331162
self.register_factory(factory, return_type, ServiceLifeStyle.TRANSIENT)
11341163
return self
11351164

11361165
def add_scoped_by_factory(
1137-
self, factory: FactoryCallableType, return_type: Type | None = None
1138-
) -> "Container":
1166+
self: _ContainerSelf,
1167+
factory: FactoryCallableType,
1168+
return_type: Type | None = None,
1169+
) -> _ContainerSelf:
11391170
self.register_factory(factory, return_type, ServiceLifeStyle.SCOPED)
11401171
return self
11411172

0 commit comments

Comments
 (0)