Skip to content

Commit 759d89e

Browse files
committed
Add reprs to wiring markers
1 parent 1500a1d commit 759d89e

File tree

5 files changed

+89
-6
lines changed

5 files changed

+89
-6
lines changed

src/dependency_injector/providers.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,7 @@ cdef class ConfigurationOption(Provider):
15991599
return self._root
16001600

16011601
def get_name(self):
1602-
return ".".join((self._root.get_name(), self._get_self_name()))
1602+
return f"{self._root.get_name()}.{self._get_self_name()}"
16031603

16041604
def get_name_segments(self):
16051605
return self._name

src/dependency_injector/wiring.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
Type,
2626
TypeVar,
2727
Union,
28+
assert_never,
2829
cast,
2930
)
3031
from warnings import warn
@@ -791,6 +792,9 @@ def modify(
791792
) -> providers.Provider:
792793
return provider.as_(self.type_)
793794

795+
def __repr__(self) -> str:
796+
return f"{self.__class__.__name__}({self.type_!r})"
797+
794798

795799
def as_int() -> TypeModifier:
796800
"""Return int type modifier."""
@@ -809,8 +813,8 @@ def as_(type_: Type) -> TypeModifier:
809813

810814
class RequiredModifier(Modifier):
811815

812-
def __init__(self) -> None:
813-
self.type_modifier = None
816+
def __init__(self, type_modifier: Optional[TypeModifier] = None) -> None:
817+
self.type_modifier = type_modifier
814818

815819
def as_int(self) -> Self:
816820
self.type_modifier = TypeModifier(int)
@@ -834,6 +838,11 @@ def modify(
834838
provider = provider.as_(self.type_modifier.type_)
835839
return provider
836840

841+
def __repr__(self) -> str:
842+
if self.type_modifier:
843+
return f"{self.__class__.__name__}({self.type_modifier!r})"
844+
return f"{self.__class__.__name__}()"
845+
837846

838847
def required() -> RequiredModifier:
839848
"""Return required modifier."""
@@ -853,6 +862,9 @@ def modify(
853862
invariant_segment = providers_map.resolve_provider(self.id)
854863
return provider[invariant_segment]
855864

865+
def __repr__(self) -> str:
866+
return f"{self.__class__.__name__}({self.id!r})"
867+
856868

857869
def invariant(id: str) -> InvariantModifier:
858870
"""Return invariant modifier."""
@@ -893,8 +905,28 @@ def modify(
893905
provider = provider[value]
894906
elif type_ == ProvidedInstance.TYPE_CALL:
895907
provider = provider.call()
908+
else:
909+
assert_never(type_)
896910
return provider
897911

912+
def _format_segments(self) -> str:
913+
segments = []
914+
for type_, value in self.segments:
915+
if type_ == ProvidedInstance.TYPE_ATTRIBUTE:
916+
segments.append(f".{value}")
917+
elif type_ == ProvidedInstance.TYPE_ITEM:
918+
segments.append(f"[{value!r}]")
919+
elif type_ == ProvidedInstance.TYPE_CALL:
920+
segments.append(".call()")
921+
else:
922+
assert_never(type_)
923+
return "".join(segments)
924+
925+
__str__ = _format_segments
926+
927+
def __repr__(self) -> str:
928+
return f"{self.__class__.__name__}(){self._format_segments()}"
929+
898930

899931
def provided() -> ProvidedInstance:
900932
"""Return provided instance modifier."""
@@ -910,14 +942,15 @@ def provided() -> ProvidedInstance:
910942
]
911943

912944

913-
if TYPE_CHECKING:
945+
if TYPE_CHECKING: # noqa
914946

915947
class _Marker(Protocol):
916948
__IS_MARKER__: bool
917949

918950
def __call__(self) -> Self: ...
919951
def __getattr__(self, item: str) -> Self: ...
920952
def __getitem__(self, item: Any) -> Any: ...
953+
def __repr__(self) -> str: ...
921954

922955
Provide: _Marker
923956
Provider: _Marker
@@ -946,6 +979,12 @@ def __class_getitem__(cls, item: MarkerItem) -> Self:
946979
def __call__(self) -> Self:
947980
return self
948981

982+
def __repr__(self) -> str:
983+
cls_name = self.__class__.__name__
984+
if self.modifier:
985+
return f"{cls_name}[{self.provider!r}, {self.modifier!r}]"
986+
return f"{cls_name}[{self.provider!r}]"
987+
949988
class Provide(_Marker): ...
950989

951990
class Provider(_Marker): ...

tests/unit/wiring/provider_ids/test_main_py36.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Main wiring tests."""
22

3+
import re
34
from decimal import Decimal
45

56
from dependency_injector import errors
@@ -67,7 +68,7 @@ def test_module_attributes_wiring():
6768

6869
def test_module_attribute_wiring_with_invalid_marker(container: Container):
6970
from samples.wiring import module_invalid_attr_injection
70-
with raises(Exception, match="Unknown type of marker {0}".format(module_invalid_attr_injection.service)):
71+
with raises(Exception, match=re.escape("Unknown type of marker {0}".format(module_invalid_attr_injection.service))):
7172
container.wire(modules=[module_invalid_attr_injection])
7273

7374

tests/unit/wiring/string_ids/test_main_py36.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Main wiring tests."""
22

3+
import re
34
from decimal import Decimal
45

56
from pytest import fixture, mark, raises
@@ -68,7 +69,7 @@ def test_module_attributes_wiring():
6869

6970
def test_module_attribute_wiring_with_invalid_marker(container: Container):
7071
from samples.wiringstringids import module_invalid_attr_injection
71-
with raises(Exception, match="Unknown type of marker {0}".format(module_invalid_attr_injection.service)):
72+
with raises(Exception, match=re.escape("Unknown type of marker {0}".format(module_invalid_attr_injection.service))):
7273
container.wire(modules=[module_invalid_attr_injection])
7374

7475

tests/unit/wiring/test_reprs.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from dependency_injector.wiring import (
2+
Closing,
3+
InvariantModifier,
4+
Provide,
5+
ProvidedInstance,
6+
RequiredModifier,
7+
TypeModifier,
8+
)
9+
10+
11+
def test_type_modifier_repr() -> None:
12+
assert repr(TypeModifier(int)) == f"TypeModifier({int!r})"
13+
14+
15+
def test_required_modifier_repr() -> None:
16+
assert repr(RequiredModifier()) == "RequiredModifier()"
17+
18+
19+
def test_required_modifier_with_type_repr() -> None:
20+
type_modifier = TypeModifier(int)
21+
required_modifier = RequiredModifier(type_modifier)
22+
assert repr(required_modifier) == f"RequiredModifier({type_modifier!r})"
23+
24+
25+
def test_invariant_modifier_repr() -> None:
26+
assert repr(InvariantModifier("test")) == "InvariantModifier('test')"
27+
28+
29+
def test_provided_instance_repr() -> None:
30+
provided_instance = ProvidedInstance().test["attr"].call()
31+
32+
assert repr(provided_instance) == "ProvidedInstance().test['attr'].call()"
33+
34+
35+
def test_marker_repr() -> None:
36+
assert repr(Closing[Provide["test"]]) == "Closing[Provide['test']]"
37+
38+
39+
def test_marker_with_modifier_repr() -> None:
40+
marker = Provide["test", RequiredModifier()]
41+
42+
assert repr(marker) == "Provide['test', RequiredModifier()]"

0 commit comments

Comments
 (0)