From cca7dd680f8534136a28e7b6f39c0b85c32a340e Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Thu, 22 Oct 2026 21:42:16 +0200 Subject: [PATCH] lint: clear what ruff 0.17.2 and sickdays' pylint hook flag - sickdays: normalise_keep raises TypeError (not ValueError) for a bare string -- ruff 0.17.2 TRY004; it is a caller type error, the CLI always passes a list. - sickdays: remove_sick_day and set_kept_lockers share require_sick(), which clears pylint R0801 (duplicate-code, 9.99/10 under --fail-under=10). - repo_contract/web.py: tomllib sorts as stdlib under ruff 0.17.x (I001). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01NBScELfMUiieK9ManFbS3Y --- repo_contract/web.py | 3 +-- sickdays/sickdays/_api.py | 20 +++++++++++++++----- sickdays/sickdays/_keep.py | 3 ++- sickdays/sickdays/_keep_api.py | 8 ++------ sickdays/sickdays/tests/test_keep.py | 2 +- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/repo_contract/web.py b/repo_contract/web.py index 3f74b9d..2dbef42 100644 --- a/repo_contract/web.py +++ b/repo_contract/web.py @@ -23,11 +23,10 @@ from __future__ import annotations import json import re +import tomllib from dataclasses import dataclass from pathlib import Path, PurePosixPath -import tomllib - from repo_contract.infer import _pm from repo_contract.sources import package_scripts, read_text diff --git a/sickdays/sickdays/_api.py b/sickdays/sickdays/_api.py index 004b69c..f909204 100644 --- a/sickdays/sickdays/_api.py +++ b/sickdays/sickdays/_api.py @@ -32,7 +32,7 @@ if TYPE_CHECKING: from datetime import date from pathlib import Path - from crdt_sync import Log + from crdt_sync import Log, Record from sickdays._conflict import FreePredicate @@ -47,6 +47,19 @@ def actor_id(paths: Paths | None = None) -> str: return load_device_identity(resolve_paths(paths).device_id).device_id +def require_sick(log: Log, day: date) -> Record: + """The record that makes ``day`` sick in ``log``. + + Raises: + NotSickError: ``day`` is not a sick day. + """ + existing = log.get(to_iso(day)) + if existing is None or not is_sick_record(existing): + msg = f"{to_iso(day)} is not a sick day" + raise NotSickError(msg) + return existing + + def is_sick_day( day: date | None = None, *, @@ -125,10 +138,7 @@ def remove_sick_day( resolved = resolve_paths(paths) refuse_past(day, today(now), "removed") log = read_pool_strict(resolved.log) - existing = log.get(to_iso(day)) - if existing is None or not is_sick_record(existing): - msg = f"{to_iso(day)} is not a sick day" - raise NotSickError(msg) + require_sick(log, day) entry = SickDay(day=day, is_sick=False, actor=actor_id(resolved)) write_entry(log, entry, resolved) record_event("remove", day, actor=entry.actor, paths=resolved) diff --git a/sickdays/sickdays/_keep.py b/sickdays/sickdays/_keep.py index 6670e56..6197e9a 100644 --- a/sickdays/sickdays/_keep.py +++ b/sickdays/sickdays/_keep.py @@ -58,11 +58,12 @@ def normalise_keep(keep: Iterable[str]) -> frozenset[str]: A bare string is refused rather than iterated character by character. Raises: + TypeError: ``keep`` is a bare string, not a collection of ids. ValueError: An id is not one of :data:`sickdays.LOCKERS`. """ if isinstance(keep, str): msg = f"keep must be a collection of locker ids, not the string {keep!r}" - raise ValueError(msg) + raise TypeError(msg) return frozenset(validate_locker(locker) for locker in keep) diff --git a/sickdays/sickdays/_keep_api.py b/sickdays/sickdays/_keep_api.py index 677434f..8318ae3 100644 --- a/sickdays/sickdays/_keep_api.py +++ b/sickdays/sickdays/_keep_api.py @@ -13,10 +13,9 @@ from __future__ import annotations from typing import TYPE_CHECKING -from sickdays._api import actor_id, load +from sickdays._api import actor_id, load, require_sick from sickdays._audit import record_event from sickdays._day import to_iso, today -from sickdays._errors import NotSickError from sickdays._keep import normalise_keep, read_keep, validate_locker from sickdays._model import SickDay, is_sick_record from sickdays._paths import resolve_paths @@ -98,10 +97,7 @@ def set_kept_lockers( resolved = resolve_paths(paths) refuse_past(day, today(now), "changed") log = read_pool_strict(resolved.log) - existing = log.get(to_iso(day)) - if existing is None or not is_sick_record(existing): - msg = f"{to_iso(day)} is not a sick day" - raise NotSickError(msg) + existing = require_sick(log, day) actor = actor_id(resolved) write_keep(log, existing, kept, actor=actor, resolved=resolved) record_event("keep", day, actor=actor, keep=kept, paths=resolved) diff --git a/sickdays/sickdays/tests/test_keep.py b/sickdays/sickdays/tests/test_keep.py index eaa692f..50f7e69 100644 --- a/sickdays/sickdays/tests/test_keep.py +++ b/sickdays/sickdays/tests/test_keep.py @@ -88,7 +88,7 @@ def test_validate_locker_names_the_choices() -> None: def test_normalise_deduplicates_and_refuses_junk() -> None: assert normalise_keep(["diet", "diet", "book"]) == {"book", "diet"} assert normalise_keep(()) == frozenset() - with pytest.raises(ValueError, match="not the string"): + with pytest.raises(TypeError, match="not the string"): normalise_keep("diet") with pytest.raises(ValueError, match="unknown locker"): normalise_keep(["diet", "nope"])