Skip to content

Python SDK

The warmhub package provides synchronous and asynchronous Python clients for reading, writing, and navigating WarmHub repositories. It supports Python 3.10 and later.

Installation, tokens, client options and error handling are shared with the TypeScript SDK and covered once in the SDK Overview — pick its Python tab. In short:

Terminal window
pip install warmhub
export WH_TOKEN="wh_..."

See Creating a personal access token if you need a token.

from warmhub import WarmHubClient
with WarmHubClient.from_env() as client:
sensors = client.repository("acme/sensors")
page = sensors.things.head(shape="Reading", limit=5)
for item in page.items:
print(item.wref, item.version, item.data)
batch = sensors.batch(message="seed a reading")
batch.add(name="probe-1", shapes=["Reading"], data={"temp_celsius": 21.4})
result = batch.commit()
print(result.operation_count)

client.repository("org/repo") binds a repository handle, so later calls do not repeat the organization and repository names. batch.add(...) only queues an operation; batch.commit() is the line that sends it. Every add states the Shapes the Thing declares — see Write Methods for the other ways to write.

Use WarmHubClient in ordinary synchronous programs, as above. AsyncWarmHubClient exposes the same repository paths and arguments for async applications:

from warmhub import AsyncWarmHubClient
async with AsyncWarmHubClient.from_env() as client:
sensors = client.repository("acme/sensors")
page = await sensors.things.head(shape="Reading", limit=5)
batch = sensors.batch(message="seed a reading")
batch.add(name="probe-2", shapes=["Reading"], data={"temp_celsius": 19.8})
result = await batch.commit()

from_env() reads WH_TOKEN and WARMHUB_API_URL. The ordinary constructors do not read credentials from the environment; pass access_token= when explicit configuration is preferable.

Payload keys are never renamed. Method arguments are snake_case, but keys inside data are stored exactly as written. If a stored field is called probeId, a typed Python payload must also call it probeId.

UNSET is not None. Optional parameters default to UNSET, which leaves the field out of the request. Don’t pass None to mean “omitted”: most optional parameters don’t accept it, and a None that reaches the request is sent as JSON null, which the server rejects for those fields.

Not every error is a WarmHubError. Some mistakes are caught before any request is sent, and how they surface depends on what was wrong:

  • A wrong argument — an unknown keyword, a missing required one, or both run_id= and delivery_id= — raises Python’s own TypeError.
  • A malformed repository locator, such as client.repository("acme"), raises ValueError.
  • An operation the SDK can check locally — an add with no Shapes, or with both shapes= and shapeless=True — raises WriteOperationError, a WarmHubError.

Everything the server decides is a WarmHubError; branch on err.kind. See Error Handling.

Task guides walk through common jobs end to end:

Concepts shared with TypeScript: Write Methods, Repository Checkpoints, and Repo Statistics.

Reference: the Python SDK reference lists every public name you can import from warmhub. Client namespace methods take an organization and repository explicitly; repository-bound methods omit them after client.repository("org/repo"). Sync and async signatures appear together, so porting a call between the two needs one page. To export a repository from Python, see Repository Checkpoints.