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:
+27
-3
@@ -7,6 +7,7 @@ clearly instead of crashing.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
SRC = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "src"
|
||||
@@ -161,10 +162,11 @@ def test_no_install_flag_reports_manual_hint(monkeypatch):
|
||||
|
||||
|
||||
def test_wheel_dir_is_passed_through(monkeypatch):
|
||||
"""An explicit --wheel-dir that covers everything is used as given."""
|
||||
seen = {}
|
||||
monkeypatch.setattr(
|
||||
bootstrap, "missing_packages",
|
||||
lambda packages=None: [] if seen.get("done") else [("x", "x")],
|
||||
lambda packages=None: [] if seen.get("done") else [("x", "x>=1")],
|
||||
)
|
||||
|
||||
def fake_install(requirements, wheel_dir=None, logger=None, timeout=300):
|
||||
@@ -173,5 +175,27 @@ def test_wheel_dir_is_passed_through(monkeypatch):
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(bootstrap, "install", fake_install)
|
||||
ensure_dependencies(wheel_dir="/opt/wheels")
|
||||
assert seen["wheel_dir"] == "/opt/wheels"
|
||||
|
||||
with tempfile.TemporaryDirectory() as folder:
|
||||
open(os.path.join(folder, "x-1.0-py3-none-any.whl"), "wb").close()
|
||||
ensure_dependencies(wheel_dir=folder)
|
||||
assert seen["wheel_dir"] == folder
|
||||
|
||||
|
||||
def test_incomplete_explicit_wheel_dir_is_flagged(monkeypatch):
|
||||
"""An unusable --wheel-dir should be called out, not silently ignored."""
|
||||
seen = {}
|
||||
monkeypatch.setattr(
|
||||
bootstrap, "missing_packages",
|
||||
lambda packages=None: [] if seen.get("done") else [("x", "x>=1")],
|
||||
)
|
||||
|
||||
def fake_install(requirements, wheel_dir=None, logger=None, timeout=300):
|
||||
seen["done"] = True
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(bootstrap, "install", fake_install)
|
||||
lines = []
|
||||
with tempfile.TemporaryDirectory() as folder:
|
||||
ensure_dependencies(wheel_dir=folder, logger=lines.append)
|
||||
assert any("you gave is incomplete" in line for line in lines)
|
||||
|
||||
Reference in New Issue
Block a user