workflows
High-level workflow helpers for the YouSleep client.
This module provides a thin, composition-only convenience layer over the
resource endpoint handlers (projects, studies, recordings,
analyses). It lets a caller analyze a file end-to-end — create a project and
study, upload the recording, submit an analysis, wait for it to finish, and
fetch results — in a single call, without threading resource IDs by hand or
constructing request models.
Entry points:
- :meth:
WorkflowsEndpoint.analyze_file— persistent: creates/uses resources and returns an :class:AnalysisWorkflowResult. Never deletes anything. - :meth:
WorkflowsEndpoint.analyze_file_temporary— an async context manager that deletes whatever it created on exit (including on exception). Caller-supplied project/study IDs are never touched. - :meth:
WorkflowsEndpoint.analyze_files/ :meth:WorkflowsEndpoint.analyze_files_temporary— multi-file variants built on the server's batch endpoints: one study per file, bounded-concurrency uploads, single batch submission and status polling, and per-file outcomes that never raise for individual failures.
FetchKind = Literal['events', 'biomarkers', 'report']
module-attribute
¶
Which results analyze_file should pull back after the analysis completes.
FileOutcomeStatus = Literal['completed', 'failed', 'timeout']
module-attribute
¶
Terminal status of one file in a multi-file workflow.
AnalysisWorkflowResult
dataclass
¶
BatchAnalysisWorkflowResult
dataclass
¶
Everything a multi-file analyze_files run produced.
Per-file failures never raise (mirroring the platform's 207-style batch
semantics); inspect :attr:failed for files that did not complete.
FileAnalysisOutcome
dataclass
¶
Outcome for a single input file of :meth:WorkflowsEndpoint.analyze_files.
status is "completed" when the file's analysis finished successfully
(result is set), "failed" when any stage failed for this file
(error describes it; analysis is attached when one was submitted),
and "timeout" when the analysis was still running when the batch wait
expired.
WorkflowsEndpoint
¶
Bases: BaseEndpoint
High-level, end-to-end analysis workflows built on the resource endpoints.
analyze_file(*, file, analysis_config_id, project_id=None, study_id=None, project_name=None, study_name=None, age=None, bmi=None, sex=None, project=None, study=None, parameters=None, channels=None, fetch=('events', 'biomarkers'), poll_interval=5.0, timeout=3600.0, on_progress=None, _ctx=None)
async
¶
Analyze a file end-to-end and return the results.
Creates a project and study (unless existing IDs are supplied), uploads
the recording, submits an analysis with analysis_config_id, waits for
it to complete, and fetches the requested results. Resources are kept
— this method never deletes anything. Use
:meth:analyze_file_temporary when you want them cleaned up.
Naming: when study_name is omitted it is inferred from the filename
(night.edf -> study night). Metadata (age/bmi/sex) is
optional and passed as plain scalars. Power users may pass full
project/study models instead, mutually exclusively with the
corresponding scalar arguments.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file
|
str | Path | BinaryIO
|
Path (or open binary file) of the recording to upload. |
required |
analysis_config_id
|
str
|
ID of the analysis config to run. |
required |
project_id
|
UUID | str | None
|
Analyze into this existing project instead of creating one. |
None
|
study_id
|
UUID | str | None
|
Analyze into this existing study (requires |
None
|
project_name
|
str | None
|
Name for the project to create (else auto-generated). |
None
|
study_name
|
str | None
|
Name for the study to create (else inferred from filename). |
None
|
age
|
int | None
|
Optional subject age (years) for a created study. |
None
|
bmi
|
float | None
|
Optional subject BMI for a created study. |
None
|
sex
|
str | None
|
Optional subject sex ("male"/"female"/"other"/"unknown"). |
None
|
project
|
ProjectCreate | None
|
Full ProjectCreate model (instead of project_name). |
None
|
study
|
StudyCreate | None
|
Full StudyCreate model (instead of study_name + metadata). |
None
|
parameters
|
list[tuple[str, str | int | float | bool]] | None
|
Optional analysis parameters as (name, value) tuples. |
None
|
channels
|
list[str] | None
|
Optional explicit channel names for the analysis. |
None
|
fetch
|
tuple[FetchKind, ...]
|
Which results to return; defaults to events and biomarkers. |
('events', 'biomarkers')
|
poll_interval
|
float
|
Seconds between status checks while waiting. |
5.0
|
timeout
|
float | None
|
Max seconds to wait for the analysis before ClientTimeoutError. |
3600.0
|
on_progress
|
Callable[[int], None] | None
|
Optional upload-progress callback (percentage 0-100). |
None
|
_ctx
|
_RunContext | None
|
Internal run context (used by analyze_file_temporary); do not set. |
None
|
Returns:
| Type | Description |
|---|---|
AnalysisWorkflowResult
|
An AnalysisWorkflowResult with the recording, analysis, and results. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If targeting arguments are combined incorrectly. |
AnalysisWorkflowError
|
If the analysis ends in a non-completed state. |
ClientTimeoutError
|
If the analysis does not finish within |
YouSleepClientError
|
On any underlying API error. |
analyze_file_temporary(*, file, analysis_config_id, project_id=None, study_id=None, project_name=None, study_name=None, age=None, bmi=None, sex=None, project=None, study=None, parameters=None, channels=None, fetch=('events', 'biomarkers'), poll_interval=5.0, timeout=3600.0, on_progress=None)
async
¶
Run :meth:analyze_file, deleting created resources on exit.
Takes the same arguments as :meth:analyze_file. On exit — whether the
block completes normally or raises — this deletes whatever resources the
workflow created, relying on server-side cascade (deleting the created
project/study/recording removes its descendants and frees quota).
Caller-supplied project_id/study_id are never deleted.
Example
Yields:
| Type | Description |
|---|---|
AsyncIterator[AnalysisWorkflowResult]
|
The AnalysisWorkflowResult, valid for the duration of the block. |
analyze_files(*, files, analysis_config_id, project_id=None, project_name=None, project=None, study_id=None, parameters=None, channels=None, fetch=('events', 'biomarkers'), poll_interval=5.0, timeout=3600.0, max_concurrency=4, on_progress=None, _ctx=None)
async
¶
Analyze multiple files end-to-end and return per-file outcomes.
Creates one project (unless project_id is given) and one study per
file (names inferred from filenames), uploads the recordings with
bounded concurrency, submits all analyses in a single batch call, polls
the whole batch with single status calls, and fetches results for
completed analyses. Resources are kept — use
:meth:analyze_files_temporary for automatic cleanup.
Per-file failures never raise: each input file yields a
:class:FileAnalysisOutcome (completed/failed/timeout) and
the rest of the batch continues. Only argument errors and whole-batch
failures (e.g. the project cannot be created) raise.
One study per file. study_id targets an existing study and is
therefore only valid with a single file — a study holds exactly one
recording. Passing it with several files raises ValueError.
Multiple nights of one subject are several studies, one per night,
linked by a shared subject_key.
Per-file subject metadata is not supported here — create studies via the lower-level endpoints if needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
files
|
Sequence[str | Path | BinaryIO]
|
Paths (or open binary files) of the recordings, 1-500. |
required |
analysis_config_id
|
str
|
ID of the analysis config to run on every file. |
required |
project_id
|
UUID | str | None
|
Analyze into this existing project instead of creating one. |
None
|
project_name
|
str | None
|
Name for the project to create (else auto-generated). |
None
|
project
|
ProjectCreate | None
|
Full ProjectCreate model (instead of project_name). |
None
|
study_id
|
UUID | str | None
|
Existing study to upload into (requires project_id). Valid with a single file only — a study holds one recording. |
None
|
parameters
|
list[tuple[str, str | int | float | bool]] | None
|
Optional analysis parameters as (name, value) tuples. |
None
|
channels
|
list[str] | None
|
Optional explicit channel names for the analyses. |
None
|
fetch
|
tuple[FetchKind, ...]
|
Which results to return per file; defaults to events + biomarkers. |
('events', 'biomarkers')
|
poll_interval
|
float
|
Seconds between batch status polls while waiting. |
5.0
|
timeout
|
float | None
|
Max seconds to wait for the whole batch; analyses still
running afterwards yield |
3600.0
|
max_concurrency
|
int
|
Max parallel uploads / per-item result fetches. |
4
|
on_progress
|
Callable[[str | Path | BinaryIO, int], None] | None
|
Optional upload-progress callback receiving
|
None
|
_ctx
|
_BatchRunContext | None
|
Internal run context (used by analyze_files_temporary); do not set. |
None
|
Returns:
| Type | Description |
|---|---|
BatchAnalysisWorkflowResult
|
A BatchAnalysisWorkflowResult with one outcome per input file, in |
BatchAnalysisWorkflowResult
|
input order. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If arguments are combined incorrectly or out of range. |
YouSleepClientError
|
On whole-batch API failures (before any per-file work exists). |
analyze_files_temporary(*, files, analysis_config_id, project_id=None, project_name=None, project=None, study_id=None, parameters=None, channels=None, fetch=('events', 'biomarkers'), poll_interval=5.0, timeout=3600.0, max_concurrency=4, on_progress=None)
async
¶
Run :meth:analyze_files, deleting created resources on exit.
Takes the same arguments as :meth:analyze_files. On exit — whether the
block completes normally or raises — this deletes whatever the workflow
created: the created project (one cascade delete), or each created study
when the caller supplied the project, or each uploaded recording when
the caller supplied a shared study. Caller-supplied resources are never
deleted.
Yields:
| Type | Description |
|---|---|
AsyncIterator[BatchAnalysisWorkflowResult]
|
The BatchAnalysisWorkflowResult, valid for the duration of the block. |