Allow activation of environments in relative directories.

Also disallow the creation of venvs with reserved names
This commit is contained in:
Jamie Bliss 2016-10-02 21:49:38 -04:00
parent d34f52d6e1
commit ce98aa8fa9
3 changed files with 60 additions and 13 deletions

13
news/vox-reldir.rst Normal file
View file

@ -0,0 +1,13 @@
**Added:** None
**Changed:**
* `vox activate` now accepts relative directories.
**Deprecated:** None
**Removed:** None
**Fixed:** None
**Security:** None

View file

@ -3,9 +3,11 @@
import builtins
import stat
import os
import pytest
from xontrib.voxapi import Vox
from tools import skip_if_on_conda
from xonsh.platform import ON_WINDOWS
@skip_if_on_conda
@ -97,6 +99,7 @@ def test_path(xonsh_builtins, tmpdir):
assert oldpath == xonsh_builtins.__xonsh_env__['PATH']
@skip_if_on_conda
def test_crud_subdir(xonsh_builtins, tmpdir):
"""
@ -121,3 +124,24 @@ def test_crud_subdir(xonsh_builtins, tmpdir):
del vox['spam/eggs']
assert not tmpdir.join('spam', 'eggs').check()
@skip_if_on_conda
def test_crud_subdir(xonsh_builtins, tmpdir):
"""
Creates a virtual environment, gets it, enumerates it, and then deletes it.
"""
xonsh_builtins.__xonsh_env__['VIRTUALENV_HOME'] = str(tmpdir)
vox = Vox()
with pytest.raises(ValueError):
if ON_WINDOWS:
vox.create('Scripts')
else:
vox.create('bin')
with pytest.raises(ValueError):
if ON_WINDOWS:
vox.create('spameggs/Scripts')
else:
vox.create('spameggs/bin')

View file

@ -133,6 +133,8 @@ class Vox(collections.abc.Mapping):
# NOTE: clear=True is the same as delete then create.
# NOTE: upgrade=True is its own method
env_path = os.path.join(self.venvdir, name)
if not self._check_reserved(env_path):
raise ValueError("venv can't contain reserved names ({})".format(', '.join(_subdir_names())))
venv.create(
env_path,
system_site_packages=system_site_packages, symlinks=symlinks,
@ -177,6 +179,10 @@ class Vox(collections.abc.Mapping):
# Ok, do what we came here to do.
venv.create(env_path, upgrade=True, **flags)
@staticmethod
def _check_reserved(name):
return os.path.basename(name) not in _subdir_names() # FIXME: Check the middle components, too
def __getitem__(self, name):
"""Get information about a virtual environment.
@ -187,24 +193,28 @@ class Vox(collections.abc.Mapping):
the current one (throws a KeyError if there isn't one).
"""
if name is ...:
env_path = builtins.__xonsh_env__['VIRTUAL_ENV']
elif os.path.isabs(name):
env_path = name
env_paths = [builtins.__xonsh_env__['VIRTUAL_ENV']]
else:
env_path = os.path.join(self.venvdir, name)
if not self._check_reserved(name):
# Don't allow a venv that could be a venv special dir
raise KeyError()
ve = _mkvenv(env_path)
env_paths = []
if os.path.isdir(name):
env_paths += [name]
env_paths += [os.path.join(self.venvdir, name)]
if os.path.basename(ve.env) in _subdir_names(): # FIXME: Check the inner components, too
# Don't allow a venv that could be a venv special dir
for ep in env_paths:
ve = _mkvenv(ep)
# Actually check if this is an actual venv or just a organizational directory
# eg, if 'spam/eggs' is a venv, reject 'spam'
if not os.path.exists(ve.bin):
continue
return ve
else:
raise KeyError()
# Actually check if this is an actual venv or just a organizational directory
# eg, if 'spam/eggs' is a venv, reject 'spam'
if not os.path.exists(ve.bin):
raise KeyError()
return ve
def __contains__(self, name):
# For some reason, MutableMapping seems to do this against iter, which is just silly.
try: