hmr 0.0.3.2__tar.gz → 0.1.1__tar.gz

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.0.3.2
3
+ Version: 0.1.1
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
@@ -6,7 +6,7 @@ description = "Hot Module Reload for Python"
6
6
  dependencies = [
7
7
  "watchfiles>=0.21,<2",
8
8
  ]
9
- version = "0.0.3.2"
9
+ version = "0.1.1"
10
10
 
11
11
  [project.scripts]
12
12
  hmr = "reactivity.hmr:cli"
@@ -11,7 +11,7 @@ from runpy import run_path
11
11
  from types import ModuleType
12
12
  from typing import Any
13
13
 
14
- from . import Reactive, batch, create_effect, memoized_method
14
+ from . import Reactive, batch, memoized_method
15
15
 
16
16
 
17
17
  def is_called_in_this_file() -> bool:
@@ -58,6 +58,7 @@ class ReactiveModule(ModuleType):
58
58
  return self.__file
59
59
  raise AttributeError("file")
60
60
 
61
+ @memoized_method
61
62
  def __load(self):
62
63
  code = compile(self.__file.read_text("utf-8"), str(self.__file), "exec", dont_inherit=True)
63
64
  exec(code, self.__namespace, self.__namespace_proxy)
@@ -103,7 +104,7 @@ class ReactiveModuleLoader(Loader):
103
104
 
104
105
  def exec_module(self, module: ModuleType):
105
106
  assert isinstance(module, ReactiveModule)
106
- create_effect(lambda: module.load())
107
+ module.load()
107
108
 
108
109
 
109
110
  class ReactiveModuleFinder(MetaPathFinder):
@@ -112,27 +113,30 @@ class ReactiveModuleFinder(MetaPathFinder):
112
113
  self.includes = [Path(i).resolve() for i in includes]
113
114
  self.excludes = [Path(e).resolve() for e in excludes]
114
115
 
116
+ def _accept(self, path: Path):
117
+ return path.is_file() and not is_relative_to_any(path, self.excludes) and is_relative_to_any(path, self.includes)
118
+
115
119
  def find_spec(self, fullname: str, paths: Sequence[str] | None, _=None):
116
120
  if fullname in sys.modules:
117
121
  return None
118
122
 
119
- for p in paths or sys.path:
123
+ for p in sys.path:
120
124
  directory = Path(p).resolve()
121
125
  if directory.is_file():
122
126
  continue
123
- if any(directory.is_relative_to(exclude) for exclude in self.excludes):
124
- continue
125
- if all(not directory.is_relative_to(include) for include in self.includes):
126
- continue
127
127
 
128
128
  file = directory / f"{fullname.replace('.', '/')}.py"
129
- if file.is_file() and all(not file.is_relative_to(exclude) for exclude in self.excludes):
129
+ if self._accept(file) and (paths is None or is_relative_to_any(file, paths)):
130
130
  return spec_from_loader(fullname, ReactiveModuleLoader(file), origin=str(file))
131
131
  file = directory / f"{fullname.replace('.', '/')}/__init__.py"
132
- if file.is_file() and all(not file.is_relative_to(exclude) for exclude in self.excludes):
132
+ if self._accept(file) and (paths is None or is_relative_to_any(file, paths)):
133
133
  return spec_from_loader(fullname, ReactiveModuleLoader(file, is_package=True), origin=str(file), is_package=True)
134
134
 
135
135
 
136
+ def is_relative_to_any(path: Path, paths: Iterable[str | Path]):
137
+ return any(path.is_relative_to(p) for p in paths)
138
+
139
+
136
140
  def patch_module(name_or_module: str | ModuleType):
137
141
  name = name_or_module if isinstance(name_or_module, str) else name_or_module.__name__
138
142
  module = sys.modules[name_or_module] if isinstance(name_or_module, str) else name_or_module
@@ -155,11 +159,12 @@ class BaseReloader:
155
159
  self.includes = includes
156
160
  self.excludes = excludes
157
161
  patch_meta_path(includes, excludes)
162
+ self.last_globals = {}
158
163
 
159
164
  @memoized_method
160
165
  def run_entry_file(self):
161
166
  try:
162
- run_path(self.entry, run_name="__main__")
167
+ self.last_globals = run_path(self.entry, self.last_globals, "__main__")
163
168
  except Exception as e:
164
169
  sys.excepthook(e.__class__, e, e.__traceback__)
165
170
 
@@ -182,12 +187,18 @@ class BaseReloader:
182
187
  if type is Change.modified:
183
188
  path = Path(file).resolve()
184
189
  if path.samefile(self.entry):
185
- self.run_entry_file.trigger()
190
+ self.run_entry_file.invalidate()
186
191
  elif module := path2module.get(path):
187
192
  try:
188
- module.load()
193
+ module.load.invalidate()
189
194
  except Exception as e:
190
195
  sys.excepthook(e.__class__, e, e.__traceback__)
196
+
197
+ for module in path2module.values():
198
+ try:
199
+ module.load()
200
+ except Exception as e:
201
+ sys.excepthook(e.__class__, e, e.__traceback__)
191
202
  self.run_entry_file()
192
203
 
193
204
 
@@ -249,4 +260,4 @@ def cli():
249
260
  SyncReloader(entry, excludes={".venv"}).keep_watching_until_interrupt()
250
261
 
251
262
 
252
- __version__ = "0.0.3.2"
263
+ __version__ = "0.1.1"
File without changes
File without changes
File without changes
File without changes