Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with virtual environment reuse and multiple Python versions installed through pyenv #441

Closed
purefunctor opened this issue Jun 8, 2021 · 5 comments

Comments

@purefunctor
Copy link

Describe the bug
G'day, Nox 2021.6.6 seems to fail reusing environments when it finds multiple Python interpreters installed by pyenv. Perhaps this is related to #428 ?

How to reproduce
Install multiple versions with pyenv

$ pyenv install 3.8.9
$ pyenv install 3.9.5
$ pyenv global 3.9.5 3.8.9

This populates ~/.pyenv/shims/ with the following with executable scripts e.g. python, python3.9, python3.8, etc. This folder is typically added to PATH.

Running the following session breaks virtual environment reuse:

@nox.session(python="3.9")
def test(session):
    session.install("pytest", ".")
    session.run("pytest")

Installing/running nox using poetry or a manually-created virtualenv environment in a project seems to resolve this, however.

Expected behavior
Virtual environments are reused in the presence of pyenv-installed Python versions.

@cjolowicz
Copy link
Collaborator

cjolowicz commented Jun 8, 2021

Can you verify that virtualenv -p 3.9 (or whichever Python version you were using for your Nox session) gives you the expected full Python version?

I have seen similar behavior on macOS, though my situation was slightly different from the one you described. To my knowledge, virtualenv does not invalidate its cache when you install a newer point release (X.Y.Z) of Python using pyenv. Its cache invalidation code only checks the mtime of the pyenv shim, which does not change.

Nox will refuse to reuse the environment because the interpreter does not have the expected version. (That's not to say that Nox can't support this case better.)

Also, which OS are you using?

@cjolowicz
Copy link
Collaborator

See pypa/virtualenv#2130

@purefunctor
Copy link
Author

Can you verify that virtualenv -p 3.9 (or whichever Python version you were using for your Nox session) gives you the expected full Python version?

I'm not entirely sure what steps to take but when I did virtualenv -p 3.9 and inspected the generated pyvenv.cfg file inside of the environment directory, I found:

home = /usr
implementation = CPython
version_info = 3.9.5.final.0
virtualenv = 20.4.7
include-system-site-packages = false
base-prefix = /usr
base-exec-prefix = /usr
base-executable = /usr/bin/python3.9

As opposed to using virtualenv -p 3.8 which generates:

home = /home/pure/.pyenv/versions/3.8.9
implementation = CPython
version_info = 3.8.9.final.0
virtualenv = 20.4.7
include-system-site-packages = false
base-prefix = /home/pure/.pyenv/versions/3.8.9
base-exec-prefix = /home/pure/.pyenv/versions/3.8.9
base-executable = /home/pure/.pyenv/versions/3.8.9/bin/python3.8

The former seems to occur because of how I've installed nox through pipx (which was installed from Arch packages, thus the use of the system interpreter). nox environments that have their pyvenv.cfg pointing to pyenv-installed Python versions are successfully reused.

As a workaround, Installing nox directly on the Python 3.9 version I'm using through pyenv resolves the issue for my project, but it'd be nice if we could resolve this edge case as well.

Also, which OS are you using?

I'm on Linux.

@cjolowicz
Copy link
Collaborator

Thanks for the additional input!

I think what's going on here is this: Nox decides whether it can reuse the environment by comparing the base prefix of the installed interpreter with the base prefix of the expected interpreter. In your case, these two are different:

  • The installed interpreter is based on the system interpreter. This is because virtualenv was installed (via pipx) using the system interpreter, and it favors its own interpreter as long as it matches the spec.
  • The expected interpreter is the one installed by pyenv. Nox expects the interpreter to be the one it found searching the PATH, and the pyenv shims are at the front of PATH.

So fixing the upstream bug mentioned above won't do anything for your use case. The versions of both interpreters are identical, only their base prefix differs.

I think there are (at least) two ways in which Nox's behavior could be improved here:

  1. Nox should check the interpreter in an existing environment against the spec in the Noxfile, not against some interpreter it found searching the PATH.
  2. The expected interpreter for a virtualenv should be based on virtualenv's own Python discovery mechanism.

The second point may be irrelevant if we find a good solution for the first one. But I'm not yet sure what that would be.

@cjolowicz
Copy link
Collaborator

This was fixed in Nox 2021.6.12.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants