Skip to content

Commit e9035fb

Browse files
committed
uv-test against all supported versions
1 parent ba5c919 commit e9035fb

1 file changed

Lines changed: 110 additions & 4 deletions

File tree

uv-test

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,59 @@
44
set -eu # (no pipefail in POSIX sh)
55

66
usage() {
7-
echo "Usage: uv-test [-p|--python PY_VER] [pytest args...]"
8-
echo " -p, --python Set Python version (default: \$UV_PY or 3.14)"
9-
echo " -h, --help Show this help"
7+
echo "Usage: uv-test [-p|--python PY_VER] [-a|--all-versions] [pytest args...]"
8+
echo " -p, --python Set Python version (default: \$UV_PY or 3.14)"
9+
echo " -a, --all-versions Run tests on all minor versions from pyproject.toml"
10+
echo " -h, --help Show this help"
11+
}
12+
13+
# Extract supported Python versions from pyproject.toml
14+
get_supported_versions() {
15+
if [ ! -f pyproject.toml ]; then
16+
echo "error: pyproject.toml not found" >&2
17+
return 1
18+
fi
19+
20+
# Extract requires-python field (e.g., ">=3.10", ">=3.8,<3.13")
21+
req_python=$(grep -E 'requires-python\s*=' pyproject.toml | sed -E 's/.*"([^"]+)".*/\1/')
22+
23+
if [ -z "$req_python" ]; then
24+
echo "error: requires-python not found in pyproject.toml" >&2
25+
return 1
26+
fi
27+
28+
# Extract minimum version (e.g., ">=3.10" -> "3.10")
29+
min_ver=$(echo "$req_python" | sed -E 's/^[^0-9]*([0-9]+\.[0-9]+).*$/\1/')
30+
min_major=$(echo "$min_ver" | cut -d. -f1)
31+
min_minor=$(echo "$min_ver" | cut -d. -f2)
32+
33+
# uv doesn't support Python <= 3.7, so enforce minimum of 3.8
34+
if [ "$min_major" -eq 3 ] && [ "$min_minor" -lt 8 ]; then
35+
min_minor=8
36+
fi
37+
38+
# Extract maximum version if present (e.g., "<3.13" -> "3.13")
39+
max_ver=$(echo "$req_python" | sed -E 's/.*<\s*([0-9]+\.[0-9]+).*/\1/')
40+
if [ "$max_ver" = "$req_python" ]; then
41+
# No max version specified, use current stable (3.14 as of now)
42+
max_ver="3.14"
43+
fi
44+
max_major=$(echo "$max_ver" | cut -d. -f1)
45+
max_minor=$(echo "$max_ver" | cut -d. -f2)
46+
47+
# Generate list of minor versions
48+
versions=""
49+
current_minor=$min_minor
50+
while [ "$min_major" -eq "$max_major" ] && [ "$current_minor" -lt "$max_minor" ]; do
51+
versions="$versions $min_major.$current_minor"
52+
current_minor=$((current_minor + 1))
53+
done
54+
55+
echo "$versions"
1056
}
1157

1258
PYVER="${UV_PY:-3.14}"
59+
ALL_VERSIONS=0
1360

1461
# Parse only our flags; pass the rest to pytest
1562
while [ $# -gt 0 ]; do
@@ -18,6 +65,8 @@ while [ $# -gt 0 ]; do
1865
shift
1966
[ $# -gt 0 ] || { echo "error: -p/--python requires a version" >&2; exit 2; }
2067
PYVER="$1"; shift ;;
68+
-a|--all-versions)
69+
ALL_VERSIONS=1; shift ;;
2170
-h|--help) usage; exit 0 ;;
2271
--) shift; break ;;
2372
*) break ;;
@@ -30,4 +79,61 @@ if [ ! -f pyproject.toml ] && [ ! -f setup.py ]; then
3079
exit 1
3180
fi
3281

33-
exec uvx --python "$PYVER" --with pytest --isolated --with-editable . -- pytest "$@"
82+
# Run tests for all versions if requested
83+
if [ "$ALL_VERSIONS" -eq 1 ]; then
84+
versions=$(get_supported_versions)
85+
if [ -z "$versions" ]; then
86+
echo "error: could not determine supported Python versions" >&2
87+
exit 1
88+
fi
89+
90+
echo "Running tests for Python versions:$versions"
91+
echo ""
92+
93+
# Create a temporary directory for log files
94+
tmpdir=$(mktemp -d)
95+
trap 'rm -rf "$tmpdir"' EXIT
96+
97+
# Start all tests in parallel
98+
pids=""
99+
for ver in $versions; do
100+
(
101+
echo "========================================"
102+
echo "Testing with Python $ver"
103+
echo "========================================"
104+
uvx --python "$ver" --with pytest --isolated --with-editable . -- pytest "$@"
105+
echo "$?" > "$tmpdir/$ver.exit"
106+
) > "$tmpdir/$ver.log" 2>&1 &
107+
pids="$pids $!"
108+
done
109+
110+
# Wait for all tests to complete
111+
for pid in $pids; do
112+
wait "$pid" || true
113+
done
114+
115+
# Collect results and display logs
116+
failed_versions=""
117+
for ver in $versions; do
118+
echo ""
119+
cat "$tmpdir/$ver.log"
120+
exit_code=$(cat "$tmpdir/$ver.exit")
121+
if [ "$exit_code" -ne 0 ]; then
122+
failed_versions="$failed_versions $ver"
123+
fi
124+
done
125+
126+
echo ""
127+
echo "========================================"
128+
echo "Summary"
129+
echo "========================================"
130+
if [ -z "$failed_versions" ]; then
131+
echo "All versions passed!"
132+
exit 0
133+
else
134+
echo "Failed versions:$failed_versions"
135+
exit 1
136+
fi
137+
else
138+
exec uvx --python "$PYVER" --with pytest --isolated --with-editable . -- pytest "$@"
139+
fi

0 commit comments

Comments
 (0)