A new crate, wai/wai-quantum-py, built by maturin 1.15.0 into one abi3 wheel per platform (pyo3 0.29.3, Python 3.9 on), module wai_quantum. Its extension module wraps the shared job engine and nothing else: run, plan, lint, draw (text and the engine SVG), layout, critique, improve, shortcuts, equivalent, verify, seal, canonical, digest, methods, accuracy_classes and history, values crossing one to one with JSON (NaN, integers past 64 bits and non-string keys refused). A job is the service form as a plain dict with helpers (counts, probabilities, expectations, amplitudes, method, accuracy, receipt); Key reads and writes the command line key files and finds the same user key; bloch gives each qubit reduced state from the engine expectation values. A refusal raises EngineError with the engine message, its line, and a code slot for the engine diagnostic codes. Service is a client in the standard library alone for the job service (submit, status, result, cancel, run), naming itself wai-quantum-python/<version>, its receipts checked here offline. Widgets (the widgets extra): Circuit (the engine drawing, gates clickable, authorship marks from a history), Result, Receipt (the engine verdict) and Bloch (drag to turn), each a plain ES module, each with static HTML (and SVG) fallbacks that render without the widget library. Five doc notebooks run in CI and are held to their stored outputs. ci/check.sh is the whole check; 62 pytest tests hold the package to the command line (same results, plans, lints, critiques, drawings, methods, equivalence verdicts; receipts verified both ways; the same user key; the digest recomputed from Python canonical bytes), to the service run locally, and run the front ends under node on the payloads; Python 3.9 smoke with the wheel alone. Workflow wai-quantum-py.yml runs it on linux and macos. Co-Authored-By: Claude Opus 5.5 <[email protected]>
57 lines
2.2 KiB
Python
57 lines
2.2 KiB
Python
"""The installed wheel on the oldest Python it promises (3.9), with nothing
|
|
else installed: the standard library and the package alone.
|
|
|
|
python -I tests/smoke.py
|
|
|
|
Prints one line per check and exits non-zero on the first that fails.
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import tempfile
|
|
import xml.etree.ElementTree as ET
|
|
|
|
import wai_quantum as wq
|
|
from wai_quantum import widgets
|
|
|
|
BELL = "OPENQASM 3.0; qubit[2] q; bit[2] c; h q[0]; cx q[0], q[1]; c = measure q;"
|
|
|
|
|
|
def main():
|
|
print("python", sys.version.split()[0], "wai_quantum", wq.__version__)
|
|
demo = wq.Key.demo()
|
|
job = wq.run(BELL, shots=1000, seed=7, key=demo)
|
|
assert job.method == "stabilizer" and job.accuracy == "exact" and set(job.counts) <= {"00", "11"}, job.summary()
|
|
assert wq.verify(json.loads(json.dumps(job))).valid
|
|
print("run and verify:", job.summary())
|
|
forged = json.loads(json.dumps(job))
|
|
forged["result"]["counts"]["00"] += 1
|
|
assert not wq.verify(forged)
|
|
print("a forged result does not verify")
|
|
assert ET.fromstring(wq.draw(BELL, format="svg")).tag.endswith("svg")
|
|
assert wq.equivalent("qubit[1] q; h q[0]; h q[0];", "qubit[1] q;")["verdict"] == "equivalent"
|
|
b = wq.bloch("OPENQASM 3.0; qubit[1] q; h q[0];", key=demo)
|
|
assert abs(b["qubits"][0]["x"] - 1) < 1e-12
|
|
print("draw, equivalent and bloch: ok")
|
|
with tempfile.TemporaryDirectory() as d:
|
|
import os
|
|
|
|
os.environ["XDG_CONFIG_HOME"] = d
|
|
k = wq.Key.user()
|
|
assert wq.verify(wq.run(BELL, shots=10)).key == k.public_key
|
|
print("the user's key: made and signed with")
|
|
assert not widgets.HAVE_WIDGETS, "this check runs with the package alone"
|
|
html = wq.Result(job)._repr_html_() + wq.Circuit(BELL)._repr_html_() + wq.Receipt(job)._repr_html_()
|
|
assert "verified" in html and "<svg" in html
|
|
print("the widgets' static fallbacks render without their library")
|
|
s = wq.Service("http://127.0.0.1:9/quantum-jobs/v1", timeout=1)
|
|
try:
|
|
s.describe()
|
|
except wq.ServiceError as e:
|
|
assert e.status is None
|
|
print("the service client: an unreachable service is a ServiceError;", wq.USER_AGENT)
|
|
print("smoke: every check passed")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|