diff --git a/src/repoma/check_dev_files/__init__.py b/src/repoma/check_dev_files/__init__.py index e7f20eeb..b98836ca 100644 --- a/src/repoma/check_dev_files/__init__.py +++ b/src/repoma/check_dev_files/__init__.py @@ -33,6 +33,7 @@ ruff, setup_cfg, toml, + tox, update_pip_constraints, vscode, ) @@ -96,6 +97,7 @@ def main(argv: Sequence[str] | None = None) -> int: executor(vscode.main, has_notebooks) executor(gitpod.main, args.no_gitpod, dev_python_version) executor(precommit.main) + executor(tox.main, has_notebooks) return executor.finalize(exception=False) diff --git a/src/repoma/check_dev_files/tox.py b/src/repoma/check_dev_files/tox.py new file mode 100644 index 00000000..656dbfe3 --- /dev/null +++ b/src/repoma/check_dev_files/tox.py @@ -0,0 +1,46 @@ +"""Check Tox configuration file.""" + +from __future__ import annotations + +from configparser import ConfigParser +from pathlib import Path + +from repoma.errors import PrecommitError +from repoma.utilities import CONFIG_PATH + + +def main(has_notebooks: bool) -> None: + if not CONFIG_PATH.tox.exists(): + return + tox = _read_tox_config(CONFIG_PATH.tox) + _check_expected_sections(tox, has_notebooks) + + +def _read_tox_config(path: Path) -> ConfigParser: + config = ConfigParser() + config.read(path) + return config + + +def _check_expected_sections(tox: ConfigParser, has_notebooks: bool) -> None: + # cspell:ignore doclive docnb docnblive testenv + sections: set[str] = set(tox) + expected_sections: set[str] = set() + if Path("docs").exists(): + expected_sections |= { + "testenv:doc", + "testenv:doclive", + } + if has_notebooks: + expected_sections |= { + "testenv:docnb", + "testenv:docnblive", + "testenv:nb", + } + missing_sections = expected_sections - sections + if missing_sections: + msg = ( + f"{CONFIG_PATH.tox} is missing job definitions:" + f" {', '.join(sorted(missing_sections))}" + ) + raise PrecommitError(msg)