It seems like you can't use Tox to test against multiple Python versions inside of a virtualenv created with pyenv-virtualenv. From what I can tell, this is because activating a pyenv-virtualenv sets the PYENV_VERSION to the named virtualenv, which makes all the other pythonX.Y shims invalid.
A complete example demonstrating this problem:
$> pyenv install 2.7.6
$> pyenv install 3.4.1
$> pyenv global 2.7.6 3.4.1
$> pyenv versions
system
* 2.7.6 (set by /Users/andy/.pyenv/version)
* 3.4.1 (set by /Users/andy/.pyenv/version)
# NOTE, installing tox "globally" here and running it
# against 2.7.6 and 3.4.1 works fine because both
#2.7.6 and 3.4.1 are "activated" in the non-virtualenv
# environment
$> pyenv virtualenv 2.7.6 redis-py
$> pyenv activate redis-py
$> pyenv versions
system
2.7.6
3.4.1
* redis-py (set by PYENV_VERSION environment variable)
# Now Tox (or any other program trying to call python3.4) will fail
$> python3.4
pyenv: python3.4: command not found
The `python3.4' command exists in these Python versions:
3.4.1
I've gotten around this problem by using pyenv-virtualenvwrapper, which doesn't seem to use the pyenv versions system to create the virtualenv and doesn't set the PYENV_VERSION environment variable.
In this case, you don't have to activate the virtualenv of redis-py.
Following example doesn't help?
## Setup CPython and virtualenv.
$ pyenv install 2.7.6
$ pyenv install 3.4.1
$ pyenv virtualenv 2.7.6 redis-py27
$ pyenv virtualenv 3.4.1 redis-py34
$ pyenv global redis-py27 redis-py34
## Setup tox.
$ pip install tox
$ pyenv rehash
$ cat <<EOF >setup.py
from setuptools import setup
setup(name="x")
EOF
$ cat <<EOF >tox.ini
[tox]
envlist = py27, py34
[testenv:py27]
basepython = python2.7
[testenv:py34]
basepython = python3.4
[testenv]
commands = python --version
EOF
## Then, run tox.
$ tox
GLOB sdist-make: /home/yamashita/x/setup.py
py27 inst-nodeps: /home/yamashita/x/.tox/dist/x-0.0.0.zip
py27 runtests: PYTHONHASHSEED='2368391035'
py27 runtests: commands[0] | python --version
Python 2.7.6
py34 inst-nodeps: /home/yamashita/x/.tox/dist/x-0.0.0.zip
py34 runtests: PYTHONHASHSEED='2368391035'
py34 runtests: commands[0] | python --version
Python 3.4.1
__________________________________________________________________________________ summary ___________________________________________________________________________________
py27: commands succeeded
py34: commands succeeded
congratulations :)
Perhaps I'm not understanding the "pyenv way". Your example seems to break whenever there's other dependencies. I did what you suggest above and changed a few things:
# AFTER pyenv global redis-py27 redis-py34
pip install hiredis # a dependency used by my project
# tox.ini:
[tox]
envlist = py27, py34
[testenv:py27]
basepython = python2.7
[testenv:py34]
basepython = python3.4
[testenv]
commands = python foo.py
# foo.py
from __future__ import print_function
try:
import hiredis
except ImportError:
print("import error")
# RUNNING TOX (notice the import errors being printed out)
$> tox
GLOB sdist-make: /Users/andy/tmp/setup.py
py27 inst-nodeps: /Users/andy/tmp/.tox/dist/z-0.0.0.zip
py27 runtests: PYTHONHASHSEED='1564301523'
py27 runtests: commands[0] | python foo.py
import error
py34 inst-nodeps: /Users/andy/tmp/.tox/dist/z-0.0.0.zip
py34 runtests: PYTHONHASHSEED='1564301523'
py34 runtests: commands[0] | python foo.py
import error
___________________________________ summary ____________________________________
py27: commands succeeded
py34: commands succeeded
congratulations :)
Even weirder, I can successfully import hiredis in the REPL from python and python2.7, but not python3.4. Which makes me wonder why the tox py27 environment test failed.
Sorry, I guess I should have included hiredis as one of the deps in tox.ini. That would fix this issue as tox maintains it's own idea of virtualenvs.
Even so, it seems pretty painful to me to have to switch the pyenv global when I want to work on a different project.
e.g.,
# work on redis-py...
pyenv global redis-py27 redis-py34
# work on foobar...
pyenv global foobar27 foobar34
I'd rather just activate a single redis-py or foobar virtualenv. That worked with non-pyenv virtualenv and it works with pyenv-virtualenvwrapper.
There is pyenv local it allows you to set project Python version per directory basis. See also https://github.com/yyuu/pyenv/blob/master/COMMANDS.md#pyenv-local
This works. The biggest disconnect for me was I was thinking that pyenv virtualenv worked just like the Python virtualenv module. I made this assumption because they share the same name.
More documentation around this might be a good idea in the future. Specifically, something that says that when you activate a pyenv virtualenv that all the shims for other Python versions aren't available.
Closing stale issue. Please reopen this if you still have a problem.
@andymccurdy You can set up multiple envs as "local" which tox will then pickup
e.g.
pyenv local redis-py 2.7.6 3.4.1 ...
@andymccurdy You made my days !
should definitely be in the doc IMHO ! I will do a PR if's ok for you @yyuu
You can set up multiple envs as "local" which tox will then pickup
e.g.
pyenv local redis-py 2.7.6 3.4.1 ...
Most helpful comment
@andymccurdy You can set up multiple envs as "local" which tox will then pickup
e.g.
pyenv local redis-py 2.7.6 3.4.1 ...