summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/config.txt14
-rw-r--r--doc/example/basic.txt24
-rw-r--r--tests/conftest.py28
-rw-r--r--tests/test_config.py40
-rw-r--r--tests/test_venv.py61
-rw-r--r--tox.ini6
-rw-r--r--tox/_config.py18
-rw-r--r--tox/_venv.py38
8 files changed, 158 insertions, 71 deletions
diff --git a/doc/config.txt b/doc/config.txt
index fae93f2..f9cf80f 100644
--- a/doc/config.txt
+++ b/doc/config.txt
@@ -19,6 +19,7 @@ List of optional global options::
distdir=path # defaults to {toxworkdir}/dist
distshare=path # defaults to {homedir}/.tox/distshare
envlist=ENVLIST # defaults to the list of all environments
+
``tox`` autodetects if it is running in a Hudson_ context
(by checking for existence of the ``HUDSON_URL`` environment variable)
@@ -27,7 +28,15 @@ and will first lookup global tox settings in this section::
[tox:hudson]
... # override [tox] settings for the hudson context
# note: for hudson distshare defaults to ``{toxworkdir}/distshare``.
+
+.. confval:: indexserver=
+ name URL
+ name URL
+ ...
+ Definition of "name -> URL" mappings which can be used in
+ dependency specifications to install packages from different
+ indexservers.
envlist setting
+++++++++++++++++++++++++
@@ -104,11 +113,6 @@ Complete list of settings that you can put into ``testenv*`` sections:
passed to easy_install/pip for processing. It usually can be a file,
and URL or a package name.
-.. confval:: indexserver=URL
-
- The Index server to use. When nothing is specified the default
- of the installation tool (easy_install or pip) will be used.
-
.. confval:: upgrade=True|False(default)
Install dependencies in "upgrade" mode by passing upgrade flag to install tools.
diff --git a/doc/example/basic.txt b/doc/example/basic.txt
index f46b401..c3b4de6 100644
--- a/doc/example/basic.txt
+++ b/doc/example/basic.txt
@@ -51,13 +51,35 @@ using a different PyPI server
.. versionadded: 0.9
To install dependencies and packages from a different
-PyPI servertype::
+PyPI server type::
tox --indexserver http://pypi.testrun.org
This causes both the internal pip and easy-install steps
to use the specified server for upgrading.
+installing dependencies from multiple PyPI server
+---------------------------------------------------
+
+.. versionadded: 0.9
+
+You can instrument tox to install dependencies from
+different PyPI servers, example::
+
+ [tox]
+ indexserver =
+ DEV http://mypypiserver.org
+
+ [testenv]
+ deps =
+ docutils # comes from standard PyPI
+ DEV mypackage # will come from custom PYPI above
+
+Note that the ``--indexserver`` command line overrides
+the default index server, not the ``DEV`` one here.
+This will cause both the internal pip and easy-install steps
+to use the specified servers accordingly.
+
upgrading packages
-----------------------------------------------
diff --git a/tests/conftest.py b/tests/conftest.py
index b1e57db..0e5d367 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -6,6 +6,7 @@ from py.builtin import print_
from fnmatch import fnmatch
import time
from tox._config import parseconfig
+from tox._venv import VirtualEnv
def pytest_configure():
if 'TOXENV' in os.environ:
@@ -82,6 +83,7 @@ def pytest_funcarg__mocksession(request):
class MockSession(Session):
def __init__(self):
self._clearmocks()
+ #self.config = request.getfuncargvalue("newconfig")([], "")
def _clearmocks(self):
self._pcalls = []
self.report = ReportExpectMock()
@@ -91,6 +93,32 @@ def pytest_funcarg__mocksession(request):
self._pcalls.append(pcallMock(args, log, cwd, env))
return MockSession()
+def pytest_funcarg__mocksession(request):
+ from tox._cmdline import Session
+ class MockSession(Session):
+ def __init__(self):
+ self._clearmocks()
+ #self.config = request.getfuncargvalue("newconfig")([], "")
+ def getenv(self, name):
+ return VirtualEnv(self.config.envconfigs[name], session=self)
+ def _clearmocks(self):
+ self._pcalls = []
+ self.report = ReportExpectMock()
+ def make_emptydir(self, path):
+ pass
+ def pcall(self, args, log, cwd, env=None):
+ self._pcalls.append(pcallMock(args, log, cwd, env))
+ return MockSession()
+
+def pytest_funcarg__newmocksession(request):
+ mocksession = request.getfuncargvalue("mocksession")
+ newconfig = request.getfuncargvalue("newconfig")
+ def newmocksession(args, source):
+ config = newconfig(args, source)
+ mocksession.config = config
+ return mocksession
+ return newmocksession
+
class Cmd:
def __init__(self, request):
self.tmpdir = request.getfuncargvalue("tmpdir")
diff --git a/tests/test_config.py b/tests/test_config.py
index 85592bf..58ed2c8 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -25,7 +25,7 @@ class TestVenvConfig:
basepython=hello
deps=
world1
- world2
+ xyz world2
""" % (tmpdir, ))
assert config.toxworkdir == tmpdir
assert len(config.envconfigs) == 2
@@ -34,7 +34,7 @@ class TestVenvConfig:
assert config.envconfigs['py1'].deps == ['hello']
assert config.envconfigs['py2'].basepython == "hello"
assert config.envconfigs['py2'].envdir == tmpdir.join("py2")
- assert config.envconfigs['py2'].deps == ['world1', 'world2']
+ assert config.envconfigs['py2'].deps == ['world1', 'xyz world2']
class TestConfigPackage:
def test_defaults(self, tmpdir, newconfig):
@@ -43,7 +43,6 @@ class TestConfigPackage:
assert config.toxworkdir == tmpdir.join(".tox")
envconfig = config.envconfigs['python']
assert envconfig.args_are_paths
- assert not envconfig.indexserver
assert not envconfig.upgrade
def test_defaults_distshare(self, tmpdir, newconfig):
@@ -265,15 +264,6 @@ class TestConfigTestEnv:
assert envconfig.changedir.basename == "xyz"
assert envconfig.changedir == config.toxinidir.join("xyz")
- def test_indexurl(self, tmpdir, newconfig):
- config = newconfig("""
- [testenv]
- indexserver = XYZ
- """)
- assert len(config.envconfigs) == 1
- envconfig = config.envconfigs['python']
- assert envconfig.indexserver == "XYZ"
-
def test_envbindir(self, tmpdir, newconfig):
config = newconfig("""
[testenv]
@@ -497,16 +487,32 @@ class TestGlobalOptions:
assert env.basepython == "python2.4"
assert env.commands == [['xyz']]
-class TestParseEnv:
+class TestIndexServer:
+ def test_indexserver(self, tmpdir, newconfig):
+ config = newconfig("""
+ [tox]
+ indexserver =
+ name1 XYZ
+ name2 ABC
+ """)
+ assert config.indexserver['default'] == None
+ assert config.indexserver['name1'] == "XYZ"
+ assert config.indexserver['name2'] == "ABC"
+
def test_parse_indexserver(self, newconfig):
inisource = """
- [testenv:hello]
- indexserver = XYZ
+ [tox]
+ indexserver =
+ default http://pypi.testrun.org
+ name2 XYZ
"""
config = newconfig([], inisource)
- assert config.envconfigs['hello'].indexserver == "XYZ"
+ assert config.indexserver['default'] == "http://pypi.testrun.org"
config = newconfig(["--indexserver", "ABC"], inisource)
- assert config.envconfigs['hello'].indexserver == "ABC"
+ assert config.indexserver['default'] == "ABC"
+ assert config.indexserver['name2'] == "XYZ"
+
+class TestParseEnv:
def test_parse_upgrade(self, newconfig):
inisource = ""
diff --git a/tests/test_venv.py b/tests/test_venv.py
index 7e49b58..1c0602d 100644
--- a/tests/test_venv.py
+++ b/tests/test_venv.py
@@ -119,16 +119,15 @@ def test_create_sitepackages(monkeypatch, mocksession, newconfig):
assert "--no-site-packages" in " ".join(args)
@py.test.mark.skipif("sys.version_info[0] >= 3")
-def test_install_downloadcache(mocksession, newconfig):
- config = newconfig([], """
+def test_install_downloadcache(newmocksession):
+ mocksession = newmocksession([], """
[testenv:py123]
distribute=True
deps=
dep1
dep2
""")
- envconfig = config.envconfigs['py123']
- venv = VirtualEnv(envconfig, session=mocksession)
+ venv = mocksession.getenv("py123")
venv.create()
l = mocksession._pcalls
assert len(l) == 1
@@ -139,40 +138,47 @@ def test_install_downloadcache(mocksession, newconfig):
assert l[1].cwd == venv.envconfig.envlogdir
assert "pip" in str(args[0])
assert args[1] == "install"
- arg = "--download-cache=" + str(envconfig.downloadcache)
+ arg = "--download-cache=" + str(venv.envconfig.downloadcache)
assert arg in args[2:]
assert "dep1" in args
assert "dep2" in args
deps = filter(None, [x[1] for x in venv._getliveconfig().deps])
assert deps == ['dep1', 'dep2']
-def test_install_indexserver(mocksession, newconfig):
- config = newconfig([], """
+def test_install_indexserver(newmocksession):
+ mocksession = newmocksession([], """
+ [tox]
+ indexserver=
+ abc ABC
+
[testenv:py123]
- indexserver=XYZ
- deps= dep1
+ deps=
+ dep1
+ abc dep2
""")
- envconfig = config.envconfigs['py123']
- venv = VirtualEnv(envconfig, session=mocksession)
+ venv = mocksession.getenv('py123')
venv.create()
l = mocksession._pcalls
assert len(l) == 1
+ l[:] = []
venv.install_deps()
+ # two different index servers, two calls
assert len(l) == 2
- args = l[1].args
+ args = " ".join(l[0].args)
+ assert "-i" not in args
+ assert "dep1" in args
- i = args.index('-i')
- assert i != -1
- assert args[i+1] == "XYZ"
+ args = " ".join(l[1].args)
+ assert "-i ABC" in args
+ assert "dep2" in args
-def test_install_upgrade(mocksession, newconfig):
- config = newconfig(['--upgrade'], """
+def test_install_upgrade(newmocksession):
+ mocksession = newmocksession(['--upgrade'], """
[testenv]
deps=xyz
""")
- envconfig = config.envconfigs['python']
- venv = VirtualEnv(envconfig, session=mocksession)
+ venv = mocksession.getenv('python')
venv.create()
l = mocksession._pcalls
assert len(l) == 1
@@ -181,18 +187,17 @@ def test_install_upgrade(mocksession, newconfig):
assert len(l) == 2
assert '-U' in l[1].args
-def test_install_python3(tmpdir, mocksession, newconfig):
+def test_install_python3(tmpdir, newmocksession):
if not py.path.local.sysfind('python3.1'):
py.test.skip("needs python3.1")
- config = newconfig([], """
+ mocksession = newmocksession([], """
[testenv:py123]
basepython=python3.1
deps=
dep1
dep2
""")
- envconfig = config.envconfigs['py123']
- venv = VirtualEnv(envconfig, session=mocksession)
+ venv = mocksession.getenv('py123')
venv.create()
l = mocksession._pcalls
assert len(l) == 1
@@ -317,13 +322,13 @@ class TestCreationConfig:
class TestVenvTest:
- def test_patchPATH(self, newconfig, mocksession, monkeypatch):
- config = newconfig([], """
+ def test_patchPATH(self, newmocksession, monkeypatch):
+ mocksession = newmocksession([], """
[testenv:python]
commands=abc
""")
- envconfig = config.envconfigs['python']
- venv = VirtualEnv(envconfig, session=mocksession)
+ venv = mocksession.getenv("python")
+ envconfig = venv.envconfig
monkeypatch.setenv("PATH", "xyz")
oldpath = venv.patchPATH()
assert oldpath == "xyz"
@@ -337,7 +342,7 @@ class TestVenvTest:
assert envconfig.commands
monkeypatch.setattr(venv, '_pcall', lambda *args, **kwargs: 0/0)
- py.test.raises(ZeroDivisionError, "venv._install([1,2,3])")
+ py.test.raises(ZeroDivisionError, "venv._install(list('123'))")
py.test.raises(ZeroDivisionError, "venv.test()")
py.test.raises(ZeroDivisionError, "venv.easy_install(['qwe'])")
py.test.raises(ZeroDivisionError, "venv.pip_install(['qwe'])")
diff --git a/tox.ini b/tox.ini
index 2d33ecf..8b36526 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,10 +1,12 @@
[tox]
envlist=py27,py26,py25,py24,py31,docs
+indexserver=
+ dev http://pypi.testrun.org
[testenv]
-indexserver=http://pypi.testrun.org
commands=py.test --junitxml={envlogdir}/junit-{envname}.xml []
-deps=pytest
+deps=
+ dev pytest
[testenv:docs]
basepython=python
diff --git a/tox/_config.py b/tox/_config.py
index ec15194..9e17582 100644
--- a/tox/_config.py
+++ b/tox/_config.py
@@ -58,7 +58,8 @@ def prepare_parse():
parser.add_argument("--sdistonly", action="store_true", dest="sdistonly",
help="only perform the sdist activity.")
parser.add_argument("--indexserver", action="store", dest="indexserver",
- help="use the specified PyPI indexserver for installation actions")
+ default=None, metavar="URL",
+ help="indexserver for installing deps (default pypi python.org"),
parser.add_argument("-U", "--upgrade", action="store_true", dest="upgrade",
help="try to upgrade dependencies in installation step")
parser.add_argument("args", nargs="*",
@@ -122,6 +123,17 @@ class parseini:
homedir=config.homedir)
config.toxworkdir = reader.getpath(toxsection, "toxworkdir",
"{toxinidir}/.tox")
+
+ # determine indexserver dictionary
+ config.indexserver = d = {}
+ for line in reader.getlist(toxsection, "indexserver"):
+ name, value = line.strip().split(None, 1)
+ d.setdefault(name, value)
+ if config.opts.indexserver:
+ d['default'] = config.opts.indexserver
+ else:
+ d.setdefault('default', None)
+
reader.addsubstitions(toxworkdir=config.toxworkdir)
config.distdir = reader.getpath(toxsection, "distdir",
"{toxworkdir}/dist")
@@ -173,10 +185,6 @@ class parseini:
vc.upgrade = True
else:
vc.upgrade = reader.getbool(section, "upgrade", False)
- if config.opts.indexserver:
- vc.indexserver = config.opts.indexserver
- else:
- vc.indexserver = reader.getdefault(section, "indexserver", None)
args = config.opts.args
if args:
if vc.args_are_paths:
diff --git a/tox/_venv.py b/tox/_venv.py
index a4349ab..8253154 100644
--- a/tox/_venv.py
+++ b/tox/_venv.py
@@ -178,20 +178,20 @@ class VirtualEnv(object):
self.session.report.action("installing dependencies %s" %(deps))
self._install(deps)
- def _commoninstallopts(self):
+ def _commoninstallopts(self, indexserver):
l = []
- if self.envconfig.indexserver:
- l += ["-i", self.envconfig.indexserver]
+ if indexserver:
+ l += ["-i", indexserver]
if self.envconfig.upgrade:
l += ["-U"]
return l
- def easy_install(self, args):
- argv = ["easy_install"] + self._commoninstallopts() + args
+ def easy_install(self, args, indexserver=None):
+ argv = ["easy_install"] + self._commoninstallopts(indexserver) + args
self._pcall(argv, cwd=self.envconfig.envlogdir)
- def pip_install(self, args):
- argv = ["pip", "install"] + self._commoninstallopts()
+ def pip_install(self, args, indexserver=None):
+ argv = ["pip", "install"] + self._commoninstallopts(indexserver)
if self.envconfig.downloadcache:
self.envconfig.downloadcache.ensure(dir=1)
argv.append("--download-cache=%s" %
@@ -203,13 +203,25 @@ class VirtualEnv(object):
argv += args
self._pcall(argv, cwd=self.envconfig.envlogdir)
- def _install(self, args):
- if not args:
+ def _install(self, deps):
+ if not deps:
return
- if self._ispython3():
- self.easy_install(args)
- else:
- self.pip_install(args)
+ d = {}
+ for depline in deps:
+ try:
+ parts = depline.split(None, 1)
+ except AttributeError: # e.g. py.path.local
+ parts = depline,
+ if len(parts) == 1:
+ d.setdefault('default', []).append(depline)
+ else:
+ d.setdefault(parts[0], []).append(parts[1])
+ for name, args in d.items():
+ indexserver = self.session.config.indexserver[name]
+ if self._ispython3():
+ self.easy_install(args, indexserver)
+ else:
+ self.pip_install(args, indexserver)
def test(self):
self.session.make_emptydir(self.envconfig.envtmpdir)