Skip to content

Commit fd302b5

Browse files
committed
Use nox
Nox provides a lot of utility for testing, linting, etc via the noxfile configuration. Nox has been added as a dev dependency and helped us eliminate a number of rough edges around CI linting, etc. This also now allows a local developer to run `test.sh python-all` and test all python versions locally (trivially) compared to before.
1 parent 9e195cf commit fd302b5

File tree

7 files changed

+154
-21
lines changed

7 files changed

+154
-21
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ jobs:
169169
with:
170170
fetch-depth: 0
171171
- uses: astral-sh/setup-uv@v6
172-
- run: ./script/init.sh
173172
- run: ./script/test.sh python
174173

175174
release:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@
1111
/uv.lock
1212
__pycache__
1313
/typings
14+
/.nox

noxfile.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import os
2+
3+
import nox
4+
5+
# Python versions from pyproject.toml
6+
PYTHON_VERSIONS = ["3.9", "3.10", "3.11", "3.12", "3.13"]
7+
8+
# Use uv for faster package installs
9+
nox.options.default_venv_backend = "uv"
10+
11+
12+
@nox.session(python=PYTHON_VERSIONS)
13+
def tests(session):
14+
"""Run tests with pytest-xdist parallelization."""
15+
session.install(".[test]")
16+
17+
# Pass through any arguments to pytest
18+
pytest_args = ["-vv", "-n", "auto"] + list(session.posargs)
19+
20+
# Only add -n auto if -n isn't already specified
21+
if any(arg.startswith("-n") for arg in session.posargs):
22+
pytest_args = ["-vv"] + list(session.posargs)
23+
24+
session.run("pytest", *pytest_args)
25+
26+
27+
@nox.session(python="3.11") # Single version for regular testing
28+
def test(session):
29+
"""Run tests on single Python version (faster for development)."""
30+
session.install(".[test]")
31+
32+
# Pass through any arguments to pytest
33+
pytest_args = ["-vv", "-n", "auto"] + list(session.posargs)
34+
35+
# Only add -n auto if -n isn't already specified
36+
if any(arg.startswith("-n") for arg in session.posargs):
37+
pytest_args = ["-vv"] + list(session.posargs)
38+
39+
session.run("pytest", *pytest_args)
40+
41+
42+
@nox.session(python=None) # Use current system Python, but create venv
43+
def test_current(session):
44+
"""Run tests using current system Python with isolated venv (for CI)."""
45+
session.install(".[test]")
46+
47+
# Pass through any arguments to pytest
48+
pytest_args = ["-vv", "-n", "auto"] + list(session.posargs)
49+
50+
# Only add -n auto if -n isn't already specified
51+
if any(arg.startswith("-n") for arg in session.posargs):
52+
pytest_args = ["-vv"] + list(session.posargs)
53+
54+
session.run("pytest", *pytest_args)
55+
56+
57+
@nox.session
58+
def lint(session):
59+
"""Run ruff linting (check mode)."""
60+
session.install(".[dev]")
61+
# Check if --fix is in posargs for local dev
62+
if "--fix" in session.posargs:
63+
session.run("ruff", "check", "--fix", ".")
64+
else:
65+
session.run("ruff", "check", ".")
66+
67+
68+
@nox.session
69+
def format(session):
70+
"""Format code with ruff."""
71+
session.install(".[dev]")
72+
# Check mode for CI, format mode for local
73+
if "--check" in session.posargs:
74+
session.run("ruff", "format", "--check", ".")
75+
else:
76+
session.run("ruff", "format", ".")
77+
78+
79+
@nox.session
80+
def typecheck(session):
81+
"""Run mypy type checking."""
82+
session.install(".[dev]")
83+
session.run(
84+
"mypy", ".",
85+
"--exclude", "build",
86+
"--exclude", "python/tests/cases",
87+
"--exclude", "python/tests/bad_inputs",
88+
"--exclude", "python/tests/bad_predictors",
89+
"--exclude", "python/tests/runners",
90+
"--exclude", "python/tests/schemas",
91+
"--exclude", "python/.*\\.pyi",
92+
*session.posargs
93+
)
94+
95+
96+
@nox.session
97+
def check_all(session):
98+
"""Run all checks (lint, format check, typecheck)."""
99+
session.notify("lint")
100+
session.notify("format", ["--check"])
101+
session.notify("typecheck")

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ dev = [
1818
'build',
1919
'ipython',
2020
'mypy==1.16.0', # pinned to fix CI
21+
'nox',
2122
'setuptools',
2223
]
2324

script/check.sh

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ set -uo pipefail
66

77
base_dir="$(git rev-parse --show-toplevel)"
88

9+
# Source shared functions
10+
source "$base_dir/script/functions.sh"
11+
912
check_go() {
1013
cd "$base_dir"
1114
local="$(go list -m)"
@@ -23,22 +26,16 @@ check_go() {
2326
}
2427

2528
check_python() {
26-
set -e
27-
uv sync --all-extras
29+
cd "$base_dir"
2830
if [[ -z "${CI:-}" ]]; then
29-
uv tool run ruff check --fix
30-
uv tool run ruff format
31+
# Local dev: fix and format
32+
run_nox -s lint -- --fix
33+
run_nox -s format
34+
run_nox -s typecheck
3135
else
32-
uv tool run ruff check
33-
uv tool run ruff format --check
36+
# CI: use check_all session (lint + format --check + typecheck)
37+
run_nox -s check_all
3438
fi
35-
.venv/bin/mypy . --exclude build \
36-
--exclude python/tests/cases \
37-
--exclude python/tests/bad_inputs \
38-
--exclude python/tests/bad_predictors \
39-
--exclude python/tests/runners \
40-
--exclude python/tests/schemas \
41-
--exclude 'python/.*\.pyi'
4239
}
4340

4441
check_stubs() {

script/functions.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
# Common functions for scripts
4+
5+
run_nox() {
6+
if [[ -n "${CI:-}" ]]; then
7+
# In CI, use uv tool run nox (no venv setup needed)
8+
uv tool run nox "$@"
9+
else
10+
# Local dev, use nox from .venv
11+
if [ ! -x ".venv/bin/nox" ]; then
12+
echo "Error: nox not found in .venv/bin/"
13+
echo "Run: uv pip install -e \".[dev]\" to install nox"
14+
exit 1
15+
fi
16+
.venv/bin/nox "$@"
17+
fi
18+
}

script/test.sh

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ base_dir="$(git rev-parse --show-toplevel)"
1010

1111
cd "$base_dir"
1212

13+
# Source shared functions
14+
source "$base_dir/script/functions.sh"
15+
1316
test_go() {
1417
format="dots-v2"
1518
if [ -n "${GITHUB_ACTIONS:-}" ]; then
@@ -18,13 +21,20 @@ test_go() {
1821
go run gotest.tools/gotestsum@latest --format "$format" ./... -- -timeout=30s "$@"
1922
}
2023

24+
2125
test_python() {
22-
# Only add -n auto if -n isn't already specified (supports -n <digits> or -n auto)
23-
if [[ ! "$*" =~ -n[[:space:]]*([[:digit:]]+|auto) ]]; then
24-
.venv/bin/pytest "$@" -vv -n auto
25-
else
26-
.venv/bin/pytest "$@" -vv
27-
fi
26+
# Use nox with current system Python and isolated venv
27+
run_nox -s test_current -- "$@"
28+
}
29+
30+
test_python_all() {
31+
# Test all Python versions with nox
32+
run_nox -s tests -- "$@"
33+
}
34+
35+
test_python_nox() {
36+
# Test single Python version with nox (faster for development)
37+
run_nox -s test -- "$@"
2838
}
2939

3040
if [ $# -eq 0 ]; then
@@ -40,8 +50,14 @@ else
4050
python)
4151
test_python "$@"
4252
;;
53+
python-all)
54+
test_python_all "$@"
55+
;;
56+
python-nox)
57+
test_python_nox "$@"
58+
;;
4359
*)
44-
echo "Unknown test $t"
60+
echo "Unknown test $t. Available: go, python, python-all, python-nox"
4561
exit 1
4662
;;
4763
esac

0 commit comments

Comments
 (0)