hmr 0.4.1.1__py3-none-any.whl → 0.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hmr
3
- Version: 0.4.1.1
3
+ Version: 0.4.2
4
4
  Summary: Hot Module Reload for Python
5
5
  Project-URL: repository, https://github.com/promplate/pyth-on-line/tree/reactivity
6
6
  Requires-Python: >=3.12
@@ -1,14 +1,14 @@
1
- hmr-0.4.1.1.dist-info/METADATA,sha256=AZJ6lFoPbTauSV8qwcFBBjMULXEErXov3sU9e13l-cQ,260
2
- hmr-0.4.1.1.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
- hmr-0.4.1.1.dist-info/entry_points.txt,sha256=g_T0uJ43WgsdG14kkkdaBQuIL0HO-m1qvtjXMP6d060,59
1
+ hmr-0.4.2.dist-info/METADATA,sha256=0dGqIVXUA-EX7VuNsQSOLtOvX5aKy-noYyrRLZpSwkc,258
2
+ hmr-0.4.2.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
+ hmr-0.4.2.dist-info/entry_points.txt,sha256=g_T0uJ43WgsdG14kkkdaBQuIL0HO-m1qvtjXMP6d060,59
4
4
  reactivity/__init__.py,sha256=pX-RUzkezCC1x4eOWGxNhXbwrbvBLP_3pQuZr9eZz1Y,300
5
5
  reactivity/functional.py,sha256=U06vshcVhZ0sb218gcmHtEhfgTNAGtQ7zyvPz2w5qKM,1292
6
6
  reactivity/helpers.py,sha256=1KCpre2HTFZrngEKkI2HwSFMkCmsUCq2aPEbp0y3kKg,5140
7
7
  reactivity/hmr/__init__.py,sha256=S5ZIHqCRpevdzWuhS0aCua_S8F0LkK0YNg6IgeTScFQ,177
8
8
  reactivity/hmr/__main__.py,sha256=uIcyjR5gMFIXH_3hS0B3SD00RirVf7GIct-uItx675o,64
9
9
  reactivity/hmr/api.py,sha256=Esb1fYiBW0SLxQ0MPXby25ZgIIZhIp-M3b2KiqpffmU,2094
10
- reactivity/hmr/core.py,sha256=S6sqMkMKdc6DSNt6I9ZZWbR6bH_069MQ-eBUU_4qdDY,11584
10
+ reactivity/hmr/core.py,sha256=x71UilKjeH-HH72ta_u46tnRV3Fb28KXqoqtGdGabko,12250
11
11
  reactivity/hmr/hooks.py,sha256=jIFpe4CNxfaS9RcR4OIodx_sOZlnJ_IA1T1RtHPXhwU,945
12
12
  reactivity/hmr/utils.py,sha256=-PO-LMP4sc3IP-Bn_baq2w9IFWBZ3zGesgRn5wR6bS0,1555
13
13
  reactivity/primitives.py,sha256=mB6cbHKDqtilOfgaEhshtRWJq9s0nPEKqRK0hfCoyFE,5671
14
- hmr-0.4.1.1.dist-info/RECORD,,
14
+ hmr-0.4.2.dist-info/RECORD,,
reactivity/hmr/core.py CHANGED
@@ -15,7 +15,7 @@ from weakref import WeakValueDictionary
15
15
  from .. import Reactive, batch
16
16
  from ..functional import create_effect
17
17
  from ..helpers import DerivedMethod
18
- from ..primitives import BaseDerived, Derived, Signal
18
+ from ..primitives import BaseComputation, BaseDerived, Derived, Signal
19
19
  from .hooks import call_post_reload_hooks, call_pre_reload_hooks
20
20
 
21
21
 
@@ -33,8 +33,7 @@ def is_called_in_this_file() -> bool:
33
33
 
34
34
 
35
35
  class Name(Signal, BaseDerived):
36
- def __init__(self, initial_value):
37
- super().__init__(initial_value)
36
+ pass
38
37
 
39
38
 
40
39
  class NamespaceProxy(Reactive[str, Any]):
@@ -44,7 +43,7 @@ class NamespaceProxy(Reactive[str, Any]):
44
43
  self.module = module
45
44
 
46
45
  def _null(self):
47
- self.module.load.subscribers.add(signal := Name(self.UNSET))
46
+ self.module.load.subscribers.add(signal := Name(self.UNSET, self._check_equality))
48
47
  signal.dependencies.add(self.module.load)
49
48
  return signal
50
49
 
@@ -97,12 +96,24 @@ class ReactiveModule(ModuleType):
97
96
  else:
98
97
  exec(code, self.__namespace, self.__namespace_proxy)
99
98
  finally:
100
- for dep in list((load := self.__load).dependencies):
101
- assert ismethod(load.fn) # for type narrowing
99
+ load = self.__load
100
+ assert ismethod(load.fn) # for type narrowing
101
+ for dep in list(load.dependencies):
102
102
  if isinstance(dep, Derived) and ismethod(dep.fn) and isinstance(dep.fn.__self__, ReactiveModule) and dep.fn.__func__ is load.fn.__func__:
103
103
  # unsubscribe it because we want invalidation to be fine-grained
104
104
  dep.subscribers.remove(load)
105
105
  load.dependencies.remove(dep)
106
+ elif isinstance(dep, BaseComputation):
107
+ visited = set() # cache visited nodes, maybe share cache between iteration too (?)
108
+ to_visit: set[BaseComputation] = {dep}
109
+ while to_visit and (current := to_visit.pop()) not in visited:
110
+ visited.add(current)
111
+ if load in current.dependencies:
112
+ # unsubscribe it to avoid circular dependencies
113
+ dep.subscribers.remove(load)
114
+ load.dependencies.remove(dep)
115
+ break
116
+ to_visit.update(i for i in current.dependencies if isinstance(i, BaseComputation))
106
117
 
107
118
  @property
108
119
  def load(self):
@@ -133,14 +144,13 @@ class ReactiveModule(ModuleType):
133
144
 
134
145
 
135
146
  class ReactiveModuleLoader(Loader):
136
- def __init__(self, file: Path, is_package=False):
147
+ def __init__(self, file: Path):
137
148
  super().__init__()
138
149
  self._file = file
139
- self._is_package = is_package
140
150
 
141
151
  def create_module(self, spec: ModuleSpec):
142
152
  namespace = {"__file__": str(self._file), "__spec__": spec, "__loader__": self, "__name__": spec.name}
143
- if self._is_package:
153
+ if spec.submodule_search_locations is not None:
144
154
  assert self._file.name == "__init__.py"
145
155
  namespace["__path__"] = [str(self._file.parent)]
146
156
  return ReactiveModule(self._file, namespace, spec.name)
@@ -173,7 +183,7 @@ class ReactiveModuleFinder(MetaPathFinder):
173
183
  return spec_from_loader(fullname, ReactiveModuleLoader(file), origin=str(file))
174
184
  file = directory / f"{fullname.replace('.', '/')}/__init__.py"
175
185
  if self._accept(file) and (paths is None or is_relative_to_any(file, paths)):
176
- return spec_from_loader(fullname, ReactiveModuleLoader(file, is_package=True), origin=str(file), is_package=True)
186
+ return spec_from_loader(fullname, ReactiveModuleLoader(file), origin=str(file), is_package=True)
177
187
 
178
188
 
179
189
  def is_relative_to_any(path: Path, paths: Iterable[str | Path]):
@@ -339,4 +349,4 @@ def cli():
339
349
  SyncReloader(entry).keep_watching_until_interrupt()
340
350
 
341
351
 
342
- __version__ = "0.4.1.1"
352
+ __version__ = "0.4.2"
File without changes