From 9226a19adfe25c76881adcef076c92d020391a72 Mon Sep 17 00:00:00 2001 From: Preocts Date: Sun, 3 May 2026 15:16:33 -0400 Subject: [PATCH] Use nox virtual-environments in sessions The prior implementation used `python=False` for all session decorators which disabled the creation of virtual environments. While this made things simple, there were trade-offs with maintaining the state of the developer's environment and venv. Instead, determine the desired version of Python from two sources. The `.python-version` file and the `UV_PYTHON` environment variable. Use the environment variable if it exists, otherwise use the file. Pass this into the session decorator and allow nox to manage its virtual environments for the following sessions: - test - combine - lint - format The result is using more of the features nox provides while keep the dev's environment as-is during nox sessions that run `uv sync`. The test, lint, format, and combine sessions all trigger a sync to ensure their dependencies are met. Prior, this would leave the dev's environment in an altered state. Example: If the the dev had installed nox with `uv pip install nox` for developement on the sessions, once any of the listed sessions were run the `.venv` was rebuilt. --- noxfile.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/noxfile.py b/noxfile.py index a995101..7303765 100644 --- a/noxfile.py +++ b/noxfile.py @@ -12,6 +12,11 @@ LINT_PATH = "./src" TESTS_PATH = "./tests" +_file_python_version = pathlib.Path(".python-version").read_text() +_uv_python_version = os.getenv("UV_PYTHON", "") +# Favor the UV_PYTHON environment variable as this should override the .python-version +PYTHON_VERSION = _uv_python_version or _file_python_version + # What we allowed to clean (delete) CLEANABLE_TARGETS = [ "./dist", @@ -61,23 +66,19 @@ @nox.session(name="dev", python=False) -def dev_session(session: nox.Session) -> None: +def create_dev_environment(session: nox.Session) -> None: """Create a development environment.""" session.run_install("uv", "sync") -@nox.session(name="test", python=False) +@nox.session(name="test", python=PYTHON_VERSION) def run_tests_with_coverage(session: nox.Session) -> None: """Run pytest in isolated environment, display coverage. Extra arguements passed to pytest.""" - uv_args = UV_ARGS - if "UV_PYTHON" in os.environ: - uv_args = UV_ARGS + [f"--python={os.environ['UV_PYTHON']}"] - partial = "partial-coverage" in session.posargs - session.run_install("uv", "sync", *uv_args) + session.run_install("uv", "sync", *UV_ARGS) - coverage = functools.partial(session.run, "uv", "run", *uv_args, "coverage") + coverage = functools.partial(session.run, "uv", "run", *UV_ARGS, "coverage") coverage("erase") @@ -90,7 +91,7 @@ def run_tests_with_coverage(session: nox.Session) -> None: coverage("html") -@nox.session(name="combine", python=False) +@nox.session(name="combine", python=PYTHON_VERSION) def combine_coverage(session: nox.Session) -> None: """Combine parallel-mode coverage files and produce reports.""" session.run_install("uv", "sync", *UV_ARGS) @@ -103,7 +104,7 @@ def combine_coverage(session: nox.Session) -> None: coverage("json") -@nox.session(name="lint", python=False) +@nox.session(name="lint", python=PYTHON_VERSION) def run_linters(session: nox.Session) -> None: """Run code linters, and type checking against all files.""" session.run_install("uv", "sync", "--group", "lint", *UV_ARGS) @@ -112,7 +113,7 @@ def run_linters(session: nox.Session) -> None: session.run("uv", "run", *UV_ARGS, *linter_args) -@nox.session(name="format", python=False) +@nox.session(name="format", python=PYTHON_VERSION) def run_formatters(session: nox.Session) -> None: """Run code formatters against all files.""" session.run_install("uv", "sync", "--group", "format", *UV_ARGS)