hmr 0.4.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
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.dist-info/METADATA,sha256=Zx1F2ZUK7Els9nM6w76ceL693CD7JAPUvf7uBVUS2LQ,258
2
- hmr-0.4.1.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
- hmr-0.4.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=HxPngNSKcw5OrIiokqJtbUfAw2Fph-1G3ToJIDP4Pf4,11677
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.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):
@@ -122,8 +133,7 @@ class ReactiveModule(ModuleType):
122
133
  try:
123
134
  return self.__namespace_proxy[name]
124
135
  except KeyError as e:
125
- caller = currentframe().f_back.f_globals["__name__"] # type: ignore
126
- if caller != "importlib._bootstrap" and (getattr := self.__namespace_proxy.get("__getattr__")):
136
+ if name != "__path__" and (getattr := self.__namespace_proxy.get("__getattr__")):
127
137
  return getattr(name)
128
138
  raise AttributeError(*e.args) from e
129
139
 
@@ -134,14 +144,13 @@ class ReactiveModule(ModuleType):
134
144
 
135
145
 
136
146
  class ReactiveModuleLoader(Loader):
137
- def __init__(self, file: Path, is_package=False):
147
+ def __init__(self, file: Path):
138
148
  super().__init__()
139
149
  self._file = file
140
- self._is_package = is_package
141
150
 
142
151
  def create_module(self, spec: ModuleSpec):
143
152
  namespace = {"__file__": str(self._file), "__spec__": spec, "__loader__": self, "__name__": spec.name}
144
- if self._is_package:
153
+ if spec.submodule_search_locations is not None:
145
154
  assert self._file.name == "__init__.py"
146
155
  namespace["__path__"] = [str(self._file.parent)]
147
156
  return ReactiveModule(self._file, namespace, spec.name)
@@ -174,7 +183,7 @@ class ReactiveModuleFinder(MetaPathFinder):
174
183
  return spec_from_loader(fullname, ReactiveModuleLoader(file), origin=str(file))
175
184
  file = directory / f"{fullname.replace('.', '/')}/__init__.py"
176
185
  if self._accept(file) and (paths is None or is_relative_to_any(file, paths)):
177
- 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)
178
187
 
179
188
 
180
189
  def is_relative_to_any(path: Path, paths: Iterable[str | Path]):
@@ -340,4 +349,4 @@ def cli():
340
349
  SyncReloader(entry).keep_watching_until_interrupt()
341
350
 
342
351
 
343
- __version__ = "0.4.1"
352
+ __version__ = "0.4.2"
File without changes