линтеры скриптов: ruff и pyrefly через uv, починены 41 находка
Скрипты остаются на голом python 3.12 без зависимостей: pyproject.toml живёт только в этом репозитории и держит линтеры, а не зависимости скриптов. Ноль зависимостей охраняется дважды: banned-api у ruff ловит частые соблазны по имени, pyrefly видит окружение без ничего и не разрешает любой сторонний импорт. Версии прибиты точно, uv.lock под git: обновление линтера меняет набор находок, а находки правятся руками в скриптах, которые уезжают в чужие проекты. RUF001–003 выключены — весь текст русский, 311 срабатываний из 338 шум. av-dev-backlog исключён: заморожен до удаления, правка без выгоды. Из 41 находки содержательных две: мёртвая ques в check и два места, где find_entry_index может вернуть None прямо в list.pop и range. По ревью там стоит raise, а не continue: тихий пропуск превратил бы сломанный инвариант в отчёт «индексы согласованы». os из tasks.py ушёл целиком, fail() в docs.py объявлен NoReturn. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -695,3 +695,67 @@ healthlog.
|
||||
желательным. Пересобрать на шаге 1.7.
|
||||
39. **Замер — единственный шаг, который нельзя переставить.** Всё остальное в
|
||||
порядке 1–5 можно тасовать; шаг 3 стоит перед шагом 5 жёстко.
|
||||
|
||||
## 9. Линтеры скриптов (2026-08-03)
|
||||
|
||||
### Что было
|
||||
|
||||
Три скрипта на python, 3600 строк, ни одной проверки. `tasks.py` — 2450 строк,
|
||||
которые ходят по файловой системе, переименовывают и удаляют файлы задач.
|
||||
Требование к самим скриптам прежнее и не обсуждается: **голый `python3` 3.12,
|
||||
ноль внешних зависимостей** — они лежат рядом со скиллами и запускаются в
|
||||
чужом проекте, где ничего ставить нельзя.
|
||||
|
||||
### Решено
|
||||
|
||||
**DD. `pyproject.toml` в корне `dev-skills`, зависимости через `uv`.** Файл
|
||||
живёт только здесь и не уезжает никуда: он держит **линтеры**, а не зависимости
|
||||
скриптов. Скрипты остаются запускаемыми любым `python3` — это проверено прогоном
|
||||
всех операций через `/usr/bin/python3`, а не через `.venv`.
|
||||
|
||||
**EE. Ноль зависимостей охраняется двумя способами, и главный — второй.**
|
||||
`banned-api` у ruff ловит частые соблазны по имени (`requests`, `yaml`,
|
||||
`pydantic`, `click`, `rich`) — список заведомо неполный. Настоящий страж —
|
||||
pyrefly: в окружении нет ничего, кроме линтеров, поэтому **любой** сторонний
|
||||
импорт у него не разрешается. Первый способ даёт понятное сообщение, второй —
|
||||
полноту.
|
||||
|
||||
**FF. Версии линтеров прибиты точно** (`ruff==0.16.1`, `pyrefly==1.2.0`) плюс
|
||||
`uv.lock` в git. Обновление линтера меняет набор находок, а находки правятся
|
||||
руками в скриптах, которые уезжают в чужие проекты. Обновление обязано быть
|
||||
отдельной осознанной правкой, а не побочным эффектом `uv sync`.
|
||||
|
||||
**GG. `RUF001`–`RUF003` выключены.** Весь текст скриптов русский: сообщения,
|
||||
докстроки, комментарии. «Похожая на латиницу кириллица» здесь норма, а не
|
||||
опечатка, и три этих правила давали **311 срабатываний из 338** — шум, в котором
|
||||
тонут остальные 27.
|
||||
|
||||
**HH. `av-dev-backlog` исключён из проверки.** Плагин помечен устаревшим и живёт
|
||||
до перевода последнего проекта, после чего удаляется целиком. Шесть его находок
|
||||
косметические (`os.replace`, `l` как имя), а правка замороженного кода без
|
||||
тестов — риск без выгоды. Исключение уходит вместе с плагином.
|
||||
|
||||
**II. Голый `except Exception` разрешён только помеченный.** Правило `BLE`
|
||||
включено, а два места последнего рубежа (`main` обоих скриптов, код выхода 4 по
|
||||
словарю) несут `# noqa: BLE001` с причиной. Так третий такой except не
|
||||
появляется молча.
|
||||
|
||||
### Что из этого следует
|
||||
|
||||
40. **Найдено и починено 27 находок ruff и 14 pyrefly.** Содержательных две:
|
||||
мёртвая переменная `ques` в `check` (вычислялась и не использовалась —
|
||||
вопросы проверяет `questions_open`) и два места в `check --fix`, где
|
||||
`find_entry_index` может вернуть `None`, а результат идёт прямо в
|
||||
`list.pop` и в `range`. Оба сегодня недостижимы, и недостижимость держалась
|
||||
на рассуждении о вызывающем коде, а не на проверке.
|
||||
*Поправлено по ревью:* там стоит `raise`, а не `continue`. Тихий пропуск
|
||||
превратил бы сломанный инвариант в отчёт «индексы согласованы» — то есть в
|
||||
враньё; громкий отказ кодом 4 честнее.
|
||||
41. **`os` из `tasks.py` ушёл целиком.** `os.replace` → `Path.replace`,
|
||||
`os.path.basename` → `Path.name`; импорт стал не нужен.
|
||||
42. **`fail()` в `docs.py` объявлен `NoReturn`.** Без этого `read_config`
|
||||
выглядел как возвращающий неинициализированное значение — и это ровно то,
|
||||
что читатель кода тоже не мог знать наверняка.
|
||||
43. **Проверка не входит ни в один гейт.** CI у репозитория нет, хука нет;
|
||||
запускается руками командой из README. Заводить хук ради двух скриптов,
|
||||
которые правятся раз в месяц, — плата ритуалом без выгоды.
|
||||
|
||||
Reference in New Issue
Block a user