Ship the reader wheels inside the package for offline install
A device with no internet could not set itself up: the auto-install needed PyPI. The rdm6300 and pyserial wheels now ship inside the package, so first start works with no network at all. Both wheels are pure Python (py3-none-any / py2.py3-none-any), which is what makes this possible - the same files work on armv7l, aarch64 and x86_64. This is the difference from the workstation app's Files/repository cache, which held aarch64 manylinux binaries and so could not be committed; that cache only ever existed on the Pi devices. - bundled_wheel_dir() locates them; ensure_dependencies() prefers them automatically, so the service needs no --wheel-dir. - verify_wheels() checks SHA256SUMS before installing. A wheel that fails its checksum is refused rather than installed, then PyPI is tried, and if that is unreachable it reports exit 2 instead of proceeding unverified. - local_wheel_missing() falls back to PyPI when the bundle does not cover a requirement, instead of attempting a --no-index install that must fail. - An explicit --wheel-dir that is incomplete or unverified is called out, not silently swapped for PyPI. Verified end to end: built wheel and sdist both contain the wheels; a venv with no rdm6300 self-provisions with a dead proxy and no PIP_NO_INDEX; and a tampered wheel is refused with nothing installed.
This commit is contained in:
@@ -89,7 +89,7 @@ Also works as a module: `python -m rdm_card_reader`.
|
||||
| `--demo` | – | Simulated reads; needs no hardware and no `rdm6300` |
|
||||
| `--demo-count` | `3` | Number of simulated reads in `--demo` |
|
||||
| `--no-install-deps` | off | Never install missing libraries automatically |
|
||||
| `--wheel-dir` | – | Install missing libraries from local wheels (offline) |
|
||||
| `--wheel-dir` | bundled | Install from local wheels in this DIR instead of the bundled ones |
|
||||
| `--version` | – | Print the version |
|
||||
|
||||
With `--serve`: `--host` (`127.0.0.1`), `--bridge-port` (`8765`), `--mode`
|
||||
@@ -115,32 +115,46 @@ is what you want when piping into another program:
|
||||
|
||||
### Automatic dependency install
|
||||
|
||||
On first start the reader checks that it can import its libraries and installs
|
||||
any that are missing, so a freshly flashed device works without manual setup:
|
||||
The wheels for `rdm6300` and `pyserial` **ship inside this package**
|
||||
(`rdm_card_reader/wheels/`), so a device with no internet can still set itself
|
||||
up. On first start the reader installs whatever is missing from those wheels:
|
||||
|
||||
```
|
||||
Reader library not found - checking dependencies...
|
||||
Missing reader dependencies: rdm6300
|
||||
Installing from PyPI ...
|
||||
Using the wheels bundled with this package:
|
||||
/opt/rdm-card-reader/.venv/lib/python3.13/site-packages/rdm_card_reader/wheels
|
||||
Installing from .../rdm_card_reader/wheels
|
||||
Dependencies ready: rdm6300
|
||||
```
|
||||
|
||||
No network access is needed. They ship with the package rather than being
|
||||
fetched at build time, because the build machine and the target device are not
|
||||
necessarily the same.
|
||||
|
||||
Both wheels are **pure Python** (`py3-none-any` / `py2.py3-none-any`), which is
|
||||
what makes this possible: the same files install on armv7l, aarch64 and x86_64.
|
||||
This differs from the workstation app's `Files/repository/` cache, which held
|
||||
architecture-specific binaries (aarch64 manylinux wheels) and so could not be
|
||||
committed — that cache only ever existed on the Pi devices themselves.
|
||||
|
||||
* Nothing is installed when the libraries are already present, so a normal start
|
||||
does no network work at all.
|
||||
* A failed install does not crash: it reports `exit 2` and tells you the exact
|
||||
command to run by hand.
|
||||
* The bundled install runs with `--no-index`, so it works with no route to PyPI
|
||||
at all — no proxy or DNS needed.
|
||||
* Wheels are verified against a bundled `SHA256SUMS` before installation. **A
|
||||
wheel that fails its checksum is refused, not installed** — then it falls back
|
||||
to PyPI, and if that is unreachable it reports `exit 2` rather than proceeding
|
||||
with something unverified.
|
||||
* Outside a virtualenv pip is given `--break-system-packages`, which Debian and
|
||||
Raspberry Pi OS require before they will touch the system Python.
|
||||
* A failed install does not crash: it reports `exit 2` and tells you the exact
|
||||
command to run by hand.
|
||||
|
||||
For a device with **no internet**, put the wheels next to the app and install
|
||||
from there — no index is contacted:
|
||||
|
||||
```bash
|
||||
pip download rdm6300 pyserial -d wheels # on a machine with internet
|
||||
rdm-card-reader --serve --wheel-dir ./wheels
|
||||
```
|
||||
|
||||
To manage dependencies yourself, pass `--no-install-deps`.
|
||||
To install from your own wheel directory instead (for example a newer version
|
||||
than the bundled one), pass `--wheel-dir`. An explicit directory that is
|
||||
incomplete or fails verification is reported and then PyPI is used, rather than
|
||||
failing outright. To manage dependencies yourself, pass `--no-install-deps`.
|
||||
|
||||
### Exit codes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user