docs: добавлены docstrings и расширен CONTRIBUTING.md

- Зачем:
  - покрытие документацией было неравномерным, отсутствовало архитектурное описание
- Что:
  - добавлены модульные docstrings во все 5 модулей (utils, config, formatter, transcriber, cli)
  - добавлены docstrings для всех публичных функций без документации
  - добавлены inline-комментарии для неочевидной логики (CUDA fallback, strict device, glob, SOCKS proxy)
  - CONTRIBUTING.md: секции «Архитектура», «Ключевые решения», «Тестирование», «Частые задачи»
  - обновлено правило языка комментариев (русский вместо английского)
- Проверка:
  - uv run pytest (97 passed, 1 skipped)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-18 23:25:17 +03:00
co-authored by Claude Opus 4.6
parent 87f7dc1723
commit ac8ea508ce
6 changed files with 100 additions and 2 deletions
+21
View File
@@ -1,3 +1,5 @@
"""Утилиты для валидации входных файлов, определения устройства и работы с путями."""
import glob
import shutil
import subprocess
@@ -11,6 +13,11 @@ SUPPORTED_EXTENSIONS = {
def detect_device(requested: str = "auto") -> str:
"""Определяет устройство для вычислений.
При ``requested="auto"`` проверяет наличие ``nvidia-smi`` в PATH
и возвращает ``"cuda"`` или ``"cpu"``. Явное значение возвращается как есть.
"""
if requested != "auto":
return requested
if shutil.which("nvidia-smi") is not None:
@@ -19,6 +26,7 @@ def detect_device(requested: str = "auto") -> str:
def get_gpu_name() -> str | None:
"""Возвращает название GPU через ``nvidia-smi`` (для метаданных транскрипта)."""
try:
result = subprocess.run(
["nvidia-smi", "--query-gpu=name", "--format=csv,noheader"],
@@ -37,6 +45,12 @@ def get_gpu_name() -> str | None:
def validate_input_file(path: Path) -> Path:
"""Проверяет существование, непустоту и расширение файла.
Неизвестное расширение — предупреждение, а не ошибка: файл может оказаться
корректным контейнером, просто с нестандартным суффиксом.
Возвращает resolved-путь.
"""
if not path.exists():
raise FileNotFoundError(f"Файл не найден: {path}")
if not path.is_file():
@@ -53,12 +67,18 @@ def validate_input_file(path: Path) -> Path:
def build_output_path(input_path: Path, output: Path | None = None) -> Path:
"""Строит путь выходного файла: ``<имя>-transcript.md`` рядом с исходным."""
if output is not None:
return output
return input_path.with_stem(input_path.stem + "-transcript").with_suffix(".md")
def expand_globs(paths: list[Path]) -> list[Path]:
"""Раскрывает glob-паттерны в списке путей с дедупликацией.
Typer на Windows не раскрывает ``*.mp4`` самостоятельно,
поэтому глобы обрабатываются вручную. Дедупликация — по resolved-пути.
"""
seen: set[Path] = set()
result: list[Path] = []
for p in paths:
@@ -76,4 +96,5 @@ def expand_globs(paths: list[Path]) -> list[Path]:
def has_existing_transcript(input_path: Path) -> bool:
"""Проверяет наличие транскрипта для skip-логики батч-режима."""
return build_output_path(input_path).exists()