mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 22:07:15 +01:00
The three Python packages pinned ruff twice at different versions: requirements.txt at 0.16.7, .pre-commit-config.yaml at v0.15.2. Only the older one ever ran, so `select = ["ALL"]` was enforced two minor versions behind. Measured before aligning: v0.15.2 reports 0 findings, every 0.16.x reports CPY001 on each file -- 70 crdt-sync, 23 freedays, 71 gatelock, and no other rule. Resolved by adding the notice rather than ignoring the rule, so the gate keeps its teeth. Two gatelock modules sat at exactly the 250-line cap, so a one-line header tipped them to 251. Both are split along a real seam rather than shaved: _widget_fills.py colour arithmetic over LockConfig, no tkinter import _surfaces_focus.py selects among existing surfaces, never mutates them The focus split keeps _surfaces.py's documented containment (it stays the only module that creates, moves or destroys windows), and the static guard in test_recovery_invariants.py globs _surfaces*.py, so the new sibling is covered with no list to extend. widgets.py re-exports the fills helpers, which keeps gatelock.widgets the single public surface its tests import. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019kMvSMtsVMB3d2uoZ56pbp
94 lines
3.1 KiB
Python
94 lines
3.1 KiB
Python
# Copyright (c) 2026 Krzysztof Rudnicki
|
|
"""The three argument bundles :func:`crdt_sync.sync_log` takes.
|
|
|
|
Split from :mod:`crdt_sync._sync` for the 250-line cap. Grouping sync_log's
|
|
arguments into what/how/whether bundles is what keeps its signature readable;
|
|
the bundles themselves carry no behaviour.
|
|
|
|
Re-exported from :mod:`crdt_sync._sync`, so existing imports keep working.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Callable
|
|
|
|
from crdt_sync._log import Log
|
|
from crdt_sync._remote import RemoteStore
|
|
from crdt_sync._syncstate import SyncStateStore
|
|
|
|
|
|
_DEFAULT_FILENAME = "log.json"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class SyncTarget:
|
|
"""Which remote, which device, and where its logs live.
|
|
|
|
Args:
|
|
client: An authenticated :class:`RemoteStore` -- a
|
|
:class:`crdt_sync.GitHubSyncClient`, a
|
|
:class:`crdt_sync.FirebaseSyncClient`, or a mirror of both.
|
|
device_id: This device's identifier; also the directory name its own
|
|
log is pushed under.
|
|
path_prefix: The directory holding one subdirectory per device
|
|
(e.g. ``"devices"``).
|
|
legacy_device_id: The id this device pushed under before migrating to
|
|
a persisted uuid. Treated as this device's own for skip-own
|
|
purposes, so its pre-migration log is not pulled back and
|
|
re-merged as a peer's. Pass ``None`` once the old path has been
|
|
reclaimed.
|
|
"""
|
|
|
|
client: RemoteStore
|
|
device_id: str
|
|
path_prefix: str
|
|
legacy_device_id: str | None = None
|
|
|
|
@property
|
|
def own_ids(self) -> frozenset[str]:
|
|
"""Every id whose pushed log belongs to this device."""
|
|
if self.legacy_device_id is None:
|
|
return frozenset({self.device_id})
|
|
return frozenset({self.device_id, self.legacy_device_id})
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class LogCodec:
|
|
"""How a log is turned into pushed text and back.
|
|
|
|
Args:
|
|
encode: Serializes a merged log for pushing.
|
|
decode: Parses a remote device's pushed text back into a log.
|
|
Raising ``ValueError``, ``KeyError``, or ``TypeError`` is treated
|
|
as a corrupt/unparsable push, and that device is skipped for
|
|
this tick rather than aborting the whole sync.
|
|
filename: The file name each device pushes its log as.
|
|
commit_message: The commit message used for this device's push.
|
|
"""
|
|
|
|
encode: Callable[[Log], str]
|
|
decode: Callable[[str], Log]
|
|
filename: str = _DEFAULT_FILENAME
|
|
commit_message: str = "crdt_sync: update log"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class RevisionTracking:
|
|
"""Optional skip-unchanged behaviour for a tick.
|
|
|
|
Omit it entirely and the tick behaves exactly as it always did: fetch
|
|
everything, push unconditionally.
|
|
|
|
Args:
|
|
state_store: Persists what this device last pushed and last merged.
|
|
revs_path: Where revisions live; defaults to
|
|
:func:`default_revs_path`.
|
|
"""
|
|
|
|
state_store: SyncStateStore | None = None
|
|
revs_path: str | None = None
|