Skip to content

Packaging for non-developer users (pip/uvx installable, GUI bundled)#86

Merged
matt-pharr merged 8 commits into
developfrom
feature/pypi-packaging
Jul 8, 2026
Merged

Packaging for non-developer users (pip/uvx installable, GUI bundled)#86
matt-pharr merged 8 commits into
developfrom
feature/pypi-packaging

Conversation

@matt-pharr

Copy link
Copy Markdown
Collaborator

Closes #79.

Makes the app installable and runnable by non-developers: uvx magnetics (or pip install magnetics && magnetics) starts the service and opens the bundled GUI in a browser — no Node or dev stack. The GUI ships inside the wheel.

What's here

  • Packaging — fold fastapi/uvicorn (+ platformdirs) into core deps, drop the service extra, add magnetics / magnetics-fetch / magnetics-service console scripts. Lower requires-python to >=3.12 (.python-version stays 3.14 for dev). CI now tests 3.12 and 3.14.
    • Fixes 9 PEP 758 unparenthesized-except sites (except A, B:) that only compiled on 3.14 and would break every 3.12 install.
  • magnetics launcher (src/magnetics/cli.py) — free-port pick, opens the browser once the server binds, --host/--port/--no-browser/--data-dir.
  • Installed-mode data dirdata_dir() falls back to a persistent per-user dir (platformdirs) when not run from a source checkout, so an installed wheel writes shot data somewhere real and writable. $MAGNETICS_DATA_DIR / --data-dir override (the knob for clusters → scratch).
  • Same-origin GUI — a production vite build now defaults to relative /api/… URLs, fixing the silently-mock --prod/wheel. Verified with Playwright (live badge, same-origin calls, zero /mock/ hits).
  • Release automation — tag-triggered release.yml (build GUI → stage → uv build → verify bundle → smoke-test the wheel → PyPI trusted-publish → GitHub Release). workflow_dispatch = build + smoke only. Docs in docs/RELEASING.md.
  • Toolingrun.shrun-dev.sh (dev only); new scripts/build-dist.sh does the GUI-stage-then-uv build dance (--smoke installs+boots the wheel). The release workflow calls this script so local and CI builds can't drift.

Verification

  • 377 tests pass on both 3.12 and 3.14; ruff format/lint, ty, eslint, tsc, 41 vitest — all green.
  • Full installed-wheel smoke test (via build-dist.sh --smoke): import magnetics, all 3 scripts installed, launched from a non-checkout dir → /api/machines 200, GUI 200, data_dir() → per-user dir (not site-packages).
  • Both sdist and wheel bundle the GUI + device JSONs (asserted in the build script / workflow).

Follow-up for a maintainer (not in this PR)

The first PyPI publish needs the one-time trusted-publisher setup (project magnetics is unclaimed) and the pypi GitHub environment — steps are in docs/RELEASING.md. Version bump + tag cuts the release.

matt-pharr and others added 8 commits July 8, 2026 01:27
Make `pip install magnetics` runnable with no extras: move fastapi/
uvicorn into core dependencies (+ platformdirs), drop the `service`
extra, and add `magnetics` / `magnetics-fetch` console scripts.

Lower requires-python to >=3.12 (the 3.14 pin was a project choice, not
forced by any dependency; .python-version stays 3.14 for dev). Fixes 9
PEP 758 unparenthesized-`except` sites that only compiled on 3.14, and
adds a 3.12+3.14 CI test matrix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New `magnetics` console script starts the service and opens the bundled
GUI in a browser (free-port pick like run.sh; browser opens once the
server binds; --host/--port/--no-browser). No Node/dev stack needed.

data_dir() now falls back to a per-user data dir (platformdirs) when not
run from a source checkout, so an installed wheel writes shot data to a
real, writable location instead of a path under site-packages.
$MAGNETICS_DATA_DIR still overrides. Drop inspect.py's dead default
(pointed at a never-shipped shot file).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The packaged app serves the GUI and the API on one origin, but api.ts
decided live-vs-mock from the build-time VITE_API_BASE truthiness, so a
plain `vite build` (no env) shipped a MOCK-mode bundle — `run.sh --prod`
and any pip-installed app silently served demo fixtures.

Now: an explicit VITE_API_BASE still wins (trailing slashes trimmed); a
production build with none defaults to "" (same-origin, relative /api/…
URLs); the dev server stays in mock mode. Since "" is a valid live base,
every live-vs-mock check switches from truthiness to an explicit LIVE
flag, and QuasiStationaryTab's `!apiBase()` guard becomes
`!usingLiveBackend()`.

Verified with Playwright against the packaged app: badge "● live
backend", same-origin /api/ requests, zero /mock/ hits.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On a `v*` tag: build the GUI, stage it into the package, build sdist +
wheel, assert the GUI and device data are bundled, smoke-test the wheel
in a clean 3.12 venv (install, import, boot the launcher, curl the API
and GUI), then publish via PyPI trusted publishing and cut a GitHub
Release. `workflow_dispatch` runs build + smoke test only (no publish)
for dry runs.

docs/RELEASING.md covers the one-time trusted-publisher setup and the
GitFlow-lite release procedure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A --data-dir flag sets MAGNETICS_DATA_DIR for the run, so non-developers
can choose where shot data lands without touching env vars. On a cluster
this points at scratch/project space instead of the quota'd home dir.

The flag is applied before any code resolves h5source.data_dir();
toksearch's default output path is recomputed at fetch time (not from
the import-time DATA_DIR) so a late override still takes effect.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Document `uvx magnetics` / `pip install magnetics` + `magnetics` as the
one-command install-and-run path, the --port/--no-browser/--data-dir
flags, the magnetics-fetch/magnetics-service scripts, and where shot
data is cached (incl. the cluster → MAGNETICS_DATA_DIR=scratch pattern).
Keep the dev setup and point to docs/RELEASING.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
run.sh only ever ran the dev stack; rename it to run-dev.sh to make room
for a distribution builder. scripts/build-dist.sh does the staging dance
`uv build` can't: build the GUI, stage it into the package, build the
sdist + wheel, verify the GUI/device data are bundled, and (with
--smoke) install and boot the wheel in a clean 3.12 venv.

The release workflow now calls build-dist.sh so local and CI builds
can't drift. Fixes a SIGPIPE in the bundle-verify greps (`… | grep -q`
under `set -o pipefail` aborted once grep matched) by capturing the
listings first. Updates the run.sh references in the README, CLAUDE.md,
and code comments.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a README section showing `uvx --from ./dist/*.whl magnetics` to try a
freshly built wheel in a throwaway env that touches neither the repo's
.venv nor its data/ dir, plus the --data-dir and --reinstall variants.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@matt-pharr

Copy link
Copy Markdown
Collaborator Author

FYI @logan-nc @ebursch this is the build pipeline newly set up. This enables the building of a wheel. The method for running this as an user will be pip install magnetics-or-whatever-we-name-it; magnetics. Everything is packaged as the python package. The package is still importable as import magnetics from a python env where it is installed. I updated the readme with some basic instructions on building + running. I also renamed run.sh to run-dev.sh to avoid confusion (it is only for running while developing the module). I still need to get it set up to work right on cybele / other nx / login nodes, but that is coming soon.

@matt-pharr matt-pharr merged commit 741476c into develop Jul 8, 2026
5 checks passed
@logan-nc

logan-nc commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

awesome! thanks @matt-pharr !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

We need packaging for non-developer users

2 participants