Skip to content

Модернизация: Python 3.14, свежие зависимости, Actions, WPS, SessionStart-хук - #2

Merged
troyan-dy merged 5 commits into
mainfrom
claude/modernize-2026-10
Oct 24, 2026
Merged

troyan-dy merged 5 commits into
mainfrom
claude/modernize-2026-10

Conversation

@troyan-dy

@troyan-dy troyan-dy commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Что обновлено

Рантайм: Python 3.13 → 3.14 (3.14.6). Версия синхронизирована в pyproject.toml (requires-python, ruff target-version, mypy python_version), .python-version, Dockerfile (ghcr.io/astral-sh/uv:python3.14-bookworm-slim) и CI.

Lock перегенерирован штатно (uv lock --upgrade). Нижние границы в pyproject.toml подтянуты к проверенным версиям.

Пакет Было Стало
aiogram 3.29.0 3.31.0
SQLAlchemy 2.0.51 2.1.6
openai 2.44.0 3.37.0
alembic 1.18.5 1.20.1
asyncpg 0.31.0 0.32.0
APScheduler 3.11.2 3.11.3 (ограничение <4)
feedparser 6.0.12 6.0.14
pydantic-settings 2.14.2 2.16.1
pydantic 2.13.4 2.13.5
aiohttp 3.14.1 3.14.5
ruff 0.15.20 0.17.2
mypy 2.1.0 2.4.0
coverage 7.14.3 7.17.0
wemake-python-styleguide — 1.8.1 (новое, + flake8 7.4.1)
pytest / pytest-asyncio / pytest-cov / loguru / aiosqlite — без изменений (уже последние)

Транзитивные замены: openai 3 перешёл с httpx/httpcore на httpx2/httpcore2, feedparser — с sgmllib3k на feedparser-sgmllib.

Изменения в коде

  • Под обновление зависимостей правки не понадобились. Используемые API работают без изменений: AsyncOpenAI(...).chat.completions.create с response_format, postgresql.insert ... on_conflict_do_nothing, async-сессии SQLAlchemy, aiogram.
  • Остальные изменения кода сделаны ради WPS (раздел ниже), поведение и публичные точки входа не менялись.

CI

  • actions/checkout v4 → v7.
  • astral-sh/setup-uv v5 → v10.3.2. Начиная с v8 плавающий мажорный тег не публикуется, поэтому версия закреплена точно (рядом есть комментарий).
  • docker/setup-qemu-action v3 → v4, docker/setup-buildx-action v3 → v4, docker/login-action v3 → v4, docker/build-push-action v6 → v7. Все используемые входы на месте.
  • Python в CI: 3.13 → 3.14.
  • Новый шаг Style (wemake-python-styleguide): uv run flake8 . --select=WPS.

WPS

  • Подключение: wemake-python-styleguide>=1.8.1 в dev-группе, flake8 7.4.1 приходит транзитивно.
  • Конфиг лежит в setup.cfg ([flake8]): select = WPS, max-line-length = 100 как у ruff, exclude для .venv, кэшей, migrations, deploy. Ruff остаётся базовым линтером.
  • Запуск: make wps, он же входит в make check. Также добавлен в CI, в SessionStart-хук (проверка, что flake8 установлен), в README и скилл /check.
  • Было 325 нарушений: 158 в app/, 167 в tests/. Сейчас flake8 --select=WPS проходит чисто.

Что исправлено в коде:

  • Однобуквенные имена и result/value/data/items заменены осмысленными.
  • Магические числа вынесены в константы: размеры колонок в models.py (схема не изменилась, alembic check чистый), _MAX_HOUR, _MIN_FETCH, _PICK_TEMPERATURE, _MISFIRE_GRACE_SECONDS и т.д.
  • Разбиты сложные функции:
    • pipeline.run_once → _collect_candidates / _select_candidates / _unpublished_fallback / _choose / _post_entry;
    • _publish → _send_media / _send_video / _send_photo / _send_gallery;
    • rss._extract_images → генераторы _media_image_urls и _html_image_urls;
    • в handlers: добавление канала → _resolve_chat / _check_can_post / _store_channel, разбор ссылки → _parse_tme_path, статус → _status_block;
    • main() → _prepare / _start_services / _poll / _shutdown.
  • В deepseek: functools.cache вместо global _client; разбор ответа модели вынесен в _extract_pick / _parse_pick с той же логикой отката на 0.
  • TONES и TONE_BTN_TEXTS стали неизменяемыми (MappingProxyType).
  • Строковые конкатенации и сложные f-строки переписаны.
  • Тесты: переименования, _channel(**overrides) вместо функции с 8 аргументами, без трюка (_ for _ in ()).throw и лишних лямбд.

Оставшиеся точечные noqa (с причиной):

Где Правило Почему
app/main.py, app/scheduler/worker.py WPS476 (await в цикле) каналы прогоняются последовательно намеренно, чтобы не делать пачку запросов к API
app/main.py WPS501 (try/finally без except) обычная очистка ресурсов, исключения должны пробрасываться как раньше
app/bot/fsm_storage.py WPS110 (data) имя параметра задаёт интерфейс aiogram BaseStorage.set_data
app/models.py WPS110 (value) имя колонки — часть схемы БД

per-file-ignores в setup.cfg (глобального ignore нет):

Файл Правила Почему
app/bot/handlers.py WPS201, WPS202, WPS204, WPS347 aiogram-роутер: все хендлеры в одном модуле на одном Router; охранные channel is None и т.п. повторяются в каждом хендлере; F — канонический импорт magic filter
app/bot/fsm_storage.py WPS615 get_state/set_state/get_data/set_data — интерфейс BaseStorage
app/main.py WPS201, WPS202 точка входа связывает все подсистемы
app/pipeline.py, app/services/rss.py, app/storage.py WPS202 плоские модули из маленьких функций (по функции на шаг или операцию с БД)
app/tone.py WPS432 температура в таблице пресетов — данные, а не магическое число
tests/*.py WPS118, WPS202, WPS204, WPS210, WPS217, WPS218, WPS219, WPS226, WPS430, WPS431, WPS432 тестовые конвенции: литералы и числа в фикстурах и ассертах, длинные описательные имена, фейки внутри тестов, много ассертов и await в одном сценарии

SessionStart-хук

Добавлен .claude/hooks/session-start.sh (исполняемый, set -euo pipefail), зарегистрирован в .claude/settings.json (секция hooks.SessionStart). Существующие permissions сохранены.

  • Работает только при CLAUDE_CODE_REMOTE=true, локально сразу выходит с кодом 0.
  • Если uv нет, ставит его официальным установщиком и добавляет в PATH через $CLAUDE_ENV_FILE.
  • Выполняет uv sync --frozen с dev-группой: ruff, mypy, pytest, WPS. Python uv скачает сам по .python-version. Хук идемпотентен.
  • В конце быстрая проверка flake8 --version / ruff --version.
  • Режим синхронный: тесты и линтеры готовы с первой команды.

Что проверено

  • Установка с нуля (rm -rf .venv → хук → uv sync --frozen) на Python 3.14.6: ✅
  • make check:
    • ruff ✅
    • WPS ✅ (0 нарушений)
    • mypy ✅ (17 файлов)
    • pytest ✅ 157 passed, покрытие 97.3% (порог 90%)
  • pytest -W error::DeprecationWarning ✅
  • python -m compileall app migrations и импорт всех модулей ✅
  • На реальном PostgreSQL 16 (и до WPS-рефакторинга, и после):
    • alembic upgrade head ✅;
    • alembic check → «No new upgrade operations detected» ✅;
    • смоук storage (add_channel → mark_seen ×2 с повторной публикацией через fallback → filter_unseen / published_among / recent_published_titles → delete_channel) ✅
  • Хук:
    • первый запуск ✅;
    • повторный (ничего не делает) ✅;
    • без CLAUDE_CODE_REMOTE выходит с кодом 0 ✅
  • Тег ghcr.io/astral-sh/uv:python3.14-bookworm-slim существует (проверено через registry). Сам Docker-образ локально не собирался: в контейнере закрыт доступ к блобам GHCR.

Что не обновлено и почему

  • APScheduler 4.x: стабильного релиза нет, а API полностью новый. Добавлено ограничение <4, чтобы будущий релиз не сломал планировщик.
  • Базовый образ оставлен на bookworm, на trixie не переводил: это смена дистрибутива, а не обновление зависимости.
  • alembic check в CI так и не запускается (нужен Postgres-сервис). Не стал расширять CI сверх задачи.
  • pre-commit в проекте нет, поэтому WPS туда не добавлялся.

Риски

  • openai 2 → 3 и SQLAlchemy 2.0 → 2.1 — мажорный и минорно-ломающий апгрейды. Тесты работают на моках и SQLite. Путь через Postgres проверен вручную, а реальный вызов DeepSeek не делался (ключа нет). После деплоя стоит прогнать /preview или /run на одном канале.
  • WPS-рефакторинг затрагивает pipeline, handlers, main без изменения поведения. Все 157 тестов проходят, покрытие выросло. main.py и worker.py юнит-тестами не покрыты (исключены из coverage), их проверял только импортом.
  • Мультиарх-сборку build-push с новыми docker-actions проверит только push в main.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DPytQbDGMNbeLuCcazo3ha

uv lock --upgrade: aiogram 3.31, SQLAlchemy 2.1, openai 3.37, alembic 1.20,
asyncpg 0.32, pydantic-settings 2.16, ruff 0.17, mypy 2.4 и др. Нижние
границы в pyproject подтянуты к проверенным версиям; apscheduler ограничен
<4 (4.x — несовместимый API). Python 3.14 синхронизирован в pyproject,
.python-version, ruff/mypy и Dockerfile. Код правок не потребовал.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DPytQbDGMNbeLuCcazo3ha
Хук (.claude/hooks/session-start.sh) в облачной сессии (CLAUDE_CODE_REMOTE=true)
ставит uv при отсутствии и делает uv sync --frozen — сразу работают make check,
pytest, ruff, mypy. Локально ничего не делает.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DPytQbDGMNbeLuCcazo3ha
WPS в dev-группе (flake8 7.4 транзитивно), конфиг [flake8] в setup.cfg:
select = WPS, max-line-length = 100 как у ruff, исключены migrations/deploy,
точечные per-file-ignores с обоснованием. Запуск `make wps` входит в
`make check`, добавлен шаг в CI, SessionStart-хук проверяет, что flake8/ruff
установлены. Обновлены README и скилл /check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DPytQbDGMNbeLuCcazo3ha
325 нарушений → 0: осмысленные имена вместо однобуквенных и result/value/data,
магические числа → константы, сложные функции разбиты на шаги (pipeline.run_once,
_publish, rss._extract_images, добавление канала и статус в handlers, main),
неизменяемые константы-маппинги (MappingProxyType), functools.cache вместо
global в deepseek. Оставшееся — точечные noqa с причиной и per-file-ignores.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DPytQbDGMNbeLuCcazo3ha
@troyan-dy troyan-dy changed the title Модернизация: Python 3.14, свежие зависимости, Actions, SessionStart-хук Модернизация: Python 3.14, свежие зависимости, Actions, WPS, SessionStart-хук Oct 24, 2026
@troyan-dy
troyan-dy merged commit 090b844 into main Oct 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants