[build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" [project] name = "aTrain" description = "aTrain is a tool for automatically transcribing speech recordings utilizing state-of-the-art machine learning models without uploading any data." authors = [ { name = "Armin Haberl", email = "armin.haberl@uni-graz.at" }, { name = "Jürgen Fleiß", email = "juergen.fleiss@uni-graz.at" }, { name = "Dominik Kowald", email = "dkowald@know-center.at" }, { name = "Stefan Thalmann", email = "stefan.thalmann@uni-graz.at" }, ] dynamic = ["version"] readme = "README.md" license = "AGPL-3.0-or-later" requires-python = ">=3.11" dependencies = [ # Engine (formerly aTrain_core's own dependencies; consolidated post-monorepo merge) "faster-whisper==1.2.1", # faster-whisper 1.2.1 calls av.open(metadata_errors=...), which av 19 removed. "av<19", # CrisperWhisper v2 uses this Transformers-only path. Do not add its # CTranslate2 extra (a incompatible fork of Ctranslate2 used by faster-whisper): "crisperwhisper[transformers]==2.0.3", "transformers==4.57.3", "pandas==3.0.6", "pyannote.audio==4.0.7", "numpy==2.4.6", "werkzeug==3.1.9", # transformers 4.57 requires >=0.34; keep this below 1 until all callers # have been evaluated against the Hub 1.x API. "huggingface-hub==0.36.0", "torch==2.9.1+cu128; sys_platform == 'win32'", "torch==2.9.1; sys_platform != 'win32'", # torchaudio must match torch (ABI-coupled); keep in lockstep with the pins above. "torchaudio==2.9.1+cu128; sys_platform == 'win32'", "torchaudio==2.9.1; sys_platform != 'win32'", "typer==0.27.3", "platformdirs==4.12.4", "jiwer==4.0.0", ] [project.optional-dependencies] # Install with `pip install 'aTrain[gui]'` to use the GUI / desktop window. # Without these, `aTrain start` fails with a clean error pointing here; # headless CLI (`aTrain_core transcribe …`, `aTrain init`) works on the # base install. gui = [ "nicegui==3.18.0", "pywebview==6.2.1", "pywebview[GTK]; sys_platform == 'linux'", "show-in-file-manager==1.1.6", "wakepy==1.0.0", "dask; sys_platform == 'linux'", ] [tool.setuptools.packages.find] where = ["."] include = ["aTrain*"] [tool.setuptools.package-data] # Ship the engine's JSON config, loaded at runtime via # importlib.resources.files("aTrain_core.data"). Without this the wheel omits # them and a non-editable `pip install` breaks at startup; CI only passes # because the tests run from the source tree. aTrain_core = ["data/*.json"] [project.scripts] aTrain = "aTrain.app:cli" aTrain_core = "aTrain_core.cli:cli" [tool.setuptools.dynamic] version = { attr = "aTrain.version.__version__" } [tool.uv] # torch+cu128 wheels live only on download.pytorch.org; PyPI rejects # local-version tags (+...), so cross-index name collision is impossible. index-strategy = "unsafe-best-match" [[tool.uv.index]] name = "pytorch-cu128" url = "https://download.pytorch.org/whl/cu128" explicit = true # only used when [tool.uv.sources] points at it (win32 torch+cu128). Without this, unsafe-best-match would also pull cu128 wheels on Linux, which break the torchcodec binary ABI. [tool.uv.sources] torch = [{ index = "pytorch-cu128", marker = "sys_platform == 'win32'" }] torchaudio = [{ index = "pytorch-cu128", marker = "sys_platform == 'win32'" }] torchvision = [{ index = "pytorch-cu128", marker = "sys_platform == 'win32'" }] [dependency-groups] dev = [ "ruff>=0.15.0", "bandit[toml]>=1.9.0", "pip-audit>=2.10.0", ] [tool.bandit] # CI runs `bandit -r aTrain aTrain_core`; these excludes keep ad-hoc local # runs from descending into build/venv/model dirs. exclude_dirs = [".venv", "build", "dist", "aTrain.egg-info", "aTrain_core.egg-info", "aTrain/required_models"] [tool.pytest.ini_options] testpaths = ["tests"] # NiceGUI's `user` fixture (UI E2E) is async; auto mode lets pytest-asyncio # handle async tests/fixtures without per-item markers. asyncio_mode = "auto" # nicegui>=3's `user` fixture executes a main file per test (replaces the # 2.x `module_under_test` marker); see tests/ui/main.py. main_file = "tests/ui/main.py"