exlab_wizard.lims.client#

Read-only LIMS client (Mapping B). Backend Spec §7.2.

The client wraps an httpx.AsyncClient to talk to the LIMS REST API. Authentication is cookie-session per §7.2.5: login() POSTs the operator’s email + password to /api/v1/login, the underlying httpx client retains the session cookie, and subsequent reads (list_projects, get_project, get_me) reuse it. On a 401 response from any of those reads, the client transparently re-runs login() once before failing – the LIMS may have invalidated the cookie out-of-band (server restart, session timeout) and a fresh login recovers without surfacing a transient error to the caller.

The client is intentionally read-only. Per §7.2.8 the v1 LIMS write surface is the empty set; the only mutating call is login and that is auth bookkeeping, not project mutation.

Classes

LIMSClient(*, endpoint, email, ...)

Read-only LIMS client.

class exlab_wizard.lims.client.LIMSClient(*, endpoint, email, keyring_password_provider)[source]#

Bases: object

Read-only LIMS client. Backend Spec §7.2 Mapping B.

Cookie-session auth: login() establishes the session; subsequent list/get methods reuse the cookie. On 401, the client refreshes the cookie via login() once before failing.

The keyring_password_provider callable is invoked from login() when no explicit password is passed. Callers wire this to exlab_wizard.lims.keyring_store.KeyringStore.get_password in production; tests can pass a lambda that returns a static value.

Parameters:
async close()[source]#

Close the underlying httpx.AsyncClient. Idempotent.

Return type:

None

property email: str#

Configured operator email; used as the login username.

property endpoint: str#

Configured base URL (trailing slashes stripped).

async get_me()[source]#

GET /api/v1/me; returns the current operator’s row.

Return type:

LIMSUser

async get_project(uid_or_short_id)[source]#

GET /api/v1/projects/<id>; returns None on 404.

uid_or_short_id may be either a UUID (uid column) or a PROJ-NNNN string (short_id column). The LIMS resolves both at the same endpoint.

Parameters:

uid_or_short_id (str)

Return type:

LIMSProject | None

async health_check()[source]#

Return a HealthStatus snapshot. Backend Spec §7.2.3.

Calls GET /api/v1/me and times the response. On any error (network, 4xx, 5xx) returns ok=False with a short reason rather than raising – the Settings “Test connection” UX needs a value to render.

Return type:

HealthStatus

async list_projects(*, status_filter=None)[source]#

GET /api/v1/projects; returns one LIMSProject per row.

status_filter is an optional list of allowed status values; rows whose status is not in the set are dropped on the client side. Filtering happens after deserialization so the wire format stays uniform.

Wire envelope: upstream returns {"data": [...], "count": N}; a missing data key is treated as an empty list rather than propagating a KeyError to the caller.

Parameters:

status_filter (list[str] | None)

Return type:

list[LIMSProject]

async login(*, password=None)[source]#

POST /api/v1/login with email + password.

On success the underlying httpx.AsyncClient retains the session cookie automatically; subsequent reads reuse it.

Raises exlab_wizard.errors.ConfigError when the keyring provider returns no password and none was supplied – that is a configuration condition, not a transient network failure.

Parameters:

password (str | None)

Return type:

None