Pre-flight
Problem or motivation
Interactive editors hold a configuration between begin and apply. The current save API cannot express “write only if the file is still the revision I read.”
Hashing before save detects many stale drafts, but a comparison followed later by os.replace() is not compare-and-swap: two writers can pass the same check and then replace in sequence.
Proposed solution
Expose an opaque revision token for both existing and absent destinations, plus conditional save:
def stack_config_revision(path: Path = CONFIG_PATH) -> str:
"""Return an opaque token, including a stable state for a missing file."""
def save_stack_config(
config: StackConfig,
path: Path = CONFIG_PATH,
*,
expected_revision: str | None = None,
) -> Path:
"""Write unconditionally when no token is supplied; otherwise require it."""
The missing-file token avoids overloading None as both “unconditional” and “expected not to exist.” Exact token encoding is private.
All official writers that promise cooperative no-clobber behaviour should use a short exclusive lock covering:
Do not hold the lock for the lifetime of an interactive wizard.
Non-cooperating manual editors cannot be fully excluded; the documented guarantee applies to cooperating writers.
Alternatives considered
No response
Pre-flight
Problem or motivation
Interactive editors hold a configuration between begin and apply. The current save API cannot express “write only if the file is still the revision I read.”
Hashing before save detects many stale drafts, but a comparison followed later by os.replace() is not compare-and-swap: two writers can pass the same check and then replace in sequence.
Proposed solution
Expose an opaque revision token for both existing and absent destinations, plus conditional save:
The missing-file token avoids overloading None as both “unconditional” and “expected not to exist.” Exact token encoding is private.
All official writers that promise cooperative no-clobber behaviour should use a short exclusive lock covering:
Do not hold the lock for the lifetime of an interactive wizard.
Non-cooperating manual editors cannot be fully excluded; the documented guarantee applies to cooperating writers.
Alternatives considered
No response