A xonsh alias for using pyenv with vox for nice Python virtualenvironments
Today I started migrating away from virtualenvironments created by pyenv-virtualenv
and started managing virtualenvs with xonsh's built-in vox
utility. (I had previously been using the same old virtualenvironments created by pyenv virtualenv
and just activating them with vox activate ~/.pyenv/versions/virtualenv_symlink'
, but that's for the birds.)
So, one thing I wanted to do is have vox
use my pyenv
-detected python
bin whenver I created new virtualenvironments, if I didn't specify an override python
bin. In other words, I wanted stuff like the .python-version
file and the pyenv shell
command to be respected by vox
without adding all that functionality to vox
proper. This is probably a pretty specific use case, though if more people need it, lmk!
I came up with an alias that wraps the original vox
alias (that's how the vox
command is loaded into the environment, as an alias).
Before I override it, I save the previous vox
alias in a variable - the vox
alias normally just maps to a callable, so I saved the callable. This is because I want to call the previous vox
functionality inside of my new alias, which I am naming 'vox'
, and I would end up with unwanted recursion if I called my new alias function from inside itself.
| normal_vox = aliases['vox']
|
Next I define a function that does a simple check for whether I had specified an interpreter in the arguments, and if not, it prepends the pyenv
-detected python
bin to the argument list.
| def pyenv_vox(argument_list, **kwargs):
"""Use pyenv-detected python to create environments if no other interpreter is specified."""
print(f'Using alias for vox in .xonshrc')
if len(argument_list) and argument_list[0] == 'new' \
and '--interpreter' not in argument_list \
and '-p' not in argument_list:
python = $(pyenv which python).strip()
print(f'Using pyenv-detected python to create new environment: {python}')
argument_list = ['new', '--interpreter', python] + argument_list[1:]
return normal_vox(argument_list, **kwargs)
|
Regardless of whether that modification is made to the argument list, it calls the original vox
alias with the argument list, so other vox
commands effectively pass through untouched.
Finally, I set aliases['vox']
to this new alias function.
| aliases['vox'] = pyenv_vox
|
And, that's it. With the print()
statements included in the alias function, you can see what happens.
It works, too:
| eddie@eddie-ubuntu ~/website master $ vox new excitement
Using alias for vox in .xonshrc
Using pyenv-detected python to create new environment: /home/eddie/.pyenv/versions/3.7.3/bin/python
Creating environment...
Environment 'excitement' created. Activate it with "vox activate excitement".
|
Other commands are untouched by the alias - well, at least not substantively. The logging still lets you know you're using the alias.
| eddie@eddie-ubuntu ~/website master $ vox ls
Using alias for vox in .xonshrc
Available environments:
butter
excitement
website
|
You can set up pyenv to use a specific python, and that python will be used for the virtualenv:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 | eddie@eddie-ubuntu ~ [1]$ pyenv local 3.7.3
eddie@eddie-ubuntu ~ $ python --version
Python 3.7.3
eddie@eddie-ubuntu ~ $ pyenv version
3.7.3 (set by /home/eddie/.python-version)
eddie@eddie-ubuntu ~ $ vox new demo-3.7.3
Using alias for vox in .xonshrc
Using pyenv-detected python to create new environment: /home/eddie/.pyenv/versions/3.7.3/bin/python
Creating environment...
Environment 'demo-3.7.3' created. Activate it with "vox activate demo-3.7.3".
eddie@eddie-ubuntu ~ $ pyenv local 2.7.15
eddie@eddie-ubuntu ~ $ vox new demo
Using alias for vox in .xonshrc
Using pyenv-detected python to create new environment: /home/eddie/.pyenv/versions/2.7.15/bin/python
Creating environment...
New python executable in /home/eddie/.virtualenvs/demo/bin/python
Installing setuptools, pip, wheel...done.
Environment 'demo' created. Activate it with "vox activate demo".
eddie@eddie-ubuntu ~ $ vox activate demo
Using alias for vox in .xonshrc
Activated "demo".
(demo) eddie@eddie-ubuntu ~ $ python --version
Python 2.7.15
(demo) eddie@eddie-ubuntu ~ $ vox deactivate
Using alias for vox in .xonshrc
Deactivated "demo".
eddie@eddie-ubuntu ~ $ python --version
Python 2.7.15
eddie@eddie-ubuntu ~ $ vox activate demo-3.7.3
Using alias for vox in .xonshrc
Activated "demo-3.7.3".
(demo-3.7.3) eddie@eddie-ubuntu ~ $ python --version
Python 3.7.3
|
You can still override pyenv's current python when creating virtualenvs:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | eddie@eddie-ubuntu ~ $ pyenv local 2.7.15
eddie@eddie-ubuntu ~ $ python --version
Python 2.7.15
eddie@eddie-ubuntu ~ [2]$ vox new -p /usr/bin/python demo-system-python
Using alias for vox in .xonshrc
Creating environment...
New python executable in /home/eddie/.virtualenvs/demo-system-python/bin/python
Installing setuptools, pip, wheel...done.
Environment 'demo-system-python' created. Activate it with "vox activate demo-system-python".
eddie@eddie-ubuntu ~ $ /usr/bin/python --version
Python 2.7.16
eddie@eddie-ubuntu ~ $ vox activate demo-system-python
Using alias for vox in .xonshrc
Activated "demo-system-python".
(demo-system-python) eddie@eddie-ubuntu ~ $ python --version
Python 2.7.16
(demo-system-python) eddie@eddie-ubuntu ~ $ vox deactivate
Using alias for vox in .xonshrc
Deactivated "demo-system-python".
eddie@eddie-ubuntu ~ $ python --version
Python 2.7.15
|
I'll upload the code sometime, and I'll update this page with it, hopefully, but you've got what you need :)