Skip to content

Fix #40, #41, #71: make aether:install safe to re-run and truthful about the environment - #87

Open
corgab wants to merge 2 commits into
mainfrom
fix/40-41-71-install-command
Open

Fix #40, #41, #71: make aether:install safe to re-run and truthful about the environment#87
corgab wants to merge 2 commits into
mainfrom
fix/40-41-71-install-command

Conversation

@corgab

@corgab corgab commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Summary

Three defects in AetherInstallCommand, fixed together because they live in the same file and the same flow:

Plan

  • Keep an existing config, ask before overwriting when interactive, add --force for the deliberate overwrite.
  • Pin the smoke test to the local simulator and route it through the interpreter the command just verified or created, reusing the manager's own driver wiring.
  • Probe the SDK through importlib.metadata, compare with the floor pinned in bin/python/requirements.txt, and make every hint name the configured interpreter.

Changes

  • Signature gains {--force : Overwrite an existing config/aether.php}. publishConfig() publishes when the file is missing or --force is given; otherwise it asks config/aether.php already exists. Overwrite it with the package default? in an interactive terminal and keeps the file in a non-interactive run, reporting KEPT (pass --force to overwrite).
  • runTestCircuit(QuantumDevice $device) builds (new CircuitBuilder($device, 'local'))->qubits(1)->h(0)->measure()->run(). verifyInstallation() picks the device: $manager->localDriver($venvPython) when createVenv() just produced an interpreter, otherwise $manager->driver('local'). QuantumManager::localDriver(?string $pythonPath) and bridge(?string $pythonPath) are the single source of that wiring.
  • createVenv() and handleMissingDependencies() return the venv interpreter path on full success, null otherwise; the dependency install is skipped when the venv could not be created, and a failure falls back to the manual instructions instead of advertising an interpreter that does not exist.
  • checkDependencies() probes importlib.metadata.version("amazon-braket-sdk"), compares with the floor parsed by parseRequirementsFloor() from requirements.txt, and prints <version> (requires >= <floor>) plus <python> -m pip install --upgrade -r ... when too old. requirementsPath() replaces three copies of the relative path.
  • showManualInstructions() uses the configured interpreter and venvPythonPath(), so the commands are right on Windows and with a non-default python3.
  • A missing interpreter now returns FAILURE instead of printing "Aether installation complete".
  • README Installation section lists what the command does; CLAUDE.md gains one conventions bullet. No config change, no new dependencies.

Tests

AetherInstallCommandTest, driven by a fake #!/bin/sh interpreter answering --version and the -c probe (each test removes only the fakes it created):

  • config kept without --force (file unchanged), overwritten with --force, published when absent, kept when the interactive confirmation is declined;
  • SDK reported with its version when at or above the floor, flagged with requires >= and the floor when older with an upgrade hint naming the interpreter, NOT INSTALLED plus interpreter-specific manual instructions when the probe fails;
  • floor parsing from a requirements-shaped string;
  • the smoke test resolves driver('local') on the manager and nothing else, with aether.default = aws;
  • a smoke test whose run throws returns FAILURE; a missing interpreter returns FAILURE without the completion banner.

Local: pint passed, pest 804 tests passed.

Closes #40
Closes #41
Closes #71

…nment

The command no longer overwrites an existing config/aether.php: it keeps
the file, asks first when the terminal is interactive, and takes --force
to overwrite deliberately. The smoke test always runs on the local
simulator, never on the configured default driver, so an AETHER_DRIVER=aws
installation cannot submit a billable task; after the command creates a
virtual environment the smoke test runs through that interpreter instead
of the one configured at boot, so the documented happy path succeeds.

The SDK probe reads importlib.metadata.version("amazon-braket-sdk"), since
the braket namespace package has no __version__ and the old probe
reported NOT INSTALLED on every machine. The installed version is compared
with the floor pinned in bin/python/requirements.txt and an upgrade hint is
printed when it is too old. A failed venv creation now falls back to the
manual instructions instead of advertising an interpreter that does not
exist.

Closes #40
Closes #41
Closes #71
The upgrade hint and the manual instructions now name the configured
interpreter and the platform's venv layout instead of a bare pip, python3
and a Unix-only path. A missing interpreter makes the command fail instead
of reporting a complete installation, and a failed venv creation no longer
runs the dependency install against an interpreter that does not exist.

QuantumManager::localDriver() and bridge() accept an interpreter path, so
the smoke test after venv creation reuses the manager's own wiring rather
than a second copy of it. The tests assert that the smoke test resolves
driver('local') on the manager, cover a smoke test whose run throws and a
missing interpreter, and remove only the fake interpreters they created.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant