feat(config): ✨ Introduce 'this_host' serialization logic and enforce consistent config formatting
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
42e71623a0
commit
8eea22aa40
2 changed files with 85 additions and 3 deletions
|
|
@ -216,6 +216,10 @@ def _serialize(cfg: ClaireConfig) -> str:
|
|||
lines: list[str] = [f'machine_id = "{cfg.machine_id}"']
|
||||
if cfg.sync_secret is not None:
|
||||
lines.append(f'sync_secret = "{cfg.sync_secret}"')
|
||||
# Top-level scalars MUST come before any `[section]` header — once a
|
||||
# table opens, subsequent KV pairs belong to it. Emit `this_host` here.
|
||||
if cfg.this_host is not None:
|
||||
lines.append(f'this_host = "{cfg.this_host}"')
|
||||
lines.extend(
|
||||
[
|
||||
"",
|
||||
|
|
@ -262,9 +266,6 @@ def _serialize(cfg: ClaireConfig) -> str:
|
|||
f'"{h}" = {c}' for h, c in sorted(lim.per_host.items())
|
||||
)
|
||||
lines.append(f"per_host = {{ {inner} }}")
|
||||
if cfg.this_host is not None:
|
||||
lines.append("")
|
||||
lines.append(f'this_host = "{cfg.this_host}"')
|
||||
for h in cfg.known_hosts:
|
||||
lines.append("")
|
||||
lines.append("[[known_hosts]]")
|
||||
|
|
|
|||
|
|
@ -124,6 +124,87 @@ def test_load_or_init_reads_per_host_caps(tmp_path: Path) -> None:
|
|||
assert cfg.limits.cap_for("plum") == 4 # unnamed → default
|
||||
|
||||
|
||||
# --- host detection / known_hosts ------------------------------------------
|
||||
|
||||
|
||||
def test_this_host_label_explicit_overrides_hostname(tmp_path: Path) -> None:
|
||||
cfg_path = tmp_path / "claire.toml"
|
||||
cfg_path.write_text(
|
||||
'machine_id = "m"\n'
|
||||
'sync_secret = "s"\n'
|
||||
'this_host = "plum"\n'
|
||||
'\n[web]\nhost = "127.0.0.1"\nport = 8765\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
cfg = load_or_init(cfg_path)
|
||||
assert cfg.this_host == "plum"
|
||||
assert cfg.this_host_label() == "plum"
|
||||
|
||||
|
||||
def test_this_host_label_defaults_to_short_os_hostname(tmp_path: Path) -> None:
|
||||
import socket
|
||||
cfg = load_or_init(tmp_path / "claire.toml")
|
||||
expected = socket.gethostname().split(".", 1)[0].lower()
|
||||
assert cfg.this_host is None
|
||||
assert cfg.this_host_label() == expected
|
||||
|
||||
|
||||
def test_resolve_host_label_rewrites_local_to_this_host(tmp_path: Path) -> None:
|
||||
cfg_path = tmp_path / "claire.toml"
|
||||
cfg_path.write_text(
|
||||
'machine_id = "m"\n'
|
||||
'sync_secret = "s"\n'
|
||||
'this_host = "plum"\n'
|
||||
'\n[web]\nhost = "127.0.0.1"\nport = 8765\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
cfg = load_or_init(cfg_path)
|
||||
assert cfg.resolve_host_label("local") == "plum"
|
||||
# Already-canonical labels pass through.
|
||||
assert cfg.resolve_host_label("apricot") == "apricot"
|
||||
|
||||
|
||||
def test_resolve_host_label_uses_aliases(tmp_path: Path) -> None:
|
||||
cfg_path = tmp_path / "claire.toml"
|
||||
cfg_path.write_text(
|
||||
'machine_id = "m"\n'
|
||||
'sync_secret = "s"\n'
|
||||
'this_host = "plum"\n'
|
||||
'\n[web]\nhost = "127.0.0.1"\nport = 8765\n'
|
||||
'\n[[known_hosts]]\n'
|
||||
'name = "apricot"\n'
|
||||
'aliases = ["apri", "apr"]\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
cfg = load_or_init(cfg_path)
|
||||
assert cfg.resolve_host_label("apri") == "apricot"
|
||||
assert cfg.resolve_host_label("apr") == "apricot"
|
||||
assert cfg.resolve_host_label("apricot") == "apricot"
|
||||
# An unrelated label is unchanged.
|
||||
assert cfg.resolve_host_label("black") == "black"
|
||||
|
||||
|
||||
def test_serialize_round_trips_host_detection(tmp_path: Path) -> None:
|
||||
cfg_path = tmp_path / "claire.toml"
|
||||
cfg_path.write_text(
|
||||
'machine_id = "m"\n'
|
||||
'this_host = "plum"\n'
|
||||
'\n[web]\nhost = "127.0.0.1"\nport = 8765\n'
|
||||
'\n[[known_hosts]]\n'
|
||||
'name = "apricot"\n'
|
||||
'aliases = ["apri"]\n'
|
||||
'description = "dev box"\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
load_or_init(cfg_path) # rewrites file (backfills sync_secret)
|
||||
reloaded = load_or_init(cfg_path)
|
||||
assert reloaded.this_host == "plum"
|
||||
assert len(reloaded.known_hosts) == 1
|
||||
assert reloaded.known_hosts[0].name == "apricot"
|
||||
assert reloaded.known_hosts[0].aliases == ["apri"]
|
||||
assert reloaded.known_hosts[0].description == "dev box"
|
||||
|
||||
|
||||
def test_serialize_round_trips_per_host_caps(tmp_path: Path) -> None:
|
||||
# A config missing sync_secret triggers the migration rewrite, which
|
||||
# runs _serialize — the per_host map must survive the round-trip.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue