alunduil / alunduil/zfs-replicate

Task invariants are encoded in the type system via a discriminated union

Aperta
#433 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
enhancement no-issue-activity
Lingua principale
Python
Stelle
24
Fork
6
Merge medio
3h 11m
PR unite (30g)
49

Descrizione

## User story

As a **contributor changing task-handling code**, I want **the `Task` type to make "CREATE/SEND/DESTROY with or without a snapshot" illegal-by-construction** so that **I cannot accidentally read `task.snapshot` for a CREATE task and I do not need `optional.value()` to paper over the gap**.

## Why

`zfs/replicate/task/type.py` declares:

```python
@dataclass
class Task:
action: Action
filesystem: FileSystem
snapshot: Optional[Snapshot]
```

`Task.snapshot is None` is only legal for some action values. The codebase handles the mismatch at runtime: `zfs/replicate/optional.py` raises `RuntimeError("unexpected None")` at `zfs/replicate/task/execute.py:68` when the invariant is violated. A discriminated union encoded via Python's `typing.Union`/`|` plus frozen dataclasses moves this to compile-time (or at least mypy-time).

## Acceptance criteria

- [ ] New types: `CreateFilesystemTask(filesystem)`, `SendSnapshotTask(filesystem, snapshot)`, `DestroyFilesystemTask(filesystem)`, `DestroySnapshotTask(filesystem, snapshot)` — all `dataclass(frozen=True)`.
- [ ] A `Task = CreateFilesystemTask | SendSnapshotTask | DestroyFilesystemTask | DestroySnapshotTask` type alias (PEP 604).
- [ ] `task.generate` produces concrete task types; `task.execute` uses a `match` statement (Python 3.10+) to dispatch.
- [ ] `zfs/replicate/optional.py` is deleted (no remaining callers).
- [ ] mypy `--strict` still passes.
- [ ] All tests pass without changes to their expected outputs (task semantics are preserved; only the encoding changed).
- [ ] `report.py` adapts to the new types.

## Out of scope

- Changes to `Action` enum (it may or may not remain useful for grouping — pick one).

## Notes

- Target release: **none — chore** (no CLI change)
- Depends on: Python 3.8/3.9 support removal (for `match` statements).
- Source: modernization assessment §3.7.

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.