wntrblm / nox

Flexible test automation for Python
https://nox.thea.codes
Apache License 2.0
1.3k stars 148 forks source link

Setting venv_backend='uv|virtualenv' breaks if 'uv' is installed but the version of python your session is running against isn't supported by uv. #833

Open jamesharris-garmin opened 3 months ago

jamesharris-garmin commented 3 months ago

Current Behavior

nox.options.default_venv_backend = "uv|virtualenv" will always try to use uv if it is installed, even when the session's python version is incompatible with uv.

Expected Behavior

Nox would fall back to the alternate venv backend if the python version requested is earlier than the earliest supported version of the backend.

Steps To Reproduce

  1. Create a nox file with the following contents:
    
    import nox
    import sys

prefer UV if it is available

Note for older versions of nox we can't actually use this syntax.

nox.options.default_venv_backend = "uv|virtualenv"

@nox.session(python=[f"{sys.version_info.major}.{sys.version_info.minor}", "3.6"]) def hello(session): "A simple test session" session.install("cowsay") session.run("cowsay", "-t", f"Hello from Python {session.python}")

2. Invoke `nox -s hello-3.8`. Output:
```plaintext
nox > Running session hello-3.8
nox > Creating virtual environment (uv) using python3.8 in .nox/hello-3-8
nox > uv pip install cowsay
nox > cowsay -t 'Hello from Python 3.8'
  _____________________
| Hello from Python 3.8 |
  =====================
                     \
                      \
                        ^__^
                        (oo)\_______
                        (__)\       )\/\
                            ||----w |
                            ||     ||
nox > Session hello-3.8 was successful.
  1. Invoke nox -s hello-3.6. output:
    nox > Running session hello-3.6
    nox > Creating virtual environment (uv) using python3.6 in .nox/hello-3-6
    nox > Command uv venv -p python3.6 /grmn/prj/aoem/tools/build/bakelite/nox-simple-reproduction/.nox/hello-3-6 failed with exit code 1:
    × Can't use Python at `/usr/bin/python3.6`
    ╰─▶ Python 3.6.15 is not supported. Please use Python 3.8 or newer.
    nox > Session hello-3.6 failed.

I would expect the output for step 3 to be:

nox > cowsay -t 'Hello from Python 3.6'
Error processing line 1 of /grmn/prj/aoem/tools/build/bakelite/nox-simple-reproduction/.nox/hello-3-6/lib/python3.6/site-packages/_virtualenv.pth:

  Traceback (most recent call last):
    File "/usr/lib/python3.6/site.py", line 174, in addpackage
      exec(line)
    File "<string>", line 1, in <module>
    File "/grmn/prj/aoem/tools/build/bakelite/nox-simple-reproduction/.nox/hello-3-6/lib/python3.6/site-packages/_virtualenv.py", line 3
      from __future__ import annotations
                                       ^
  SyntaxError: future feature annotations is not defined

Remainder of file ignored
Error processing line 1 of /grmn/prj/aoem/tools/build/bakelite/nox-simple-reproduction/.nox/hello-3-6/lib/python3.6/site-packages/_virtualenv.pth:

  Traceback (most recent call last):
    File "/usr/lib/python3.6/site.py", line 174, in addpackage
      exec(line)
    File "<string>", line 1, in <module>
    File "/grmn/prj/aoem/tools/build/bakelite/nox-simple-reproduction/.nox/hello-3-6/lib/python3.6/site-packages/_virtualenv.py", line 3
      from __future__ import annotations
                                       ^
  SyntaxError: future feature annotations is not defined

Remainder of file ignored
  _____________________
| Hello from Python 3.6 |
  =====================
                     \
                      \
                        ^__^
                        (oo)\_______
                        (__)\       )\/\
                            ||----w |
                            ||     ||
nox > Session hello-3.6 was successful.

Environment

- OS: ubuntu 22.04
- Python: 3.8, 3.6
- Nox: 2024.4.15

Note: nox is invoked in python 3.8. Python 3.6 is installed using deadsnakes.

Anything else?

One possible solution would be to allow us to parameterize the venv_backend so that we can explicitly invoke the desired backend with the desired python version. But it seems simpler to just add logic to consider uv absent if our target session python is earlier than python 3.8