diff --git a/.gitignore b/.gitignore index a501167..b814f4b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ dist/ wheels/ *.egg-info .env +.coverage +**/htmlcov # Virtual environments .venv +.nox diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 0000000..a7258e8 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,101 @@ +from __future__ import annotations + +import nox + +PYTHON_VERSIONS: list[str] = ["3.11", "3.12", "3.13"] + + +@nox.session(venv_backend="uv", tags=["fix"]) +def coverage(session: nox.Session) -> None: + """Run tests with coverage reporting.""" + session.install("coverage[toml]", "pytest", "pytest-cov", "pytest-asyncio") + session.install("-e", ".") + + session.run( + "pytest", + "--cov=src", + "--cov-report=term-missing", + "--cov-report=html", + "--cov-config=pyproject.toml", + ) + + session.log("Coverage HTML report generated in htmlcov/") + + +@nox.session(venv_backend="uv", tags=["lint"]) +def ruff_check(session: nox.Session) -> None: + """Run ruff linting and formatting checks (CI-friendly, no changes).""" + session.install("ruff") + session.run( + "ruff", + "check", + ".", + "--config", + "pyproject.toml", + ) + session.run( + "ruff", + "format", + ".", + "--check", + "--config", + "pyproject.toml", + ) + + +@nox.session(venv_backend="uv", tags=["lint", "fix"]) +def ruff_check_fix(session: nox.Session) -> None: + """Run ruff linting and formatting but with a fix attempt (development).""" + session.install("ruff") + session.run( + "ruff", + "check", + ".", + "--fix", + "--config", + "pyproject.toml", + ) + session.run( + "ruff", + "check", + ".", + "--config", + "pyproject.toml", + ) + session.run( + "ruff", + "format", + ".", + "--check", + "--config", + "pyproject.toml", + ) + + +@nox.session(venv_backend="uv", tags=["lint", "fix"]) +def ruff_fix(session: nox.Session) -> None: + """Run ruff linting and formatting with auto-fix (development).""" + session.install("ruff") + session.run( + "ruff", + "check", + ".", + "--fix", + "--config", + "pyproject.toml", + ) + session.run( + "ruff", + "format", + ".", + "--config", + "pyproject.toml", + ) + + +@nox.session(python=PYTHON_VERSIONS, venv_backend="uv") +def all_versions(session: nox.Session) -> None: + """Run the unit test suite.""" + session.install("-e", ".") + session.install("pytest", "pytest-asyncio") + session.run("pytest") diff --git a/pyproject.toml b/pyproject.toml index e2db932..1192121 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,3 +62,55 @@ build-backend = "hatchling.build" testpaths = ["tests"] pythonpath = ["src"] addopts = "-v" + +[tool.ruff] +# Basic config for Ruff, feel free to adjust as needed +line-length = 88 +select = [ + "E", # pycodestyle errors (PEP 8 violations) + "F", # Pyflakes (unused imports, undefined names, etc.) + "N", # pep8-naming (naming convention violations) +] +ignore = [ + "E501", # Line too long + "F403", # 'from module import *' used; unable to detect undefined names + "F405", # Name may be undefined, or defined from star imports: module +] + +[tool.coverage.run] +branch = true +parallel = true +source = [ + "src/" +] + +[tool.coverage.paths] +equivalent = [ + "src/", + ".venv/lib/*/site-packages/", + ".venvs/*/lib/*/site-packages/", +] + +[tool.coverage.report] +precision = 2 +omit = [ + "src/*/__init__.py", + "src/*/__main__.py", + "tests/__init__.py", +] +exclude_lines = [ + "pragma: no cover", + "if TYPE_CHECKING", +] + +[tool.coverage.json] +output = "htmlcov/coverage.json" + +[tool.coverage.html] +directory = "htmlcov" + +[dependency-groups] +dev = [ + "nox>=2025.5.1", + "pytest-cov>=6.2.1", +]