workspace#
Workspace management for Canary test execution.
This module defines the Workspace and Session classes which handle the lifecycle of test execution environments. A Workspace acts as the central repository for test specifications, results databases, and “views” (consolidated results). Sessions represent a specific execution run of a set of jobs.
- Key functionalities include:
Creating and loading persistent workspaces on disk.
Managing a “View” of the latest test results via symlinks, hardlinks, or copies.
Coordinating the execution of Job objects within a Session.
Interfacing with the WorkspaceDatabase to store and retrieve job specifications.
Providing selection mechanisms to filter tests by tags, regex, or owners.
Example
>>> ws = Workspace.create(path=".")
>>> specs = ws.collect(scanpaths={"/src/tests": []})
>>> session = ws.run(specs=specs)
- class ViewSettings(name: str = 'TestResults', when: Literal['always', 'on_success', 'on_failure', 'never'] = 'always', only: Literal['all', 'failed', 'not_pass', 'passed'] = 'all', mode: Literal['symlink', 'hardlink', 'copy'] = 'symlink')#
Bases:
object- name: str = 'TestResults'#
- when: Literal['always', 'on_success', 'on_failure', 'never'] = 'always'#
- only: Literal['all', 'failed', 'not_pass', 'passed'] = 'all'#
- mode: Literal['symlink', 'hardlink', 'copy'] = 'symlink'#
- classmethod default() ViewSettings#
- is_enabled_for_status(status: int) bool#
- is_disabled() bool#
- class ResultsView(root: pathlib.Path, settings: _canary.workspace.ViewSettings)#
Bases:
object- root: Path#
- settings: ViewSettings#
- property dir: Path#
- exists() bool#
- make(exist_ok: bool = False) None#
- unlink(missing_ok: bool = False) None#
- class Session(name: str, jobs: list[_canary.job.Job], prefix: pathlib.Path)#
Bases:
object- name: str#
- prefix: Path#
- returncode: int = -1#
- started_on: datetime = datetime.datetime(1, 1, 1, 0, 0)#
- finished_on: datetime = datetime.datetime(1, 1, 1, 0, 0)#
- run(workspace: Workspace) None#
Executes the session’s jobs using a Runner.
- Parameters:
workspace – The Workspace instance providing the environment.
- Raises:
StopExecution – If no runnable jobs are found.
- class Workspace(anchor: str | Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/docs/source'))#
Bases:
object- version_info = (1, 0, 0)#
- root: Path#
- refs_dir: Path#
- sessions_dir: Path#
- cache_dir: Path#
- tmp_dir: Path#
- logs_dir: Path#
- canary_level: int#
- initialize_properties(*, anchor: Path) None#
Sets up the internal directory structure paths based on the anchor.
- Parameters:
anchor – The base directory where the .canary folder resides.
- static remove(start: str | Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/docs/source')) Path | None#
Deletes a workspace and its associated view.
- Parameters:
start – Path to start searching for the workspace.
- Returns:
The path to the removed workspace, or None if no workspace was found.
- rmf() None#
Dangerously removes the workspace and view directories from disk.
- latest_view() ResultsView | None#
- register_view(view: ResultsView) None#
- static find_anchor(start: str | Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/docs/source')) Path | None#
Searches upwards from start to find the directory containing the workspace.
- Parameters:
start – The directory to start the search from.
- Returns:
The anchor Path if found, otherwise None.
- static find_workspace(start: str | Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/docs/source')) Path | None#
Locates the .canary workspace directory.
- Parameters:
start – The directory to start the search from.
- Returns:
The path to the workspace directory if found, otherwise None.
- classmethod create(path: str | Path = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/canary-wm/checkouts/latest/docs/source'), force: bool = False) Workspace#
Creates a new Canary workspace at the specified path.
- Parameters:
path – The anchor directory for the workspace.
force – If True, remove existing workspace at path before creating.
- Returns:
The newly created Workspace instance.
- classmethod load(start: str | Path | None = None) Workspace#
Loads an existing workspace from the filesystem.
- Parameters:
start – The directory to start searching for the workspace.
- Returns:
A loaded Workspace instance.
- Raises:
NotAWorkspaceError – If no workspace is found.
- run(specs: list[JobSpec], session: str | None = None, inplace: bool = False, view_t: ViewSettings | None = None, only: str = 'not_pass') Session#
Executes a set of job specifications in a new or existing session.
- Parameters:
specs – List of job specs to run.
session – Optional existing session name to reuse.
inplace – If True, run jobs in their existing result directories.
view_t – View settings.
only – Rerun strategy (e.g., ‘not_pass’).
- Returns:
The resulting Session object.
- add_session_results(session: Session, view_t: ViewSettings | None = None) None#
Update latest results, view, and refs with results from
session
- rebuild_view(view_t: ViewSettings | None = None) None#
Keep only the latest results.
- relative_to_view(path: str | PathLike[str]) str | None#
If path is inside TestResults, return the relative path (which may include glob characters). Otherwise return None.
Examples
/ws/TestResults/foo/bar/test.py -> foo/bar/test.py
- is_session_dir(path: str | PathLike[str]) bool#
Checks if a path is located within the workspace’s sessions directory.
- Parameters:
path – The path to check.
- Returns:
True if the path is inside the sessions directory, False otherwise.
- info() dict[str, Any]#
Returns summary information about the workspace.
- Returns:
A dictionary containing root, session count, latest session, and version.
- collect(scanpaths: dict[str, list[str]], on_options: list[str] | None = None) list[JobSpec]#
Find test job generators in scan_paths and add them to this workspace.
- Parameters:
scanpaths – Dictionary of root paths to scan.
on_options – Options used to filter tests by option.
- Returns:
A list of resolved JobSpecs.
- store_specs(specs: list[JobSpec]) None#
Caches the provided job specifications into the workspace database.
- Parameters:
specs – The resolved job specifications to store.
- select(tag: str, prefixes: list[str] | None = None, keyword_exprs: list[str] | None = None, parameter_expr: str | None = None, owners: list[str] | None = None, regex: str | None = None) list[JobSpec]#
Selects job specifications from the database using filters and saves as a tag.
- Parameters:
tag – The name of the selection tag to create.
prefixes – Filter by path prefixes.
keyword_exprs – Filter by keywords.
parameter_expr – Filter by parameter expressions.
owners – Filter by owners.
regex – Filter by regular expression.
- Returns:
The list of selected JobSpecs.
- select_from_specs(resolved: list[JobSpec], prefixes: list[str] | None = None, keyword_exprs: list[str] | None = None, parameter_expr: str | None = None, owners: list[str] | None = None, regex: str | None = None) list[JobSpec]#
Filters a list of JobSpecs using the provided rules.
- Parameters:
resolved – The list of specs to filter.
prefixes – Filter by path prefixes.
keyword_exprs – Filter by keywords.
parameter_expr – Filter by parameter expressions.
owners – Filter by owners.
regex – Filter by regular expression.
- Returns:
The filtered list of JobSpecs.
- create_selection(tag: str | None, scanpaths: dict[str, list[str]], on_options: list[str] | None = None, keyword_exprs: list[str] | None = None, parameter_expr: str | None = None, owners: list[str] | None = None, regex: str | None = None) list[JobSpec]#
Collects generators from paths and creates a tagged selection.
- Parameters:
tag – Tag name (randomly generated if None).
scanpaths – Paths to scan for generators.
on_options – Options to filter tests by.
keyword_exprs – Filter by keywords.
parameter_expr – Filter by parameters.
owners – Filter by owners.
regex – Filter by regex.
- Returns:
The created selection of JobSpecs.
- apply_selection_rules(specs: list[JobSpec], keyword_exprs: list[str] | None = None, parameter_expr: str | None = None, owners: list[str] | None = None, regex: str | None = None, ids: list[str] | None = None) None#
Filters the provided specs in-place using selection rules.
- Parameters:
specs – The list of specs to filter.
keyword_exprs – Filter by keywords.
parameter_expr – Filter by parameters.
owners – Filter by owners.
regex – Filter by regex.
ids – Filter by specific IDs.
- load_jobs(ids: list[str] | None = None) list[Job]#
Loads jobs from the database, reconstructing them with their latest results.
- Parameters:
ids – Optional list of specific job IDs to load.
- Returns:
A list of Job objects in static dependency order.
- select_from_view(path: Path) list[JobSpec]#
Identifies JobSpecs based on ‘testcase.lock’ files found in the view.
- Parameters:
path – The directory path to scan for lock files.
- Returns:
A list of corresponding JobSpecs.
- remove_tag(tag: str) bool#
Deletes a selection tag from the database.
- Parameters:
tag – The tag name to remove.
- Returns:
True if the tag was removed, False if it didn’t exist.
- is_tag(tag: str) bool#
Checks if a given string is a valid selection tag.
- Parameters:
tag – The string to check.
- Returns:
True if it is a selection tag, False otherwise.
- generate_jobspecs(generators: list[AbstractTestGenerator], on_options: list[str] | None = None) list[JobSpec]#
Generate resolved test specs.
- Parameters:
generators – List of test generators.
on_options – Used to filter tests by option.
- Returns:
A list of resolved JobSpecs.
- construct_jobs(specs: list[JobSpec], session: Path) list[Job]#
Creates Job objects from JobSpecs, attempting to link latest results.
- Parameters:
specs – The specifications to turn into jobs.
session – The directory for the current session.
- Returns:
A list of constructed Job objects.
- get_selection(tag: str | None) list[JobSpec]#
Retrieves a list of JobSpecs associated with a tag.
- Parameters:
tag – The tag name, or None/:all: for all specs.
- Returns:
A list of JobSpecs.
- gc(dryrun: bool = False) None#
Garbage collects old result directories, keeping only the latest per job.
- Parameters:
dryrun – If True, only log what would be removed without actually deleting.
- find(*, job: str | None = None, spec: str | None = None) Any#
Locates a Job or JobSpec in the workspace.
- Parameters:
job – Identifier to find a Job.
spec – Identifier to find a JobSpec.
- Returns:
The found Job or JobSpec.
- find_job(root: str) Job#
Locates a Job by ID or matching pattern.
- Parameters:
root – The ID or pattern to match.
- Returns:
The matching Job object.
- Raises:
ValueError – If no matching job is found.
- find_jobspec(root: str) JobSpec#
Locates a JobSpec by ID or matching pattern.
- Parameters:
root – The ID or pattern to match.
- Returns:
The matching JobSpec object.
- Raises:
ValueError – If no matching spec is found.
- find_specids(ids: list[str]) list[str | None]#
Resolves a list of potentially partial IDs or names to full spec IDs.
- Parameters:
ids – List of strings to resolve.
- Returns:
A list of resolved spec IDs, or None if not found.
- testcase_done_callback(event: EventTypes, *args: Any) None#
Callback to queue job results for database persistence.
- Parameters:
event – The event type.
*args – Event arguments, expected to contain the finished job.
- exception WorkspaceExistsError#
Bases:
ExceptionRaised when attempting to create a workspace in a directory that already exists.
- exception NotAWorkspaceError#
Bases:
ExceptionRaised when a directory is not recognized as a Canary workspace.
- exception SpecNotFoundError#
Bases:
ExceptionRaised when a requested JobSpec cannot be located in the workspace.