[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "audio-scribe" version = "0.1.0" description = "Download videos, extract FLAC, and transcribe with Whisper on whatever GPU is present." requires-python = ">=3.12" dependencies = [ "click>=8.1,<9", "numpy>=2.5,<3", "huggingface-hub>=1.31,<2", "yt-dlp[default,deno]>=2026.8.19", "yt-dlp-ejs>=0.8", "openvino==2026.3.1", "openvino-genai==2026.3.1.0", ] [project.scripts] audio-scribe = "audio_scribe.cli:main" [dependency-groups] dev = [ "pytest>=8", "pytest-cov>=5", "ruff>=0.6", "pyright>=1.1.380", "mypy>=1.11", "pylint>=3.2", "pre-commit>=3.8", ] [tool.hatch.build.targets.wheel] packages = ["src/audio_scribe"] [tool.ruff] line-length = 100 src = ["src", "tests"] # ruff format also restyles Python blocks inside Markdown; docs are not ours to restyle. extend-exclude = ["*.md"] [tool.ruff.lint] select = ["E", "F", "W", "I", "N", "UP", "B", "A", "C4", "SIM", "PTH", "RET", "ARG", "TID", "TC", "RUF", "S"] # S607: binaries are looked up on PATH on purpose and preflight-checked with # shutil.which; hardcoding absolute paths would be less portable, not safer. ignore = ["S607"] [tool.ruff.lint.per-file-ignores] # S101: asserts are the point of a test file. "tests/*" = ["ARG001", "ARG002", "S101"] # Throwaway benchmarks, not pipeline code. "scripts/*" = ["S603"] [tool.pyright] include = ["src", "tests"] typeCheckingMode = "strict" venvPath = "." venv = ".venv" [tool.mypy] strict = true files = ["src", "tests"] [[tool.mypy.overrides]] # These ship no py.typed marker. module = ["openvino.*", "openvino_genai.*", "huggingface_hub.*", "yt_dlp.*"] ignore_missing_imports = true [tool.pylint.design] max-attributes = 20 # Keyword-only arguments do not carry the readability cost this check guards against. max-args = 10 # Pipeline entry points carry injectable seams for testing. max-locals = 18 [tool.pylint.main] # W0621: pytest fixtures shadow their names by design. # C1803: asserting == () is more precise than truthiness about what a call returns. # R0903: dataclasses and pytest grouping classes legitimately have few methods. disable = [ "C0114", "C0115", "C0116", "C0301", "W0611", "W0612", "W0621", "R0801", "R0903", "C1803", ] [tool.pytest.ini_options] testpaths = ["tests"] # NOTE: --cov-fail-under deliberately lives in the pre-commit hook, not here, so a # single-file TDD run (`uv run pytest tests/test_x.py`) is not blocked by coverage. addopts = "-q" [tool.coverage.run] branch = true source = ["src/audio_scribe"] [tool.coverage.report] fail_under = 100 show_missing = true exclude_also = [ "if TYPE_CHECKING:", 'if __name__ == "__main__":', "@overload", "raise NotImplementedError", "class .*\\(Protocol\\):", ]