The official Python SDK for TofuPilot. Integrate your hardware test runs into one app with just a few lines of Python.
pip install tofupilotimportosfromtofupilot.v2importTofuPilotwithTofuPilot(api_key=os.getenv("TOFUPILOT_API_KEY")) asclient:
run=client.runs.create(
procedure_id="your-procedure-id",
serial_number="SN001",
part_number="PN001",
outcome="PASS",
)
print(f"Run created: {run.id}")Set your API key as an environment variable:
export TOFUPILOT_API_KEY="your-api-key"Or pass it directly:
client=TofuPilot(api_key="your-api-key")To point to a different server (e.g. self-hosted):
client=TofuPilot(api_key="your-api-key", server_url="https://your-instance.com/api")| Resource | Operations |
|---|---|
client.runs | list, create, get, delete, update |
client.runs.attachments | upload, download |
client.units | list, create, get, delete, update, add_child, remove_child |
client.units.attachments | upload, download, delete |
client.parts | list, create, get, delete, update |
client.parts.revisions | create, get, delete, update |
client.procedures | list, create, get, delete, update |
client.procedures.versions | create, get, delete |
client.batches | list, create, get, delete, update |
client.stations | list, create, get, get_current, remove, update |
client.user | list |
fromdatetimeimportdatetime, timedelta, timezonerun=client.runs.create(
procedure_id=procedure_id,
serial_number="SN-001",
part_number="PCB-V1",
outcome="PASS",
started_at=datetime.now(timezone.utc) -timedelta(minutes=5),
ended_at=datetime.now(timezone.utc),
phases=[{
"name": "Voltage Test",
"outcome": "PASS",
"started_at": datetime.now(timezone.utc) -timedelta(minutes=5),
"ended_at": datetime.now(timezone.utc),
"measurements": [{
"name": "Output Voltage",
"outcome": "PASS",
"measured_value": 3.3,
"units": "V",
"validators": [
{"operator": ">=", "expected_value": 3.0},
{"operator": "<=", "expected_value": 3.6},
],
}],
}],
)result=client.runs.list(
part_numbers=["PCB-V1"],
outcomes=["PASS"],
limit=10,
)
forruninresult.data:
print(f"{run.id} — {run.unit.serial_number}")# Create part and revisionclient.parts.create(number="PCB-V1", name="Main Board")
client.parts.revisions.create(part_number="PCB-V1", number="REV-A")
# Create unitsclient.units.create(serial_number="PARENT-001", part_number="PCB-V1", revision_number="REV-A")
client.units.create(serial_number="CHILD-001", part_number="PCB-V1", revision_number="REV-A")
# Link parent-childclient.units.add_child(serial_number="PARENT-001", child_serial_number="CHILD-001")# Upload a file to a runclient.runs.attachments.upload(id=run_id, file="report.pdf")
# Upload a file to a unitclient.units.attachments.upload(serial_number="SN-0001", file="calibration.pdf")
# Download an attachmentrun=client.runs.get(id=run_id)
client.runs.attachments.download(run.attachments[0], dest="local-copy.pdf")
# Delete a unit attachmentclient.units.attachments.delete(serial_number="SN-0001", ids=[attachment_id])fromtofupilot.v2.models.errorsimportErrorNOTFOUND, ErrorBADREQUESTtry:
client.runs.get(id="nonexistent-id")
exceptErrorNOTFOUNDase:
print(f"Not found: {e.message}")
exceptErrorBADREQUESTase:
print(f"Bad request: {e.message}")| Exception | Status Code |
|---|---|
ErrorBADREQUEST | 400 |
ErrorUNAUTHORIZED | 401 |
ErrorFORBIDDEN | 403 |
ErrorNOTFOUND | 404 |
ErrorCONFLICT | 409 |
ErrorUNPROCESSABLECONTENT | 422 |
ErrorINTERNALSERVERERROR | 500 |
cd clients/python-speakeasy
cp tests/.env.local.example tests/.env.local # Set your API key and URL
python -m pytest tests/v2/MIT