File size: 2,777 Bytes
ecc81b3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | """Copy the built viewer into the package, where the wheel can carry it.
cd viewer && npm install && npm run build
python viewer/install_bundle.py
Run from the repo root or from ``viewer/``; both work. The bundle lands in
``src/torch_dimensions/viz/static`` and is deliberately **not** committed —
it is a build artifact, it changes on every rebuild, and a repo that carries
its own build output accumulates diffs nobody reads. CI builds it before
packaging; ``pyproject.toml`` lists it under ``artifacts`` so hatchling
includes it even though ``.gitignore`` hides it.
The size guard here is the sdist-bloat lesson from DEBUG.md, one directory
over: `node_modules` once reached a released tarball because nothing looked at
what was actually in it.
"""
from __future__ import annotations
import shutil
import sys
from pathlib import Path
MAX_MB = 8.0
root = Path(__file__).resolve().parent.parent
src = root / "viewer" / "dist"
dest = root / "src" / "torch_dimensions" / "viz" / "static"
def main() -> int:
if not (src / "index.html").exists():
print(f"no build found at {src}\nrun: cd viewer && npm install && npm run build")
return 1
size_mb = sum(f.stat().st_size for f in src.rglob("*") if f.is_file()) / 2**20
files = sum(1 for f in src.rglob("*") if f.is_file())
if size_mb > MAX_MB:
print(f"refusing to install a {size_mb:.1f} MB bundle (limit {MAX_MB} MB)")
print("something is being bundled that should not be — check for source maps or assets")
return 1
if any(p.name == "node_modules" for p in src.rglob("*")):
print("node_modules is inside the build output; refusing")
return 1
if dest.exists():
shutil.rmtree(dest)
shutil.copytree(src, dest)
# Vite copies everything in `viewer/public/` into the build, and the live
# training script writes `viewer/public/run.json` there. Left alone, a
# wheel would carry whatever run happened to be on the packager's laptop —
# and the viewer would load it in preference to the model the user passed
# to `td.viz.show`, which is how this was noticed at all.
# `weights.json` is the same kind of stray: `td.viz.show(model)` serves the
# real one from memory, and a packaged copy would show the packager's
# weights for somebody else's model.
for name in ("run.json", "weights.json"):
for stray in dest.rglob(name):
stray.unlink()
print(f"stripped {stray.relative_to(dest)} (a local artefact, not part of the viewer)")
installed = sum(1 for f in dest.rglob("*") if f.is_file())
print(f"installed {installed} of {files} files, {size_mb:.2f} MB -> {dest.relative_to(root)}")
return 0
if __name__ == "__main__":
sys.exit(main())
|