Skip to content

Commit 5ecf4b6

Browse files
add nox and test against different Python and Django versions
1 parent 074c10b commit 5ecf4b6

File tree

5 files changed

+290
-7
lines changed

5 files changed

+290
-7
lines changed

.github/workflows/test.yml

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,35 @@ env:
1616
PYTHONUNBUFFERED: "1"
1717

1818
jobs:
19+
generate-matrix:
20+
runs-on: ubuntu-latest
21+
outputs:
22+
matrix: ${{ steps.set-matrix.outputs.matrix }}
23+
steps:
24+
- uses: actions/checkout@v4
25+
26+
- name: Install uv
27+
uses: astral-sh/setup-uv@v5
28+
with:
29+
enable-cache: true
30+
pyproject-file: pyproject.toml
31+
32+
- id: set-matrix
33+
run: |
34+
uv run nox --session "gha_matrix"
35+
1936
test:
37+
name: Python ${{ matrix.python-version }}, Django ${{ matrix.django-version }} (${{ matrix.os }})
2038
runs-on: ${{ matrix.os }}
39+
needs: generate-matrix
2140
strategy:
2241
fail-fast: false
2342
matrix:
2443
os:
2544
- macos-latest
2645
- ubuntu-latest
2746
- windows-latest
47+
include: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
2848
steps:
2949
- uses: actions/checkout@v4
3050

@@ -34,10 +54,6 @@ jobs:
3454
enable-cache: true
3555
pyproject-file: pyproject.toml
3656

37-
- name: Install dependencies and build
38-
run: |
39-
uv sync --frozen
40-
uv run maturin build
41-
4257
- name: Run tests
43-
run: cargo test --verbose
58+
run: |
59+
uv run nox --session "tests(python='${{ matrix.python-version }}', django='${{ matrix.django-version }}')" -- --slow

Justfile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ mod docs ".just/docs.just"
88
default:
99
@just --list
1010

11+
[private]
12+
nox SESSION *ARGS:
13+
uv run nox --session "{{ SESSION }}" -- "{{ ARGS }}"
14+
1115
bumpver *ARGS:
1216
uv run --with bumpver bumpver {{ ARGS }}
1317

@@ -17,4 +21,10 @@ clean:
1721
# run pre-commit on all files
1822
lint:
1923
@just --fmt
20-
uv run --with pre-commit-uv pre-commit run --all-files
24+
@just nox lint
25+
26+
test *ARGS:
27+
@just nox test {{ ARGS }}
28+
29+
testall *ARGS:
30+
@just nox tests {{ ARGS }}

noxfile.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
from __future__ import annotations
2+
3+
import json
4+
import os
5+
from pathlib import Path
6+
7+
import nox
8+
9+
nox.options.default_venv_backend = "uv|virtualenv"
10+
nox.options.reuse_existing_virtualenvs = True
11+
12+
PY39 = "3.9"
13+
PY310 = "3.10"
14+
PY311 = "3.11"
15+
PY312 = "3.12"
16+
PY313 = "3.13"
17+
PY_VERSIONS = [PY39, PY310, PY311, PY312, PY313]
18+
PY_DEFAULT = PY_VERSIONS[0]
19+
PY_LATEST = PY_VERSIONS[-1]
20+
21+
DJ42 = "4.2"
22+
DJ50 = "5.0"
23+
DJ51 = "5.1"
24+
DJMAIN = "main"
25+
DJMAIN_MIN_PY = PY312
26+
DJ_VERSIONS = [DJ42, DJ50, DJ51, DJMAIN]
27+
DJ_LTS = [
28+
version for version in DJ_VERSIONS if version.endswith(".2") and version != DJMAIN
29+
]
30+
DJ_DEFAULT = DJ_LTS[0]
31+
DJ_LATEST = DJ_VERSIONS[-2]
32+
33+
34+
def version(ver: str) -> tuple[int, ...]:
35+
"""Convert a string version to a tuple of ints, e.g. "3.10" -> (3, 10)"""
36+
return tuple(map(int, ver.split(".")))
37+
38+
39+
def should_skip(python: str, django: str) -> bool:
40+
"""Return True if the test should be skipped"""
41+
42+
if django == DJMAIN and version(python) < version(DJMAIN_MIN_PY):
43+
# Django main requires Python 3.10+
44+
return True
45+
46+
if django == DJ51 and version(python) < version(PY310):
47+
# Django 5.1 requires Python 3.10+
48+
return True
49+
50+
if django == DJ50 and version(python) < version(PY310):
51+
# Django 5.0 requires Python 3.10+
52+
return True
53+
54+
return False
55+
56+
57+
@nox.session
58+
def test(session):
59+
session.notify(f"tests(python='{PY_DEFAULT}', django='{DJ_DEFAULT}')")
60+
61+
62+
@nox.session
63+
@nox.parametrize(
64+
"python,django",
65+
[
66+
(python, django)
67+
for python in PY_VERSIONS
68+
for django in DJ_VERSIONS
69+
if not should_skip(python, django)
70+
],
71+
)
72+
def tests(session, django):
73+
session.run_install(
74+
"uv",
75+
"sync",
76+
"--frozen",
77+
"--inexact",
78+
"--no-install-package",
79+
"django",
80+
"--python",
81+
session.python,
82+
env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location},
83+
)
84+
85+
if django == DJMAIN:
86+
session.install(
87+
"django @ https://github.com/django/django/archive/refs/heads/main.zip"
88+
)
89+
else:
90+
session.install(f"django=={django}")
91+
92+
command = ["cargo", "test"]
93+
if session.posargs:
94+
args = []
95+
for arg in session.posargs:
96+
if arg:
97+
args.extend(arg.split(" "))
98+
command.extend(args)
99+
session.run(*command, external=True)
100+
101+
102+
@nox.session
103+
def lint(session):
104+
session.run(
105+
"uv",
106+
"run",
107+
"--with",
108+
"pre-commit-uv",
109+
"--python",
110+
PY_LATEST,
111+
"pre-commit",
112+
"run",
113+
"--all-files",
114+
)
115+
116+
117+
@nox.session
118+
def gha_matrix(session):
119+
sessions = session.run("nox", "-l", "--json", silent=True)
120+
matrix = {
121+
"include": [
122+
{
123+
"python-version": session["python"],
124+
"django-version": session["call_spec"]["django"],
125+
}
126+
for session in json.loads(sessions)
127+
if session["name"] == "tests"
128+
]
129+
}
130+
with Path(os.environ["GITHUB_OUTPUT"]).open("a") as fh:
131+
print(f"matrix={matrix}", file=fh)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ build-backend = "maturin"
66
dev = [
77
"django-stubs>=5.1.1",
88
"maturin>=1.7.8",
9+
"nox[uv]>=2025.2.9",
910
"ruff>=0.8.2",
1011
]
1112
docs = [

uv.lock

Lines changed: 125 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)