fix(release): v0.1.0 build — scipy/sklearn + wake-word failure handling #15

Merged
slaid098 merged 3 commits from fix/release/scipy-sklearn-missing into master 2026-08-11 17:02:52 +03:00
Owner

Что сделано

  • release.yml: добавлены --collect-all scipy и --collect-all scikit-learn (транзитивные deps openwakeword)
  • wake_word.py: модуль-level _load_failed флаг — после первой неудачи active_wake_word_detector() возвращает None без повторной попытки
  • cli.py: после preload — проверка active_wake_word_detector() is Nonesys.exit(1) (не бесконечный цикл с TTS)
  • tests: новый тест на failure-caching (детектор создаётся один раз, второй вызов — из кэша)

Почему

Релиз v0.1.0 не запускается: ModuleNotFoundError: scipy._external.array_api_compat.numpy.fft. PyInstaller не подобрал транзитивные deps openwakeword. Дополнительно: при ошибке загрузки — бесконечный цикл с повторением TTS-фразы каждые 2 сек

Watch out

Размер exe вырастет (~80MB scipy + ~30MB sklearn). После merge — передвинуть tag v0.1.0 на новый master, push → rebuild

Pending

Передвинуть v0.1.0 → rebuild → verify на Windows

Closes #14

## Что сделано - release.yml: добавлены `--collect-all scipy` и `--collect-all scikit-learn` (транзитивные deps openwakeword) - wake_word.py: модуль-level `_load_failed` флаг — после первой неудачи `active_wake_word_detector()` возвращает None без повторной попытки - cli.py: после preload — проверка `active_wake_word_detector() is None` → `sys.exit(1)` (не бесконечный цикл с TTS) - tests: новый тест на failure-caching (детектор создаётся один раз, второй вызов — из кэша) ## Почему Релиз v0.1.0 не запускается: `ModuleNotFoundError: scipy._external.array_api_compat.numpy.fft`. PyInstaller не подобрал транзитивные deps openwakeword. Дополнительно: при ошибке загрузки — бесконечный цикл с повторением TTS-фразы каждые 2 сек ## Watch out Размер exe вырастет (~80MB scipy + ~30MB sklearn). После merge — передвинуть tag v0.1.0 на новый master, push → rebuild ## Pending Передвинуть v0.1.0 → rebuild → verify на Windows Closes #14
fix(cli): exit on wake-word load failure instead of infinite loop
All checks were successful
CI / lint (pull_request) Successful in 1m27s
CI / complexity (pull_request) Successful in 1m26s
CI / typecheck (pull_request) Successful in 1m28s
CI / test (pull_request) Successful in 3m49s
9e9656a027
Author
Owner

Code Review Summary

Чистый фикс-PR для релиза v0.1.0: 3 бага, 3 коммита, 5 файлов, +56/-2 строк. CI зелёный, тесты покрывают новое поведение, код следует существующим конвенциям репо.

Positives

  • wake_word.py:133,150-151,158 — элегантное решение retry-loop бага: _load_failed флаг кэширует failure, повторные вызовы возвращают None без реконструкции ONNX-детектора. Логика прозрачна, порядок проверок правильный (кэш → failure → создание).
  • cli.py:55-57 — fail-fast на старте вместо бесконечного цикла с TTS-фразой каждые 2 сек. sys.exit(1) после logger.critical — правильный паттерн. while True цикл сохранён (просто недостижим при failure) — не сломана существующая структура.
  • test_wake_word.py:173-208test_active_detector_failure_cached проверяет ровно то что нужно: call_count == 1 (конструктор вызывается один раз), _load_failed is True после первой неудачи. Существующие тесты корректно обновлены (reset _load_failed = False через monkeypatch).
  • test_cli.py:29 — mock active_wake_word_detector добавлен, чтобы main() не падал на sys.exit(1) в существующем тесте loop-handles-keyboard-interrupt.
  • release.yml — минимальное изменение: только --collect-all scipy и --collect-all scikit-learn, ничего лишнего.
  • PR body качественный: ## Что сделано, ## Почему, ## Watch out, ## Pending — заполнены осмысленно. Watch out предупреждает о росте размера exe. Closes #14 привязывает issue.

Suggestions (info, not blocking)

  • wake_word.py:146global _cached_detector, _load_failed расширяет существующий global pattern (pre-existing с # noqa: PLW0603). Это устоявшийся singleton-паттерн в этом модуле, не новое нарушение. Альтернатива (класс-контейнер или functools.cache) была бы overkill для 2 переменных — текущее решение прагматично.
  • wake_word.py:133_load_failed никогда не сбрасывается в runtime. Это намеренно (процесс всё равно sys.exit(1) при failure), но если в будущем появится hot-reload моделей — понадобится reset-функция. Не блокирующее, архитектурный задел не требуется сейчас (YAGNI).

Verdict: APPROVE

## Code Review Summary Чистый фикс-PR для релиза v0.1.0: 3 бага, 3 коммита, 5 файлов, +56/-2 строк. CI зелёный, тесты покрывают новое поведение, код следует существующим конвенциям репо. ### Positives - **wake_word.py:133,150-151,158** — элегантное решение retry-loop бага: `_load_failed` флаг кэширует failure, повторные вызовы возвращают None без реконструкции ONNX-детектора. Логика прозрачна, порядок проверок правильный (кэш → failure → создание). - **cli.py:55-57** — fail-fast на старте вместо бесконечного цикла с TTS-фразой каждые 2 сек. `sys.exit(1)` после `logger.critical` — правильный паттерн. `while True` цикл сохранён (просто недостижим при failure) — не сломана существующая структура. - **test_wake_word.py:173-208** — `test_active_detector_failure_cached` проверяет ровно то что нужно: `call_count == 1` (конструктор вызывается один раз), `_load_failed is True` после первой неудачи. Существующие тесты корректно обновлены (reset `_load_failed = False` через monkeypatch). - **test_cli.py:29** — mock `active_wake_word_detector` добавлен, чтобы `main()` не падал на `sys.exit(1)` в существующем тесте loop-handles-keyboard-interrupt. - **release.yml** — минимальное изменение: только `--collect-all scipy` и `--collect-all scikit-learn`, ничего лишнего. - PR body качественный: `## Что сделано`, `## Почему`, `## Watch out`, `## Pending` — заполнены осмысленно. `Watch out` предупреждает о росте размера exe. `Closes #14` привязывает issue. ### Suggestions (info, not blocking) - **wake_word.py:146** — `global _cached_detector, _load_failed` расширяет существующий `global` pattern (pre-existing с `# noqa: PLW0603`). Это устоявшийся singleton-паттерн в этом модуле, не новое нарушение. Альтернатива (класс-контейнер или `functools.cache`) была бы overkill для 2 переменных — текущее решение прагматично. - **wake_word.py:133** — `_load_failed` никогда не сбрасывается в runtime. Это намеренно (процесс всё равно `sys.exit(1)` при failure), но если в будущем появится hot-reload моделей — понадобится reset-функция. Не блокирующее, архитектурный задел не требуется сейчас (YAGNI). ### Verdict: APPROVE
slaid098 merged commit 5bb4a5929a into master 2026-08-11 17:02:52 +03:00
slaid098 deleted branch fix/release/scipy-sklearn-missing 2026-08-11 17:02:52 +03:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
slaid098/voice_assistant!15
No description provided.