client.jobs¶
Bases: SyncResource
Sync jobs namespace (client.jobs).
get ¶
list ¶
list(*, status: JobStatus | list[JobStatus] | None = None, kind: JobKind | list[JobKind] | None = None, created_by: UUID | str | None = None, dataset_id: UUID | str | None = None, project_id: UUID | str | None = None, created_at_from: datetime | str | None = None, created_at_to: datetime | str | None = None, include_total: bool = False, limit: int | None = None, cursor: str | None = None) -> Page[Job]
List this tenant's jobs, newest first (cursor-paginated).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
status
|
JobStatus | list[JobStatus] | None
|
filter to one or more of pending/queued/running/completed/ failed/canceled (repeatable = IN). |
None
|
kind
|
JobKind | list[JobKind] | None
|
filter by job kind(s). Required to see |
None
|
created_by
|
UUID | str | None
|
only jobs created by this user id. |
None
|
dataset_id
|
UUID | str | None
|
only jobs whose target references this dataset. |
None
|
project_id
|
UUID | str | None
|
only jobs whose target references this project. |
None
|
created_at_from
|
datetime | str | None
|
created_at >= this bound (inclusive). |
None
|
created_at_to
|
datetime | str | None
|
created_at < this bound (exclusive). |
None
|
include_total
|
bool
|
also populate |
False
|
limit
|
int | None
|
page size (server cap 100). |
None
|
cursor
|
str | None
|
opaque page cursor (iteration handles this for you). |
None
|
Job handles & model¶
Kickoff methods across the SDK return a JobHandle — call .wait(). Job is the status model.
Async-job ergonomics: submit → wait → inspect, without hand-rolled polling.
Every bulk/GPU operation returns a Job (202). Resources wrap that in a
:class:JobHandle:
job = client.projects.assets.bulk_delete_annotations(pid, filter={}, source="model")
job = job.wait(timeout=600) # polls until terminal; raises on failure
job.result_summary # e.g. {"skipped_locked": 3}
Gotchas the platform enforces (surfaced here so you don't rediscover them):
- Per-tenant cap of 3 concurrently active jobs → RateLimitError(JOB_PER_TENANT_CAP).
Serialize long-running jobs (train, embed, export) rather than firing in parallel.
- GET /jobs hides internal kinds (cleanup_s3_objects) unless filtered by kind
explicitly — mirror of the server contract, not an SDK omission.
JobFailedError ¶
Bases: Exception
Raised by wait() when the job reaches failed/canceled. Carries
the terminal :class:Job on .job (job.error has the server reason).
JobTimeoutError ¶
Bases: Exception
Raised by wait() when the timeout elapses before a terminal status.
The job keeps running server-side; carry on with handle.refresh() later.
JobHandle ¶
A submitted job + the client that can poll it. Attribute access proxies the
underlying :class:Job model (handle.status, .processed, ...).
wait ¶
wait(*, timeout: float = _DEFAULT_TIMEOUT_S, poll_interval: float = _DEFAULT_POLL_S, on_progress: Callable[[Job], None] | None = None, raise_on_failure: bool = True) -> JobHandle
Poll until terminal. Raises :class:JobFailedError on failed/canceled
(unless raise_on_failure=False) and :class:JobTimeoutError on timeout.
on_progress fires after every poll with the fresh :class:Job.
Job models — the async-operation envelope every bulk/GPU kickoff returns.
Job ¶
Bases: BaseModel
One async job row (ADR-0023). Counters accrete while status is
pending/queued/running; terminal statuses are completed /
failed / canceled.
target and result_summary are deliberately plain dicts — their keys
vary per kind (the server validates them against per-kind registries).
result_summary examples: bulk-delete-annotations → {"skipped_locked": n,
"dropped_from_filter": n}; bulk-create → {"created", "failed", "errors"}.
pct is progress as an integer-valued percent (0–100) of processed over
total; it is None — not 0 — whenever total == 0 (an empty
bulk-op or a freshly-queued export with nothing counted yet), which is a normal
state, not an error.