tempestweb 0.3.0__tar.gz → 0.4.0__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.
- {tempestweb-0.3.0 → tempestweb-0.4.0}/CHANGELOG.md +16 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/PKG-INFO +1 -1
- {tempestweb-0.3.0 → tempestweb-0.4.0}/pyproject.toml +1 -1
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/cli/commands/build.py +85 -6
- {tempestweb-0.3.0 → tempestweb-0.4.0}/.gitignore +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/README.md +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/constants.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/dom.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/events.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/livereload.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/audio.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/camera.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/clipboard.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/file.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/geolocation.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/http.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/index.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/install.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/notifications.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/onnx.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/share.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/native/storage.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/offline/store.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/offline/sync.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/push/web-push-client.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/pwa/install-prompt.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/pwa/manifest.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/router.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/style.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/sw/register.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/sw/sw.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/tempestweb.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/transport-sse.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/transport-wasm.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/transport-ws.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/transport.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/client/virtualize.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/_core/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/cli/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/cli/commands/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/cli/commands/dev.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/cli/commands/new.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/cli/commands/run.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/cli/config.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/cli/loader.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/cli/main.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/cli/scaffold.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/components/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/components/fields.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/components/forms.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/core/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/core/constants.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/devserver/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/devserver/http.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/devserver/reload.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/devserver/watcher.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/audio.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/bridges.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/camera.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/clipboard.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/dispatch.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/file.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/geolocation.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/http.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/install.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/notifications.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/onnx.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/share.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/native/storage.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/observability/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/observability/auth.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/observability/error_boundary.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/observability/feature_flags.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/observability/logger.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/observability/telemetry.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/pwa/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/pwa/icons.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/pwa/manifest.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/pwa/pyodide_vendor.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/runtime/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/runtime/events.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/runtime/serialize.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/runtime/session.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/runtime/wasm.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/runtime/wasm_main.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/server/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/server/app.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/server/webpush.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/transports/__init__.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/transports/base.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/transports/sse.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/transports/wasm.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tempestweb/transports/websocket.py +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/dom.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/events.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/mount.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/native-onnx-file.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/native.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/offline-store.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/offline-sync.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/pwa-install-prompt.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/pwa-manifest.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/router.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/setup.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/smoke.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/style.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/sw-register.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/sw-strategies.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/transport-sse.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/transport-wasm.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/transport-ws.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/virtualize.test.js +0 -0
- {tempestweb-0.3.0 → tempestweb-0.4.0}/tests/client/web-push-client.test.js +0 -0
|
@@ -4,6 +4,22 @@ All notable changes to **tempestweb** are documented here. Format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/); this project adheres to semantic
|
|
5
5
|
versioning.
|
|
6
6
|
|
|
7
|
+
## [0.4.0] — 2026-06-13
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **`[wasm].modules` resolves from the installed environment** — each entry is now
|
|
12
|
+
resolved in two steps: a vendored copy beside `app.py`
|
|
13
|
+
(`<project>/<module>/`) still wins, but when none exists the module is pulled
|
|
14
|
+
straight from the project's `.venv` `site-packages` via `importlib`. A
|
|
15
|
+
dependency you `uv add` no longer has to be cloned and committed at the repo
|
|
16
|
+
root to make it into the wasm bundle — just list it in `modules`. A name that is
|
|
17
|
+
neither vendored nor importable fails the build with a clear message.
|
|
18
|
+
Backward compatible: existing vendored layouts build unchanged. A stale project
|
|
19
|
+
directory holding only `__pycache__` (real source deleted, bytecode lingering)
|
|
20
|
+
no longer shadows the installed package and silently bundles nothing — it falls
|
|
21
|
+
through to the installed copy.
|
|
22
|
+
|
|
7
23
|
## [0.3.0] — 2026-06-13
|
|
8
24
|
|
|
9
25
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tempestweb
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Build web apps in typed Python — one tree, a DOM renderer, two execution modes (WASM + server).
|
|
5
5
|
Author-email: Mauricio Benjamin <mauricio.benjamin@reloverelations.com>
|
|
6
6
|
License: MIT
|
|
@@ -23,6 +23,7 @@ WebSocket transport — ``python server.py`` (or ``uvicorn server:app``) serves
|
|
|
23
23
|
from __future__ import annotations
|
|
24
24
|
|
|
25
25
|
import hashlib
|
|
26
|
+
import importlib.util
|
|
26
27
|
import json
|
|
27
28
|
import shutil
|
|
28
29
|
import zipfile
|
|
@@ -236,6 +237,80 @@ def _zip_tree(
|
|
|
236
237
|
archive.write(path, str(path.relative_to(root)))
|
|
237
238
|
|
|
238
239
|
|
|
240
|
+
def _is_vendored(candidate: Path) -> bool:
|
|
241
|
+
"""Tell whether ``candidate`` is a usable vendored module/package.
|
|
242
|
+
|
|
243
|
+
A single file counts. A directory counts only if it holds at least one
|
|
244
|
+
bundlable file (anything outside ``__pycache__``) — so a stale directory
|
|
245
|
+
left holding only ``__pycache__`` after the real source was deleted does
|
|
246
|
+
**not** shadow the installed package and silently bundle nothing.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
candidate: The ``project_root/module`` path to test.
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
``True`` if the path is a file or a directory with real content.
|
|
253
|
+
"""
|
|
254
|
+
if candidate.is_file():
|
|
255
|
+
return True
|
|
256
|
+
if not candidate.is_dir():
|
|
257
|
+
return False
|
|
258
|
+
return any(
|
|
259
|
+
path.is_file() and "__pycache__" not in path.parts
|
|
260
|
+
for path in candidate.rglob("*")
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def _resolve_module(module: str, project_root: Path | None) -> tuple[Path, str]:
|
|
265
|
+
"""Resolve a ``[wasm].modules`` entry to its ``(root, top)`` for bundling.
|
|
266
|
+
|
|
267
|
+
Resolution order:
|
|
268
|
+
|
|
269
|
+
1. A **vendored copy** under ``project_root`` (``project_root/module``) that
|
|
270
|
+
carries real content — preserves the historical behavior where a copy
|
|
271
|
+
sitting beside ``app.py`` wins. A stale directory holding only
|
|
272
|
+
``__pycache__`` is skipped (see :func:`_is_vendored`).
|
|
273
|
+
2. An **installed** package or module on ``sys.path`` (resolved via
|
|
274
|
+
``importlib``) — so a dependency declared in the project's environment
|
|
275
|
+
(e.g. an ``uv``-managed ``.venv``) is pulled straight from site-packages
|
|
276
|
+
with no vendored copy committed to the repository.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
module: The top-level module or package name from ``[wasm].modules``.
|
|
280
|
+
project_root: The project directory, when available.
|
|
281
|
+
|
|
282
|
+
Returns:
|
|
283
|
+
A ``(root, top)`` pair where ``root`` is the parent directory archive
|
|
284
|
+
entries are made relative to and ``top`` is the file or directory name
|
|
285
|
+
under it — fed straight into :func:`_zip_tree`.
|
|
286
|
+
|
|
287
|
+
Raises:
|
|
288
|
+
BuildError: If the module is neither vendored under ``project_root`` nor
|
|
289
|
+
importable from the current environment.
|
|
290
|
+
"""
|
|
291
|
+
if project_root is not None and _is_vendored(project_root / module):
|
|
292
|
+
return project_root, module
|
|
293
|
+
|
|
294
|
+
try:
|
|
295
|
+
spec = importlib.util.find_spec(module)
|
|
296
|
+
except (ImportError, ValueError):
|
|
297
|
+
spec = None
|
|
298
|
+
if spec is not None:
|
|
299
|
+
locations = list(spec.submodule_search_locations or ())
|
|
300
|
+
if locations:
|
|
301
|
+
package_dir = Path(locations[0]).resolve()
|
|
302
|
+
return package_dir.parent, module
|
|
303
|
+
if spec.origin and spec.origin not in ("built-in", "frozen"):
|
|
304
|
+
origin = Path(spec.origin).resolve()
|
|
305
|
+
return origin.parent, origin.name
|
|
306
|
+
|
|
307
|
+
vendored = f"{project_root / module}" if project_root is not None else "<none>"
|
|
308
|
+
raise BuildError(
|
|
309
|
+
f"wasm module {module!r} not found: no vendored copy at {vendored} "
|
|
310
|
+
f"and not importable from the current environment"
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
|
|
239
314
|
def _zip_package(
|
|
240
315
|
dest: Path,
|
|
241
316
|
*,
|
|
@@ -256,11 +331,16 @@ def _zip_package(
|
|
|
256
331
|
dest: The ``.zip`` path to write.
|
|
257
332
|
project_root: The project directory the ``modules`` are relative to.
|
|
258
333
|
Required when ``modules`` is non-empty.
|
|
259
|
-
modules:
|
|
260
|
-
|
|
334
|
+
modules: Names (files or package dirs) to bundle next to ``app.py``
|
|
335
|
+
(e.g. ``("famacha",)``). Each is resolved by :func:`_resolve_module`:
|
|
336
|
+
a vendored copy under ``project_root`` wins, otherwise the module is
|
|
337
|
+
pulled from the installed environment (site-packages) via importlib —
|
|
338
|
+
so a dependency declared in the project's ``.venv`` need not be
|
|
339
|
+
vendored into the repository.
|
|
261
340
|
|
|
262
341
|
Raises:
|
|
263
|
-
BuildError: If an expected package part or a declared module
|
|
342
|
+
BuildError: If an expected package part is missing, or a declared module
|
|
343
|
+
is neither vendored nor importable.
|
|
264
344
|
"""
|
|
265
345
|
tempestweb_root = _package_dir().parent
|
|
266
346
|
tempest_core_root = _tempest_core_dir().parent
|
|
@@ -268,9 +348,8 @@ def _zip_package(
|
|
|
268
348
|
_zip_tree(archive, tempestweb_root, "tempestweb", _WASM_PACKAGE_PARTS)
|
|
269
349
|
_zip_tree(archive, tempest_core_root, "tempest_core", None)
|
|
270
350
|
for module in modules:
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
_zip_tree(archive, project_root, module, None)
|
|
351
|
+
root, top = _resolve_module(module, project_root)
|
|
352
|
+
_zip_tree(archive, root, top, None)
|
|
274
353
|
|
|
275
354
|
|
|
276
355
|
def _build_pwa(out: Path, client: Path, name: str, precache: tuple[str, ...]) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|