Replace Nox with uv Multi-Version Testing Implementation Plan⚓︎
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Replace the nox-based multi-Python test runner with a test.multi calcipy task that uses uv run --python directly, eliminating the noxfile.py boilerplate from every downstream project.
Architecture: A new multi task in calcipy/tasks/test.py reads Python versions from get_tool_versions() (already used by the noxfile) and runs uv run --python {ver} pytest ./tests for each, using UV_PROJECT_ENVIRONMENT=.uv-tests/py{ver} to maintain per-version persistent envs (mirroring nox’s reuse_venv=True). The nox.py task is soft-deprecated but kept for one-off use. The template’s noxfile.py boilerplate is removed.
Tech Stack: Python, uv, invoke, corallium (get_tool_versions), pytest
File Map⚓︎
| File | Action | Responsibility |
|---|---|---|
calcipy/tasks/test.py |
Modify | Add multi task |
calcipy/tasks/nox.py |
Modify | Add deprecation note in docstring |
calcipy/tasks/all_tasks.py |
Modify | Replace nox.noxfile with test.multi in _OTHER_TASKS |
tests/tasks/test_test.py |
Modify | Add tests for multi |
calcipy/noxfile/_noxfile.py |
Modify | Add deprecation note |
calcipy_template/package_template/noxfile.py |
Delete | No longer needed |
calcipy_template/.ctt/default/noxfile.py |
Delete | No longer needed |
pyproject.toml |
Modify | Remove nox from recommended optional-dependency |
.gitignore |
Modify | Add .uv-tests/ |
docs/README.md |
Modify | Replace nox usage with calcipy test.multi |
Task 1: Add test.multi task⚓︎
Files:
- Modify:
calcipy/tasks/test.py - Test:
tests/tasks/test_test.py
Background: get_tool_versions() is from corallium.file_helpers and returns a dict like {'python': ['3.10.11', '3.13.11']}. The version strings are full semver (e.g. 3.13.11). uv run --python 3.13.11 accepts this. The env directory slug strips the patch so 3.13.11 → py3.13 for a stable cache path across patch upgrades.
The run(ctx, cmd, **kwargs) helper (in calcipy/invoke_helpers.py) passes all kwargs through to ctx.run(), so passing env= works as-is.
- Step 1: Write the failing test
In tests/tasks/test_test.py, add at the top of the parametrize list and add a standalone test (because get_tool_versions needs mocking — easier as its own test than in the parametrize fixture):
1 | |
Merge multi into the existing import line (do not add a third from calcipy.tasks.test import ... line):
1 2 3 4 5 | |
Then add a new test function after the existing test_test_with_min_cover:
1 2 3 4 5 6 7 8 9 10 11 | |
- Step 2: Run test to verify it fails
1 | |
Expected: ImportError or AttributeError — multi does not exist yet.
- Step 3: Implement
multiincalcipy/tasks/test.py
Add import at the top of calcipy/tasks/test.py (with existing imports):
1 | |
Add task after the watch task and before coverage:
1 2 3 4 5 6 | |
Note: dict.fromkeys() deduplicates while preserving order, matching the noxfile’s set-dedup behavior.
- Step 4: Run test to verify it passes
1 | |
Expected: PASS
- Step 5: Run full test suite to check for regressions
1 | |
Expected: all PASS
- Step 6: Commit
1 2 | |
Task 2: Wire test.multi into all_tasks.py⚓︎
Files:
- Modify:
calcipy/tasks/all_tasks.py - Test:
tests/tasks/test_all_tasks.py
Background: _OTHER_TASKS currently contains nox.noxfile.with_kwargs(session='tests'). This should become test.multi. The test_all_tasks.py test only checks that main and other run without error (commands list is empty) so no test change is needed — but verify it still passes.
- Step 1: Update
_OTHER_TASKSincalcipy/tasks/all_tasks.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Also remove the nox import from the import line at the top if nox is no longer referenced:
1 2 3 4 5 | |
- Step 2: Run tests to verify nothing broke
1 | |
Expected: all PASS (test_nox.py tests nox.py directly and doesn’t depend on all_tasks.py)
- Step 3: Commit
1 2 | |
Task 3: Deprecate calcipy/tasks/nox.py and calcipy/noxfile/⚓︎
Files:
- Modify:
calcipy/tasks/nox.py - Modify:
calcipy/noxfile/_noxfile.py
Background: Both are kept for backward compatibility — existing projects using from calcipy.noxfile import tests or calling calcipy nox will continue to work. A deprecation note in the docstring is sufficient; no runtime warning is needed since we’re not breaking anything yet.
- Step 1: Add deprecation note to
calcipy/tasks/nox.py
1 2 3 4 5 6 7 8 9 | |
- Step 2: Add deprecation note to
calcipy/noxfile/_noxfile.py
At the top of the module docstring:
1 2 3 4 5 | |
- Step 3: Verify tests still pass
1 | |
Expected: all PASS
- Step 4: Commit
1 2 | |
Task 4: Update pyproject.toml and .gitignore⚓︎
Files:
- Modify:
pyproject.toml - Modify:
.gitignore
Background: The nox extra (nox >=2025.11.12) is removed from recommended since new projects won’t need it. The nox extra itself stays so existing users pinning calcipy[nox] aren’t broken. .uv-tests/ needs to be git-ignored since test.multi creates per-version envs there.
- Step 1: Remove
noxfromrecommendedinpyproject.toml
1 2 3 4 5 6 7 8 9 | |
- Step 2: Add
.uv-tests/to.gitignore
Find the existing .gitignore and add .uv-tests/ near other virtual-env entries (e.g. near .venv/ or .nox/).
- Step 3: Verify the project still installs cleanly
1 | |
Expected: no errors
- Step 4: Commit
1 2 | |
Task 5: Update calcipy_template (separate repo)⚓︎
Files (in ../calcipy_template/):
- Delete:
package_template/noxfile.py - Delete:
.ctt/default/noxfile.py
Background: Every project generated from the template has a noxfile.py with just three lines importing from calcipy. Once test.multi is the standard, those files are dead weight. The template is a separate repo — this task is a follow-up change there, not in calcipy itself.
- Step 1: Check for other references to
noxfile.pyin the template repo
1 | |
Expected: only the two noxfile.py files themselves. If other files reference them, update those first.
- Step 2: Delete both noxfile templates
1 2 | |
- Step 2: Verify the template still renders correctly with ctt
1 | |
Expected: no errors referencing missing noxfile
- Step 3: Commit (in calcipy_template repo)
1 2 | |
Task 6: Update docs/README.md⚓︎
Files:
-
Modify:
docs/README.md -
Step 1: Replace nox references with
test.multi
Find any documentation referring to nox -s tests or calcipy nox and update to:
1 2 3 4 5 | |
- Step 2: Commit
1 2 | |