hmr 0.1.2__py3-none-any.whl → 0.2.0__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,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hmr
3
- Version: 0.1.2
3
+ Version: 0.2.0
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
7
- Requires-Dist: watchfiles<2,>=0.21
7
+ Requires-Dist: watchfiles<2,>=0.21; sys_platform != "emscripten"
8
8
 
@@ -0,0 +1,9 @@
1
+ hmr-0.2.0.dist-info/METADATA,sha256=EOVgm-SYoDvhCdf7X3stdnfoOwt4JiJz4dU-MH5qp4A,258
2
+ hmr-0.2.0.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
+ hmr-0.2.0.dist-info/entry_points.txt,sha256=g_T0uJ43WgsdG14kkkdaBQuIL0HO-m1qvtjXMP6d060,59
4
+ reactivity/__init__.py,sha256=pX-RUzkezCC1x4eOWGxNhXbwrbvBLP_3pQuZr9eZz1Y,300
5
+ reactivity/functional.py,sha256=U06vshcVhZ0sb218gcmHtEhfgTNAGtQ7zyvPz2w5qKM,1292
6
+ reactivity/helpers.py,sha256=7gwsIKKrjEahSz9G9oR4s1LdYXQTCIMO0k4UGXGla9Y,3714
7
+ reactivity/hmr.py,sha256=CeJSXPeDA-wc_tE_JC0gXfFgeaGsCEvmVbbsCYJtGok,9603
8
+ reactivity/primitives.py,sha256=DR2waJbzhVKOioHXMliE4FIsxQUq7DZA0umPrlvchA4,4217
9
+ hmr-0.2.0.dist-info/RECORD,,
reactivity/helpers.py CHANGED
@@ -13,32 +13,29 @@ class Memoized[T](Subscribable, BaseComputation[T]):
13
13
  self.fn = fn
14
14
  self.is_stale = True
15
15
  self.cached_value: T
16
- self._recompute = False
16
+
17
+ def recompute(self):
18
+ self._before()
19
+ try:
20
+ self.cached_value = self.fn()
21
+ self.is_stale = False
22
+ finally:
23
+ self._after()
17
24
 
18
25
  def trigger(self):
19
- self.track()
20
- if self._recompute:
21
- self._recompute = False
22
- self._before()
23
- try:
24
- self.cached_value = self.fn()
25
- self.is_stale = False
26
- finally:
27
- self._after()
28
- else:
29
- self.invalidate()
26
+ self.invalidate()
30
27
 
31
28
  def __call__(self):
29
+ self.track()
32
30
  if self.is_stale:
33
- self._recompute = True
34
- self.trigger()
35
- assert not self._recompute
31
+ self.recompute()
36
32
  return self.cached_value
37
33
 
38
34
  def invalidate(self):
39
35
  if not self.is_stale:
40
36
  del self.cached_value
41
37
  self.is_stale = True
38
+ self.notify()
42
39
 
43
40
 
44
41
  class MemoizedProperty[T, I]:
reactivity/hmr.py CHANGED
@@ -278,9 +278,10 @@ def cli():
278
278
  print("\n Usage: hmr <entry file>, just like python <entry file>\n")
279
279
  exit(1)
280
280
  entry = sys.argv[-1]
281
- assert Path(entry).is_file(), f"{entry} is not a file"
281
+ if not (path := Path(entry)).is_file():
282
+ raise FileNotFoundError(path.resolve())
282
283
  sys.path.insert(0, ".")
283
284
  SyncReloader(entry, excludes={".venv"}).keep_watching_until_interrupt()
284
285
 
285
286
 
286
- __version__ = "0.1.2"
287
+ __version__ = "0.2.0"
reactivity/primitives.py CHANGED
@@ -1,4 +1,4 @@
1
- from collections.abc import Callable
1
+ from collections.abc import Callable, Iterable
2
2
  from typing import Any, Self, overload
3
3
  from weakref import WeakKeyDictionary, WeakSet
4
4
 
@@ -9,17 +9,19 @@ class Subscribable:
9
9
  self.subscribers = set[BaseComputation]()
10
10
 
11
11
  def track(self):
12
- for computation in _current_computations:
13
- if computation is not self:
14
- self.subscribers.add(computation)
15
- computation.dependencies.add(self)
12
+ if not _current_computations:
13
+ return
14
+ last = _current_computations[-1]
15
+ if last is not self:
16
+ self.subscribers.add(last)
17
+ last.dependencies.add(self)
16
18
 
17
19
  def notify(self):
18
20
  if _batches:
19
- _batches[-1].callbacks.extend(self.subscribers)
21
+ schedule_callbacks(self.subscribers)
20
22
  else:
21
- for subscriber in {*self.subscribers}:
22
- subscriber.trigger()
23
+ with Batch(force_flush=False):
24
+ schedule_callbacks(self.subscribers)
23
25
 
24
26
 
25
27
  class BaseComputation[T]:
@@ -46,9 +48,9 @@ class BaseComputation[T]:
46
48
  def __exit__(self, *_):
47
49
  self.dispose()
48
50
 
49
- def trigger(self) -> T: ...
51
+ def trigger(self) -> Any: ...
50
52
 
51
- def __call__(self):
53
+ def __call__(self) -> T:
52
54
  return self.trigger()
53
55
 
54
56
 
@@ -119,22 +121,38 @@ class Effect[T](BaseComputation[T]):
119
121
 
120
122
 
121
123
  class Batch:
122
- def __init__(self):
123
- self.callbacks: list[BaseComputation] = []
124
+ def __init__(self, force_flush=True):
125
+ self.callbacks = set[BaseComputation]()
126
+ self.force_flush = force_flush
124
127
 
125
128
  def flush(self):
126
- callbacks = set(self.callbacks)
127
- self.callbacks.clear()
128
- for computation in callbacks:
129
- computation.trigger()
129
+ triggered = set()
130
+ while self.callbacks:
131
+ callbacks = self.callbacks - triggered
132
+ self.callbacks.clear()
133
+ for computation in callbacks:
134
+ if computation in self.callbacks:
135
+ continue # skip if re-added during callback
136
+ computation.trigger()
137
+ triggered.add(computation)
130
138
 
131
139
  def __enter__(self):
132
140
  _batches.append(self)
133
141
 
134
142
  def __exit__(self, *_):
135
- last = _batches.pop()
143
+ if self.force_flush or len(_batches) == 1:
144
+ try:
145
+ self.flush()
146
+ finally:
147
+ last = _batches.pop()
148
+ else:
149
+ last = _batches.pop()
150
+ schedule_callbacks(self.callbacks)
136
151
  assert last is self
137
- self.flush()
138
152
 
139
153
 
140
154
  _batches: list[Batch] = []
155
+
156
+
157
+ def schedule_callbacks(callbacks: Iterable[BaseComputation]):
158
+ _batches[-1].callbacks.update(callbacks)
@@ -1,9 +0,0 @@
1
- hmr-0.1.2.dist-info/METADATA,sha256=tHSOaU8XTf-WF85Hg7r6Fimk-g6WZZa3jJeurid7yno,228
2
- hmr-0.1.2.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
- hmr-0.1.2.dist-info/entry_points.txt,sha256=g_T0uJ43WgsdG14kkkdaBQuIL0HO-m1qvtjXMP6d060,59
4
- reactivity/__init__.py,sha256=pX-RUzkezCC1x4eOWGxNhXbwrbvBLP_3pQuZr9eZz1Y,300
5
- reactivity/functional.py,sha256=U06vshcVhZ0sb218gcmHtEhfgTNAGtQ7zyvPz2w5qKM,1292
6
- reactivity/helpers.py,sha256=1KmMCO6lqluHlMsjGQQ9UJZBtbFppjFZnmi9RhowRHo,3872
7
- reactivity/hmr.py,sha256=lUqHeB_5LlrHMUSWXRvSRGoaMkFAm3ONQNxm5OCk0Uw,9570
8
- reactivity/primitives.py,sha256=lw4G3GpANRGK5dKw11eYc2-nlOJ1uCO3f3MiLa41jG8,3588
9
- hmr-0.1.2.dist-info/RECORD,,
File without changes