adsfolio.pdf.watch_session

Pure Python watch session state machine and immutable event types.

class adsfolio.pdf.watch_session.ArrivalIdentity(device, inode, birth_time_ns, generation)[source]

Bases: object

Stable identity for an arrival, distinguishing inode recycling.

Parameters:
  • device (int)

  • inode (int)

  • birth_time_ns (int | None)

  • generation (int)

birth_time_ns: int | None
device: int
generation: int
inode: int
class adsfolio.pdf.watch_session.FileSnapshot(path, size_bytes, mtime_ns, device, inode, birth_time_ns=None)[source]

Bases: object

Point-in-time filesystem facts for a single file.

Parameters:
birth_time_ns: int | None = None
device: int
classmethod from_path(path)[source]

Create a snapshot by calling stat() on the path.

Parameters:

path (Path or str) – Filesystem path to inspect.

Returns:

Constructed immutable snapshot.

Return type:

FileSnapshot

classmethod from_stat(path, st)[source]

Create a snapshot from an existing os.stat_result.

Parameters:
  • path (Path or str) – Filesystem path of the file.

  • st (os.stat_result) – Stat result from os.stat.

Returns:

Constructed immutable snapshot.

Return type:

FileSnapshot

inode: int
mtime_ns: int
path: pathlib.Path
size_bytes: int
class adsfolio.pdf.watch_session.WatchEvent(root, session_id, identity, path, state, newly_added=False)[source]

Bases: object

Immutable watch notification payload.

Parameters:
identity: adsfolio.pdf.watch_session.ArrivalIdentity
newly_added: bool = False
path: pathlib.Path
root: pathlib.Path
session_id: str
state: adsfolio.pdf.watch_session.WatchState
class adsfolio.pdf.watch_session.WatchOutcome(event, destination=None, bibcode=None, message=None, conflict_path=None, candidate_bibcode=None, candidate_sha256=None, candidate_fingerprint=None, candidate_confirmable=False, annotation_update=False)[source]

Bases: object

Store a watch result and its optional unverified ADS candidate.

bibcode identifies a resolved record. candidate_bibcode identifies a proposed record that still needs review. annotation_update marks a proven annotation-only change to an existing record.

Parameters:
annotation_update: bool = False
bibcode: str | None = None
candidate_bibcode: str | None = None
candidate_confirmable: bool = False
candidate_fingerprint: str | None = None
candidate_sha256: str | None = None
conflict_path: pathlib.Path | None = None
destination: pathlib.Path | None = None
event: adsfolio.pdf.watch_session.WatchEvent
message: str | None = None
class adsfolio.pdf.watch_session.WatchSession(root, session_id, baseline=())[source]

Bases: object

Manage watch baseline exclusion and per-arrival lifecycle transitions.

Parameters:
property baseline: frozenset[adsfolio.pdf.watch_session.ArrivalIdentity][source]

Return immutable set of baseline arrival identities.

begin_processing(identity)[source]

Transition a detected arrival into the processing state.

Parameters:

identity (ArrivalIdentity) – Arrival to begin processing.

Returns:

Event in PROCESSING state.

Return type:

WatchEvent

Raises:

ValueError – If identity is unknown, stale, or not in DETECTED state.

complete(identity, state)[source]

Record the outcome state of an arrival.

Parameters:
Returns:

Event in target outcome state.

Return type:

WatchEvent

Raises:

ValueError – If identity is unknown/stale or transition is invalid.

dismiss(identity)[source]

Mark an arrival as dismissed for this session.

Parameters:

identity (ArrivalIdentity) – Arrival identity.

Returns:

Event in DISMISSED state.

Return type:

WatchEvent

Raises:

ValueError – If identity is unknown/stale, currently processing, or already in a terminal state.

drain_followups()[source]

Return and clear events for changes seen while processing.

Call after complete(). Each event is a new DETECTED generation of a file that changed during processing.

Return type:

list[adsfolio.pdf.watch_session.WatchEvent]

finish_baseline(snapshots)[source]

Populate baseline physical identities after intake activation.

Parameters:

snapshots (Iterable[FileSnapshot]) – Snapshots discovered during initial directory scan.

Return type:

None

is_baseline(snapshot_or_identity)[source]

Check if a snapshot or identity belongs to the baseline.

Parameters:

snapshot_or_identity (FileSnapshot or ArrivalIdentity) – Object to check.

Returns:

True if in baseline, False otherwise.

Return type:

bool

known_paths()[source]

Return paths of baseline files and currently active arrivals.

Return type:

set[pathlib.Path]

observe(snapshot, source)[source]

Process a filesystem observation and return an event when eligible.

A tracked or baseline file whose size or modification time changed starts a new arrival generation. An unchanged file, for example after a rename inside the root, only updates its recorded path. A file with a physical identity the session has not seen is a new arrival.

Parameters:
Returns:

Emitted event when a state transition occurs, otherwise None.

Return type:

WatchEvent or None

reconcile(current_snapshots, *, scan_token=None)[source]

Perform a full-snapshot reconciliation against currently present files.

Parameters:
  • current_snapshots (Iterable[FileSnapshot]) – All files currently present in the watched directory.

  • scan_token (int or None, optional) – Scan token from start_scan(). If None, defaults to any active scan token or current sequence.

Returns:

Events emitted for new or woken-up arrivals during reconciliation.

Return type:

list of WatchEvent

retry(identity)[source]

Retry an arrival in FAILED state by returning it to DETECTED.

Parameters:

identity (ArrivalIdentity) – Failed arrival identity.

Returns:

Event in DETECTED state.

Return type:

WatchEvent

Raises:

ValueError – If identity is not currently in FAILED state.

snapshot(identity)[source]

Return the last known snapshot for an identity.

Parameters:

identity (ArrivalIdentity) – Arrival identity to look up.

Returns:

Snapshot if tracked, otherwise None.

Return type:

FileSnapshot or None

start_scan()[source]

Record the start of a baseline or reconciliation scan.

Returns:

Monotonic scan token.

Return type:

int

classmethod starting(root, session_id)[source]

Construct a session in the starting state before baseline enumeration.

Parameters:
  • root (Path or str) – Watched directory root.

  • session_id (str) – Unique session identifier.

Returns:

Starting watch session.

Return type:

WatchSession

state(identity)[source]

Return the current state for an identity.

Parameters:

identity (ArrivalIdentity) – Arrival identity to look up.

Returns:

Current state if tracked, otherwise None.

Return type:

WatchState or None

class adsfolio.pdf.watch_session.WatchSource(*values)[source]

Bases: str, enum.Enum

Origin of a watch observation.

CREATED = 'created'
MODIFIED = 'modified'
MOVED_IN = 'moved_in'
RECONCILE = 'reconcile'
class adsfolio.pdf.watch_session.WatchState(*values)[source]

Bases: str, enum.Enum

Watch item processing states.

DEFERRED = 'deferred'
DETECTED = 'detected'
DISMISSED = 'dismissed'
FAILED = 'failed'
PROCESSING = 'processing'
RENAMED = 'renamed'
RESOLVED = 'resolved'
STALE = 'stale'
UNRESOLVED = 'unresolved'