Skip to content

Commit ab2ead2

Browse files
authored
refactoring: ♻️ ModuleEventProxy
1 parent 0ccda57 commit ab2ead2

File tree

4 files changed

+33
-83
lines changed

4 files changed

+33
-83
lines changed

injection/common/lazy.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
from functools import partial
2-
from types import new_class
1+
from types import MappingProxyType, new_class
32
from typing import Any, Callable, Generic, Iterator, Mapping, TypeVar
43

5-
from frozendict import frozendict
6-
74
__all__ = ("Lazy", "LazyMapping")
85

96
_sentinel = new_class("sentinel")()
@@ -22,7 +19,7 @@ def __init__(self, factory: Callable[[], T]):
2219

2320
def __setattr__(self, name: str, value: Any):
2421
if self.is_set:
25-
raise TypeError(f"`{repr(self)}` is frozen.")
22+
raise TypeError(f"`{self}` is frozen.")
2623

2724
return super().__setattr__(name, value)
2825

@@ -47,11 +44,10 @@ def is_set(self) -> bool:
4744
class LazyMapping(Mapping[K, V]):
4845
__slots__ = ("__lazy",)
4946

50-
__lazy: Lazy[frozendict[K, V]]
47+
__lazy: Lazy[MappingProxyType[K, V]]
5148

5249
def __init__(self, iterator: Iterator[tuple[K, V]]):
53-
factory = partial(frozendict, iterator)
54-
self.__lazy = Lazy(factory)
50+
self.__lazy = Lazy(lambda: MappingProxyType(dict(iterator)))
5551

5652
def __getitem__(self, key: K) -> V:
5753
return self.__lazy.value[key]

injection/core/module.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -84,29 +84,37 @@ class ModuleEventProxy(ModuleEvent):
8484
def __str__(self) -> str:
8585
return f"`{self.on_module}` has propagated an event: {self.origin}"
8686

87-
def __iter__(self) -> Iterator[Event]:
87+
@property
88+
def history(self) -> Iterator[Event]:
8889
if isinstance(self.event, ModuleEventProxy):
89-
yield from self.event
90+
yield from self.event.history
9091

9192
yield self.event
9293

9394
@property
9495
def origin(self) -> Event:
95-
return next(iter(self))
96+
return next(self.history)
9697

97-
@property
98-
def is_circular(self) -> bool:
99-
return any(
100-
isinstance(event, ModuleEvent) and event.on_module is self.on_module
101-
for event in self
102-
)
98+
def check_recursion(self):
99+
last_module = None
100+
found = False
103101

104-
@property
105-
def previous_module(self) -> Module | None:
106-
if isinstance(self.event, ModuleEvent):
107-
return self.event.on_module
102+
for event in self.history:
103+
if not isinstance(event, ModuleEvent):
104+
continue
108105

109-
return None
106+
last_module = event.on_module
107+
108+
if found is False:
109+
found = last_module is self.on_module
110+
111+
if found:
112+
raise ModuleCircularUseError(
113+
"Circular dependency between two modules: "
114+
f"`{self.on_module}` and `{last_module}`."
115+
)
116+
117+
return self
110118

111119

112120
@dataclass(frozen=True, slots=True)
@@ -390,14 +398,7 @@ def remove_listener(self, listener: EventListener):
390398
return self
391399

392400
def on_event(self, event: Event, /):
393-
self_event = ModuleEventProxy(self, event)
394-
395-
if self_event.is_circular:
396-
raise ModuleCircularUseError(
397-
"Circular dependency between two modules: "
398-
f"`{self_event.previous_module}` and `{self}`."
399-
)
400-
401+
self_event = ModuleEventProxy(self, event).check_recursion()
401402
self.notify(self_event)
402403

403404
def notify(self, event: Event):

poetry.lock

Lines changed: 6 additions & 52 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ repository = "https://github.com/simplysquare/python-injection"
1111

1212
[tool.poetry.dependencies]
1313
python = ">=3.10, <4"
14-
frozendict = "*"
1514

1615
[tool.poetry.group.dev.dependencies]
1716
black = "*"

0 commit comments

Comments
 (0)