spacr.cancellation

Cooperative cancellation for long-running spaCR pipelines.

Qt cannot safely kill a Python thread that may be writing a TIFF, committing a SQLite transaction, or updating several related artifacts. Instead, the GUI installs one CancellationToken in each worker thread and pipeline code calls checkpoint() only at boundaries where the previous unit is fully durable and the next unit has not started.

The module is intentionally standard-library only. Core workflows may import it without importing Qt, torch, or any GUI dependency.

Exceptions

PipelineCancelled

Raised at a safe boundary after cancellation has been requested.

Classes

CancellationToken

Thread-safe, idempotent cancellation request shared with one worker.

Functions

cancellation_requested(→ bool)

Return whether the calling worker has a pending cancellation request.

checkpoint(→ None)

Stop at this safe boundary when requested; otherwise do nothing.

current_token(→ Optional[CancellationToken])

Return the token installed for the calling thread, if any.

installed_token(→ Iterator[CancellationToken])

Install token for this thread and restore any prior token on exit.

Module Contents

exception spacr.cancellation.PipelineCancelled[source]

Bases: Exception

Raised at a safe boundary after cancellation has been requested.

This is a normal control-flow outcome, not a pipeline failure. Callers that catch broad Exception values must re-raise it so the worker can record the run as cancelled rather than as a failed item.

Initialize self. See help(type(self)) for accurate signature.

class spacr.cancellation.CancellationToken(reason: str = 'cancelled by the user')[source]

Thread-safe, idempotent cancellation request shared with one worker.

Parameters:

reason – default user-facing reason raised by checkpoint().

Create an unset token carrying the fallback cancellation reason.

cancel(reason: str | None = None) → bool[source]

Request cancellation and return True only for the first request.

Repeated Stop clicks are harmless and do not replace the original reason, which keeps logs and manifests deterministic.

checkpoint() → None[source]

Raise PipelineCancelled when cancellation was requested.

property cancelled: bool[source]

Whether cancellation has been requested.

property reason: str[source]

The first cancellation reason supplied to cancel().

spacr.cancellation.cancellation_requested() → bool[source]

Return whether the calling worker has a pending cancellation request.

spacr.cancellation.checkpoint() → None[source]

Stop at this safe boundary when requested; otherwise do nothing.

Calls outside a managed worker are intentionally no-ops, so the same pipeline functions work through the GUI, CLI, notebooks, and tests.

spacr.cancellation.current_token() → CancellationToken | None[source]

Return the token installed for the calling thread, if any.

spacr.cancellation.installed_token(token: CancellationToken) → Iterator[CancellationToken][source]

Install token for this thread and restore any prior token on exit.

Parameters:

token – cancellation token to expose within the context.