4 new commits in tox:

https://bitbucket.org/hpk42/tox/commits/4949def7e678/
Changeset:   4949def7e678
User:        hpk42
Date:        2013-08-15 13:00:26
Summary:     extend pseudo-homedir with .pip/pip.conf so that any "pip" command
triggered by tests (such as tox' tests itself) will pick it up.
Affected #:  2 files

diff -r 394c7438efdcae278cca3c0bbd6bde6f32aa4362 -r 
4949def7e678884e07157f12d7c33aead42227f7 tests/test_venv.py
--- a/tests/test_venv.py
+++ b/tests/test_venv.py
@@ -632,3 +632,15 @@
     assert env["HOME"] == str(tmpdir)
     assert not tmpdir.join(".pydistutils.cfg").check()
     assert "PIP_INDEX_URL" not in env
+
+def test_hack_home_env_passthrough(tmpdir, monkeypatch):
+    from tox._venv import hack_home_env
+    env = hack_home_env(tmpdir, "http://index";)
+    monkeypatch.setattr(os, "environ", env)
+
+    tmpdir = tmpdir.mkdir("tmpdir2")
+    env2 = hack_home_env(tmpdir)
+    assert env2["HOME"] == str(tmpdir)
+    assert env2["PIP_INDEX_URL"] == "http://index";
+    assert "index_url = http://index"; in \
+           tmpdir.join(".pydistutils.cfg").read()

diff -r 394c7438efdcae278cca3c0bbd6bde6f32aa4362 -r 
4949def7e678884e07157f12d7c33aead42227f7 tox/_venv.py
--- a/tox/_venv.py
+++ b/tox/_venv.py
@@ -457,7 +457,7 @@
             locate_via_py(*m.groups())
 
 
-def hack_home_env(homedir, index_url):
+def hack_home_env(homedir, index_url=None):
     # XXX HACK (this could also live with tox itself, consider)
     # if tox uses pip on a package that requires setup_requires
     # the index url set with pip is usually not recognized
@@ -468,9 +468,12 @@
     if not homedir.check():
         homedir.ensure(dir=1)
     d = dict(HOME=str(homedir))
+    if not index_url:
+        index_url = os.environ.get("TOX_INDEX_URL")
     if index_url:
         homedir.join(".pydistutils.cfg").write(
             "[easy_install]\n"
             "index_url = %s\n" % index_url)
         d["PIP_INDEX_URL"] = index_url
+        d["TOX_INDEX_URL"] = index_url
     return d


https://bitbucket.org/hpk42/tox/commits/50bd50082b7c/
Changeset:   50bd50082b7c
User:        hpk42
Date:        2013-08-15 13:00:38
Summary:     refine python2.5 and install_command behaviour and documentation. 
also show i in "--showconfig"
and rename internally from "install_command_argv" to install_command for 
consistency.

also deprecate downloadcache, distribute settings.
Affected #:  8 files

diff -r 4949def7e678884e07157f12d7c33aead42227f7 -r 
50bd50082b7cacf9a11ed5605d0af3383db23e8b CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,17 @@
 1.6.0.dev
 -----------------
 
+- fix issue35: add new EXPERIMENTAL "install_command" testenv-option to 
configure the
+  installation command with options for dep/pkg install.  Thanks Carl Meyer
+  for the PR and docs.
+
+
+- address issueintroduce python2.5 support by vendoring the virtualenv-1.9.1 
script
+  and forcing pip<1.4. Also the default [py25] environment modifies the
+  default installer_command (new config option) to use pip without the "--pre" 
+  which was introduced with pip-1.4 and is required if you want to install 
non-stable releases.
+  (tox defaults to install with "--pre" otherwise).
+
 - fix issue1: empty setup files are properly detected, thanks Anthon van
   der Neuth
 
@@ -11,10 +22,6 @@
 
 - remove toxbootstrap.py for now because it is broken.
 
-- fix issue35: add new "install_command" testenv-option to configure the
-  installation command with options for dep/pkg install.  Thanks Carl Meyer
-  for the PR and docs.
-
 - fix issue109 and fix issue111: multiple "-e" options are now combined
   (previously the last one would win). Thanks Anthon van der Neut.
 

diff -r 4949def7e678884e07157f12d7c33aead42227f7 -r 
50bd50082b7cacf9a11ed5605d0af3383db23e8b doc/config.txt
--- a/doc/config.txt
+++ b/doc/config.txt
@@ -80,9 +80,12 @@
 
     .. versionadded:: 1.6
 
-    the command to be used for installing packages into the virtual
-    environment; both the sdist for the package under test and any
-    defined dependencies. Must contain the substitution key
+    **WARNING**: This setting is **EXPERIMENTAL** so use with care 
+    and be ready to adapt your tox.ini's with post-1.6 tox releases.
+
+    the ``install_command`` setting is used for installing packages into
+    the virtual environment; both the package under test
+    and any defined dependencies. Must contain the substitution key
     ``{packages}`` which will be replaced by the packages to
     install. May also contain the substitution key ``{opts}``, which
     will be replaced by the ``-i`` option to specify index server
@@ -94,7 +97,16 @@
     :confval:`downloadcache`, and/or your :confval:`install_command`
     should not include the ``{opts}`` substitution key (in which case
     those options will have no effect).
-    **default**: ``pip install {opts} {packages}``
+    **default**::
+    
+        pip install --pre {opts} {packages}
+
+    **default on environment names containing 'py25'**::
+
+        pip install --insecure {opts} {packages}`` 
+
+    (this will use pip<1.4 (so no "--pre" option) and 
+    python2.5 typically has no SSL support).
 
 .. confval:: whitelist_externals=MULTI-LINE-LIST
 
@@ -137,37 +149,41 @@
 
 .. confval:: downloadcache=path
 
+    **DEPRECATED** -- as of August 2013 this option is not very
+    useful because of pypi's CDN and because of caching pypi
+    server solutions like `devpi <http://doc.devpi.net>`_.
+
     use this directory for caching downloads.  This value is overriden
     by the environment variable ``PIP_DOWNLOAD_CACHE`` if it exists. If
     you specify a custom :confval:`install_command` that uses an
     installer other than pip, your installer must support the
     `--download-cache` command-line option.
     **default**: no download cache will be used.
-    **note**: if creating multiple environments use of a download cache greatly
-    speeds up the testing process.
 
 .. confval:: distribute=True|False
 
-    Set to ``True`` if you want to use distribute_ instead of the default
-    setuptools_ in the virtual environment.  Prior to tox-1.5 the
-    default was True and now is False, meaning ``setuptools`` is used 
-    (note that setuptools-0.7 merged with distribute).  In future versions 
-    of tox this option might be ignored and setuptools always chosen.
+    **DEPRECATED** -- as of August 2013 you should use setuptools
+    which has merged most of distribute_ 's changes.  Just use
+    the default, Luke!  In future versions of tox this option might 
+    be ignored and setuptools always chosen.  
+
     **default:** False.
 
 .. confval:: sitepackages=True|False
 
     Set to ``True`` if you want to create virtual environments that also
-    have access to globally installed packages.  **default:** False, meaning
-    that virtualenvs will be created with ``--no-site-packages`` by default.
+    have access to globally installed packages.  
+
+    **default:** False, meaning that virtualenvs will be 
+    created without inheriting the global site packages.
 
 .. confval:: args_are_paths=BOOL
 
     treat positional arguments passed to ``tox`` as file system paths
     and - if they exist on the filesystem - rewrite them according
     to the ``changedir``.
-    **default**: True (due to the exists-on-filesystem check it's usually
-    safe to try rewriting).
+    **default**: True (due to the exists-on-filesystem check it's 
+    usually safe to try rewriting).
 
 .. confval:: envtmpdir=path
 

diff -r 4949def7e678884e07157f12d7c33aead42227f7 -r 
50bd50082b7cacf9a11ed5605d0af3383db23e8b tests/test_config.py
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -473,14 +473,28 @@
         assert envconfig.changedir.basename == "abc"
         assert envconfig.changedir == config.setupdir.join("abc")
 
-    def test_install_command(self, newconfig):
+    def test_install_command_defaults_py25(self, newconfig):
+        config = newconfig("""
+            [testenv:py25]
+            [testenv:py25-x]
+            [testenv:py26]
+        """)
+        for name in ("py25", "py25-x"):
+            env = config.envconfigs[name]
+            assert env.install_command == \
+               "pip install --insecure {opts} {packages}".split()
+        env = config.envconfigs["py26"]
+        assert env.install_command == \
+               "pip install --pre {opts} {packages}".split()
+
+    def test_install_command_setting(self, newconfig):
         config = newconfig("""
             [testenv]
-            install_command=pip install --pre {packages}
+            install_command=some_install {packages}
         """)
         envconfig = config.envconfigs['python']
-        assert envconfig.install_command_argv == [
-            'pip', 'install', '--pre', '{packages}']
+        assert envconfig.install_command == [
+            'some_install', '{packages}']
 
     def test_install_command_must_contain_packages(self, newconfig):
         py.test.raises(tox.exception.ConfigError, newconfig, """
@@ -506,7 +520,8 @@
         envconfig = config.envconfigs['python']
         assert envconfig.downloadcache == '/from/env'
 
-    def test_downloadcache_only_if_in_config(self, newconfig, tmpdir, 
monkeypatch):
+    def test_downloadcache_only_if_in_config(self, newconfig, tmpdir,
+                                             monkeypatch):
         monkeypatch.setenv("PIP_DOWNLOAD_CACHE", tmpdir)
         config = newconfig('')
         envconfig = config.envconfigs['python']
@@ -744,7 +759,8 @@
         config = newconfig(["-vv"], "")
         assert config.option.verbosity == 2
 
-    def test_substitution_jenkins_default(self, tmpdir, monkeypatch, 
newconfig):
+    def test_substitution_jenkins_default(self, tmpdir,
+                                          monkeypatch, newconfig):
         monkeypatch.setenv("HUDSON_URL", "xyz")
         config = newconfig("""
             [testenv:py24]

diff -r 4949def7e678884e07157f12d7c33aead42227f7 -r 
50bd50082b7cacf9a11ed5605d0af3383db23e8b tests/test_z_cmdline.py
--- a/tests/test_z_cmdline.py
+++ b/tests/test_z_cmdline.py
@@ -10,11 +10,6 @@
 
 pytest_plugins = "pytester"
 
-if sys.version_info < (2,6):
-    PIP_INSECURE = "setenv = PIP_INSECURE=1"
-else:
-    PIP_INSECURE = ""
-
 from tox._cmdline import Session
 from tox._config import parseconfig
 
@@ -379,10 +374,10 @@
             'tox.ini': '''
                 [testenv]
                 changedir=tests
-                %s
-                commands= py.test --basetemp={envtmpdir} 
--junitxml=junit-{envname}.xml
+                commands= py.test --basetemp={envtmpdir} \
+                                  --junitxml=junit-{envname}.xml
                 deps=pytest
-            ''' % PIP_INSECURE
+            '''
         })
 
     def test_toxuone_env(self, cmd, example123):
@@ -473,11 +468,10 @@
             [testenv]
             usedevelop=True
             changedir=tests
-            %s
             commands=
                 py.test --basetemp={envtmpdir} --junitxml=junit-{envname}.xml 
[]
             deps=pytest
-        ''' % PIP_INSECURE
+        '''
     })
     result = cmd.run("tox", "-v")
     assert not result.ret
@@ -521,9 +515,9 @@
         # content of: tox.ini
         [testenv]
         commands=pip -h
-        [testenv:py25]
+        [testenv:py26]
         basepython=python
-        [testenv:py26]
+        [testenv:py27]
         basepython=python
     """})
     result = cmd.run("tox")
@@ -532,19 +526,19 @@
 def test_notest(initproj, cmd):
     initproj("example123", filedefs={'tox.ini': """
         # content of: tox.ini
-        [testenv:py25]
+        [testenv:py26]
         basepython=python
     """})
     result = cmd.run("tox", "-v", "--notest")
     assert not result.ret
     result.stdout.fnmatch_lines([
         "*summary*",
-        "*py25*skipped tests*",
+        "*py26*skipped tests*",
     ])
-    result = cmd.run("tox", "-v", "--notest", "-epy25")
+    result = cmd.run("tox", "-v", "--notest", "-epy26")
     assert not result.ret
     result.stdout.fnmatch_lines([
-        "*py25*reusing*",
+        "*py26*reusing*",
     ])
 
 def test_PYC(initproj, cmd, monkeypatch):

diff -r 4949def7e678884e07157f12d7c33aead42227f7 -r 
50bd50082b7cacf9a11ed5605d0af3383db23e8b tox.ini
--- a/tox.ini
+++ b/tox.ini
@@ -8,10 +8,6 @@
 commands=py.test  --junitxml={envlogdir}/junit-{envname}.xml {posargs}
 deps=pytest>=2.3.5
 
-[testenv:py25]   # requires virtualenv-1.9.1
-setenvs =
-    PIP_INSECURE=True
-
 [testenv:docs]
 basepython=python
 changedir=doc

diff -r 4949def7e678884e07157f12d7c33aead42227f7 -r 
50bd50082b7cacf9a11ed5605d0af3383db23e8b tox/_cmdline.py
--- a/tox/_cmdline.py
+++ b/tox/_cmdline.py
@@ -492,6 +492,8 @@
             self.report.line("  envlogdir=%s" % envconfig.envlogdir)
             self.report.line("  changedir=%s" % envconfig.changedir)
             self.report.line("  args_are_path=%s" % envconfig.args_are_paths)
+            self.report.line("  install_command=%s" %
+                             envconfig.install_command)
             self.report.line("  commands=")
             for command in envconfig.commands:
                 self.report.line("    %s" % command)

diff -r 4949def7e678884e07157f12d7c33aead42227f7 -r 
50bd50082b7cacf9a11ed5605d0af3383db23e8b tox/_config.py
--- a/tox/_config.py
+++ b/tox/_config.py
@@ -76,8 +76,8 @@
     parser.add_argument("-v", nargs=0, action=CountAction, default=0,
         dest="verbosity",
         help="increase verbosity of reporting output.")
-    parser.add_argument("--showconfig", action="store_true", dest="showconfig",
-        help="show configuration information. ")
+    parser.add_argument("--showconfig", action="store_true",
+        help="show configuration information for all environments. ")
     parser.add_argument("-l", "--listenvs", action="store_true",
         dest="listenvs", help="show list of test environments")
     parser.add_argument("-c", action="store", default="tox.ini",
@@ -331,15 +331,24 @@
             # env var, if present, takes precedence
             downloadcache = os.environ.get("PIP_DOWNLOAD_CACHE", downloadcache)
             vc.downloadcache = py.path.local(downloadcache)
-        vc.install_command_argv = reader.getargv(
+
+        # on python 2.5 we can't use "--pre" and we typically
+        # need to use --insecure for pip commands because python2.5
+        # doesn't support SSL
+        pip_default_opts = ["{opts}", "{packages}"]
+        if "py25" in vc.envname:  # XXX too rough check for "python2.5"
+            pip_default_opts.insert(0, "--insecure")
+        else:
+            pip_default_opts.insert(0, "--pre")
+        vc.install_command = reader.getargv(
             section,
             "install_command",
-            "pip install {opts} {packages}",
+            "pip install " + " ".join(pip_default_opts),
             replace=False,
             )
-        if '{packages}' not in vc.install_command_argv:
+        if '{packages}' not in vc.install_command:
             raise tox.exception.ConfigError(
-                "'install_command' must contain '{packages}' substitution")
+             "'install_command' must contain '{packages}' substitution")
         return vc
 
     def _getenvlist(self, reader, toxsection):

diff -r 4949def7e678884e07157f12d7c33aead42227f7 -r 
50bd50082b7cacf9a11ed5605d0af3383db23e8b tox/_venv.py
--- a/tox/_venv.py
+++ b/tox/_venv.py
@@ -285,7 +285,7 @@
 
     def run_install_command(self, args, indexserver=None, action=None,
                             extraenv=None):
-        argv = self.envconfig.install_command_argv[:]
+        argv = self.envconfig.install_command[:]
         # use pip-script on win32 to avoid the executable locking
         if argv[0] == "pip" and sys.platform == "win32":
             argv[0] = "pip-script.py"


https://bitbucket.org/hpk42/tox/commits/efe7d94c863a/
Changeset:   efe7d94c863a
User:        hpk42
Date:        2013-08-15 13:00:39
Summary:     move all interpreter information detection to tox/interpreters.py
Affected #:  9 files

diff -r 50bd50082b7cacf9a11ed5605d0af3383db23e8b -r 
efe7d94c863aabd6ea2d1513b4513ce9b0d4291c CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -5,7 +5,6 @@
   installation command with options for dep/pkg install.  Thanks Carl Meyer
   for the PR and docs.
 
-
 - address issueintroduce python2.5 support by vendoring the virtualenv-1.9.1 
script
   and forcing pip<1.4. Also the default [py25] environment modifies the
   default installer_command (new config option) to use pip without the "--pre" 
@@ -36,6 +35,9 @@
 
 - if a HOMEDIR cannot be determined, use the toxinidir.
 
+- refactor interpreter information detection to live in new
+  tox/interpreters.py file, tests in tests/test_interpreters.py.
+
 1.5.0
 -----------------
 

diff -r 50bd50082b7cacf9a11ed5605d0af3383db23e8b -r 
efe7d94c863aabd6ea2d1513b4513ce9b0d4291c doc/config.txt
--- a/doc/config.txt
+++ b/doc/config.txt
@@ -88,8 +88,8 @@
     and any defined dependencies. Must contain the substitution key
     ``{packages}`` which will be replaced by the packages to
     install. May also contain the substitution key ``{opts}``, which
-    will be replaced by the ``-i`` option to specify index server
-    (according to :confval:`indexserver` and the ``:indexserver:dep``
+    will be replaced by the ``-i INDEXURL`` option if an index server
+    is active (see :confval:`indexserver` and the ``:indexserver:dep``
     syntax of :confval:`deps`) and the ``--download-cache`` option (if
     you've specified :confval:`downloadcache`). If your installer does
     not support ``-i`` and ``--download-cache`` command-line options,

diff -r 50bd50082b7cacf9a11ed5605d0af3383db23e8b -r 
efe7d94c863aabd6ea2d1513b4513ce9b0d4291c tests/test_config.py
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -5,9 +5,9 @@
 from textwrap import dedent
 
 import py
-from tox._config import IniReader, CommandParser
-from tox._config import parseconfig
-from tox._config import prepare_parse, _split_env
+from tox._config import *
+from tox._config import _split_env
+
 
 class TestVenvConfig:
     def test_config_parsing_minimal(self, tmpdir, newconfig):
@@ -473,13 +473,29 @@
         assert envconfig.changedir.basename == "abc"
         assert envconfig.changedir == config.setupdir.join("abc")
 
-    def test_install_command_defaults_py25(self, newconfig):
+    def test_install_command_defaults_py25(self, newconfig, monkeypatch):
+        from tox.interpreters import Interpreters
+        def get_info(self, name):
+            if "x25" in name:
+                class I:
+                    runnable = True
+                    executable = "python2.5"
+                    version_info = (2,5)
+            else:
+                class I:
+                    runnable = False
+                    executable = "python"
+            return I
+        monkeypatch.setattr(Interpreters, "get_info", get_info)
         config = newconfig("""
-            [testenv:py25]
+            [testenv:x25]
+            basepython = x25
             [testenv:py25-x]
+            basepython = x25
             [testenv:py26]
+            basepython = "python"
         """)
-        for name in ("py25", "py25-x"):
+        for name in ("x25", "py25-x"):
             env = config.envconfigs[name]
             assert env.install_command == \
                "pip install --insecure {opts} {packages}".split()
@@ -714,36 +730,6 @@
         assert conf.changedir.basename == 'testing'
         assert conf.changedir.dirpath().realpath() == tmpdir.realpath()
 
-    @pytest.mark.xfailif("sys.platform == 'win32'")
-    def test_substitution_envsitepackagesdir(self, tmpdir, monkeypatch,
-                                             newconfig):
-        """
-         The envsitepackagesdir property is mostly doing system work,
-         so this test doesn't excercise it very well.
-
-         Usage of envsitepackagesdir on win32/jython will explicitly
-         throw an exception,
-        """
-        class MockPopen(object):
-            returncode = 0
-
-            def __init__(self, *args, **kwargs):
-                pass
-
-            def communicate(self, *args, **kwargs):
-                return 'onevalue', 'othervalue'
-
-        monkeypatch.setattr(subprocess, 'Popen', MockPopen)
-        env = 'py%s' % (''.join(sys.version.split('.')[0:2]))
-        config = newconfig("""
-            [testenv:%s]
-            commands = {envsitepackagesdir}
-        """ % (env))
-        conf = config.envconfigs[env]
-        argv = conf.commands
-        assert argv[0][0] == 'onevalue'
-
-
 class TestGlobalOptions:
     def test_notest(self, newconfig):
         config = newconfig([], "")

diff -r 50bd50082b7cacf9a11ed5605d0af3383db23e8b -r 
efe7d94c863aabd6ea2d1513b4513ce9b0d4291c tests/test_interpreters.py
--- /dev/null
+++ b/tests/test_interpreters.py
@@ -0,0 +1,95 @@
+import sys
+import os
+
+import pytest
+from tox.interpreters import *
+
+@pytest.fixture
+def interpreters():
+    return Interpreters()
+
+@pytest.mark.skipif("sys.platform != 'win32'")
+def test_locate_via_py(monkeypatch):
+    from tox._venv import locate_via_py
+    class PseudoPy:
+        def sysexec(self, *args):
+            assert args[0] == '-3.2'
+            assert args[1] == '-c'
+            # Return value needs to actually exist!
+            return sys.executable
+    @staticmethod
+    def ret_pseudopy(name):
+        assert name == 'py'
+        return PseudoPy()
+    # Monkeypatch py.path.local.sysfind to return PseudoPy
+    monkeypatch.setattr(py.path.local, 'sysfind', ret_pseudopy)
+    assert locate_via_py('3', '2') == sys.executable
+
+def test_find_executable():
+    p = find_executable(sys.executable)
+    assert p == py.path.local(sys.executable)
+    for ver in [""] + "2.4 2.5 2.6 2.7 3.0 3.1 3.2 3.3".split():
+        name = "python%s" % ver
+        if sys.platform == "win32":
+            pydir = "python%s" % ver.replace(".", "")
+            x = py.path.local("c:\%s" % pydir)
+            print (x)
+            if not x.check():
+                continue
+        else:
+            if not py.path.local.sysfind(name):
+                continue
+        p = find_executable(name)
+        assert p
+        popen = py.std.subprocess.Popen([str(p), '-V'],
+                stderr=py.std.subprocess.PIPE)
+        stdout, stderr = popen.communicate()
+        assert ver in py.builtin._totext(stderr, "ascii")
+
+def test_find_executable_extra(monkeypatch):
+    @staticmethod
+    def sysfind(x):
+        return "hello"
+    monkeypatch.setattr(py.path.local, "sysfind", sysfind)
+    t = find_executable("qweqwe")
+    assert t == "hello"
+
+def test_run_and_get_interpreter_info():
+    name = os.path.basename(sys.executable)
+    info = run_and_get_interpreter_info(name, sys.executable)
+    assert info.version_info == tuple(sys.version_info)
+    assert info.name == name
+    assert info.executable == sys.executable
+
+class TestInterpreters:
+
+    def test_get_info_self_exceptions(self, interpreters):
+        pytest.raises(ValueError, lambda:
+                      interpreters.get_info())
+        pytest.raises(ValueError, lambda:
+                      interpreters.get_info(name="12", executable="123"))
+
+    def test_get_executable(self, interpreters):
+        x = interpreters.get_executable(sys.executable)
+        assert x == sys.executable
+        assert not interpreters.get_executable("12l3k1j23")
+
+    def test_get_info__name(self, interpreters):
+        basename = os.path.basename(sys.executable)
+        info = interpreters.get_info(basename)
+        assert info.version_info == tuple(sys.version_info)
+        assert info.name == basename
+        assert info.executable == sys.executable
+        assert info.runnable
+
+    def test_get_info__name_not_exists(self, interpreters):
+        info = interpreters.get_info("qlwkejqwe")
+        assert not info.version_info
+        assert info.name == "qlwkejqwe"
+        assert not info.executable
+        assert not info.runnable
+
+    def test_get_sitepackagesdir_error(self, interpreters):
+        info = interpreters.get_info(sys.executable)
+        s = interpreters.get_sitepackagesdir(info, "")
+        assert s

diff -r 50bd50082b7cacf9a11ed5605d0af3383db23e8b -r 
efe7d94c863aabd6ea2d1513b4513ce9b0d4291c tests/test_venv.py
--- a/tests/test_venv.py
+++ b/tests/test_venv.py
@@ -2,9 +2,7 @@
 import tox
 import pytest
 import os, sys
-from tox._venv import VirtualEnv, CreationConfig, getdigest
-from tox._venv import find_executable
-from tox._venv import _getinterpreterversion
+from tox._venv import *
 
 py25calls = int(sys.version_info[:2] == (2,5))
 
@@ -19,52 +17,6 @@
 def test_getdigest(tmpdir):
     assert getdigest(tmpdir) == "0"*32
 
-@pytest.mark.skipif("sys.platform != 'win32'")
-def test_locate_via_py(monkeypatch):
-    from tox._venv import locate_via_py
-    class PseudoPy:
-        def sysexec(self, *args):
-            assert args[0] == '-3.2'
-            assert args[1] == '-c'
-            # Return value needs to actually exist!
-            return sys.executable
-    @staticmethod
-    def ret_pseudopy(name):
-        assert name == 'py'
-        return PseudoPy()
-    # Monkeypatch py.path.local.sysfind to return PseudoPy
-    monkeypatch.setattr(py.path.local, 'sysfind', ret_pseudopy)
-    assert locate_via_py('3', '2') == sys.executable
-
-def test_find_executable():
-    p = find_executable(sys.executable)
-    assert p == py.path.local(sys.executable)
-    for ver in [""] + "2.4 2.5 2.6 2.7 3.0 3.1 3.2 3.3".split():
-        name = "python%s" % ver
-        if sys.platform == "win32":
-            pydir = "python%s" % ver.replace(".", "")
-            x = py.path.local("c:\%s" % pydir)
-            print (x)
-            if not x.check():
-                continue
-        else:
-            if not py.path.local.sysfind(name):
-                continue
-        p = find_executable(name)
-        assert p
-        popen = py.std.subprocess.Popen([str(p), '-V'],
-                stderr=py.std.subprocess.PIPE)
-        stdout, stderr = popen.communicate()
-        assert ver in py.builtin._totext(stderr, "ascii")
-
-def test_find_executable_extra(monkeypatch):
-    @staticmethod
-    def sysfind(x):
-        return "hello"
-    monkeypatch.setattr(py.path.local, "sysfind", sysfind)
-    t = find_executable("qweqwe")
-    assert t == "hello"
-
 def test_getsupportedinterpreter(monkeypatch, newconfig, mocksession):
     config = newconfig([], """
         [testenv:python]
@@ -83,10 +35,6 @@
     py.test.raises(tox.exception.InterpreterNotFound,
                    venv.getsupportedinterpreter)
 
-def test_getinterpreterversion():
-    from distutils.sysconfig import get_python_version
-    version = _getinterpreterversion(sys.executable)
-    assert version == get_python_version()
 
 def test_create(monkeypatch, mocksession, newconfig):
     config = newconfig([], """
@@ -107,7 +55,7 @@
         #assert Envconfig.toxworkdir in args
         assert venv.getcommandpath("easy_install", cwd=py.path.local())
     interp = venv._getliveconfig().python
-    assert interp == venv.getconfigexecutable()
+    assert interp == venv.envconfig._basepython_info.executable
     assert venv.path_config.check(exists=False)
 
 @pytest.mark.skipif("sys.platform == 'win32'")
@@ -243,7 +191,7 @@
     # two different index servers, two calls
     assert len(l) == 3
     args = " ".join(l[0].args)
-    assert "-i" not in args
+    assert "-i " not in args
     assert "dep1" in args
 
     args = " ".join(l[1].args)

diff -r 50bd50082b7cacf9a11ed5605d0af3383db23e8b -r 
efe7d94c863aabd6ea2d1513b4513ce9b0d4291c tox/_cmdline.py
--- a/tox/_cmdline.py
+++ b/tox/_cmdline.py
@@ -486,6 +486,8 @@
         for envconfig in self.config.envconfigs.values():
             self.report.line("[testenv:%s]" % envconfig.envname, bold=True)
             self.report.line("  basepython=%s" % envconfig.basepython)
+            self.report.line("  _basepython_info=%s" %
+                             envconfig._basepython_info)
             self.report.line("  envpython=%s" % envconfig.envpython)
             self.report.line("  envtmpdir=%s" % envconfig.envtmpdir)
             self.report.line("  envbindir=%s" % envconfig.envbindir)

diff -r 50bd50082b7cacf9a11ed5605d0af3383db23e8b -r 
efe7d94c863aabd6ea2d1513b4513ce9b0d4291c tox/_config.py
--- a/tox/_config.py
+++ b/tox/_config.py
@@ -8,6 +8,8 @@
 import subprocess
 import textwrap
 
+from tox.interpreters import Interpreters
+
 import py
 
 import tox
@@ -118,6 +120,7 @@
     def __init__(self):
         self.envconfigs = {}
         self.invocationcwd = py.path.local()
+        self.interpreters = Interpreters()
 
 class VenvConfig:
     def __init__(self, **kw):
@@ -141,32 +144,10 @@
 
     # no @property to avoid early calling (see callable(subst[key]) checks)
     def envsitepackagesdir(self):
-        print_envsitepackagesdir = textwrap.dedent("""
-        import sys
-        from distutils.sysconfig import get_python_lib
-        sys.stdout.write(get_python_lib(prefix=sys.argv[1]))
-        """)
-
-        exe = self.getsupportedinterpreter()
-        # can't use check_output until py27
-        proc = subprocess.Popen(
-            [str(exe), '-c', print_envsitepackagesdir, str(self.envdir)],
-            stdout=subprocess.PIPE)
-        odata, edata = proc.communicate()
-        if proc.returncode:
-            raise tox.exception.UnsupportedInterpreter(
-                "Error getting site-packages from %s" % self.basepython)
-        return odata
-
-    def getconfigexecutable(self):
-        from tox._venv import find_executable
-
-        python = self.basepython
-        if not python:
-            python = sys.executable
-        x = find_executable(str(python))
-        if x:
-            x = x.realpath()
+        self.getsupportedinterpreter()  # for throwing exceptions
+        x = self.config.interpreters.get_sitepackagesdir(
+                info=self._basepython_info,
+                envdir=self.envdir)
         return x
 
     def getsupportedinterpreter(self):
@@ -174,10 +155,11 @@
                 "jython" in self.basepython:
             raise tox.exception.UnsupportedInterpreter(
                 "Jython/Windows does not support installing scripts")
-        config_executable = self.getconfigexecutable()
-        if not config_executable:
+        info = self.config.interpreters.get_info(self.basepython)
+        if not info.executable:
             raise tox.exception.InterpreterNotFound(self.basepython)
-        return config_executable
+        return info.executable
+
 testenvprefix = "testenv:"
 
 class parseini:
@@ -285,6 +267,7 @@
         else:
             bp = sys.executable
         vc.basepython = reader.getdefault(section, "basepython", bp)
+        vc._basepython_info = config.interpreters.get_info(vc.basepython)
         reader.addsubstitions(envdir=vc.envdir, envname=vc.envname,
                               envbindir=vc.envbindir, envpython=vc.envpython,
                               envsitepackagesdir=vc.envsitepackagesdir)
@@ -336,7 +319,8 @@
         # need to use --insecure for pip commands because python2.5
         # doesn't support SSL
         pip_default_opts = ["{opts}", "{packages}"]
-        if "py25" in vc.envname:  # XXX too rough check for "python2.5"
+        info = vc._basepython_info
+        if info.runnable and info.version_info < (2,6):
             pip_default_opts.insert(0, "--insecure")
         else:
             pip_default_opts.insert(0, "--pre")

diff -r 50bd50082b7cacf9a11ed5605d0af3383db23e8b -r 
efe7d94c863aabd6ea2d1513b4513ce9b0d4291c tox/_venv.py
--- a/tox/_venv.py
+++ b/tox/_venv.py
@@ -145,7 +145,7 @@
             return "could not install deps %s" %(self.envconfig.deps,)
 
     def _getliveconfig(self):
-        python = self.getconfigexecutable()
+        python = self.envconfig._basepython_info.executable
         md5 = getdigest(python)
         version = tox.__version__
         distribute = self.envconfig.distribute
@@ -169,9 +169,6 @@
             l.append(dep)
         return l
 
-    def getconfigexecutable(self):
-        return self.envconfig.getconfigexecutable()
-
     def getsupportedinterpreter(self):
         return self.envconfig.getsupportedinterpreter()
 
@@ -180,11 +177,11 @@
         #    return
         if action is None:
             action = self.session.newaction(self, "create")
+
+        interpreters = self.envconfig.config.interpreters
         config_interpreter = self.getsupportedinterpreter()
-        config_interpreter_version = _getinterpreterversion(
-            config_interpreter)
-        use_venv191 = config_interpreter_version < '2.6'
-        use_pip13 = config_interpreter_version < '2.6'
+        info = interpreters.get_info(executable=config_interpreter)
+        use_venv191 = use_pip13 = info.version_info < (2,6)
         if not use_venv191:
             f, path, _ = py.std.imp.find_module("virtualenv")
             f.close()
@@ -389,21 +386,6 @@
         self.session.report.verbosity2("setting PATH=%s" % os.environ["PATH"])
         return oldPATH
 
-def _getinterpreterversion(executable):
-    print_python_version = (
-        'from distutils.sysconfig import get_python_version\n'
-        'print(get_python_version())\n')
-    proc = subprocess.Popen([str(executable), '-c', print_python_version],
-                            stdout=subprocess.PIPE)
-    odata, edata = proc.communicate()
-    if proc.returncode:
-        raise tox.exception.UnsupportedInterpreter(
-            "Error getting python version from %s" % executable)
-    if sys.version_info[0] == 3:
-        string = str
-    else:
-        string = lambda x, encoding: str(x)
-    return string(odata, 'ascii').strip()
 
 def getdigest(path):
     path = py.path.local(path)
@@ -411,51 +393,6 @@
         return "0" * 32
     return path.computehash()
 
-if sys.platform != "win32":
-    def find_executable(name):
-        return py.path.local.sysfind(name)
-
-else:
-    # Exceptions to the usual windows mapping
-    win32map = {
-            'python': sys.executable,
-            'jython': "c:\jython2.5.1\jython.bat",
-    }
-    def locate_via_py(v_maj, v_min):
-        ver = "-%s.%s" % (v_maj, v_min)
-        script = "import sys; print(sys.executable)"
-        py_exe = py.path.local.sysfind('py')
-        if py_exe:
-            try:
-                exe = py_exe.sysexec(ver, '-c', script).strip()
-            except py.process.cmdexec.Error:
-                exe = None
-            if exe:
-                exe = py.path.local(exe)
-                if exe.check():
-                    return exe
-
-    def find_executable(name):
-        p = py.path.local.sysfind(name)
-        if p:
-            return p
-        actual = None
-        # Is this a standard PythonX.Y name?
-        m = re.match(r"python(\d)\.(\d)", name)
-        if m:
-            # The standard names are in predictable places.
-            actual = r"c:\python%s%s\python.exe" % m.groups()
-        if not actual:
-            actual = win32map.get(name, None)
-        if actual:
-            actual = py.path.local(actual)
-            if actual.check():
-                return actual
-        # The standard executables can be found as a last resort via the
-        # Python launcher py.exe
-        if m:
-            locate_via_py(*m.groups())
-
 
 def hack_home_env(homedir, index_url=None):
     # XXX HACK (this could also live with tox itself, consider)

diff -r 50bd50082b7cacf9a11ed5605d0af3383db23e8b -r 
efe7d94c863aabd6ea2d1513b4513ce9b0d4291c tox/interpreters.py
--- /dev/null
+++ b/tox/interpreters.py
@@ -0,0 +1,170 @@
+import sys
+import os
+import py
+import subprocess
+import inspect
+
+class Interpreters:
+    def __init__(self):
+        self.name2executable = {}
+        self.executable2info = {}
+
+    def get_executable(self, name):
+        """ return path object to the executable for the given
+        name (e.g. python2.5, python2.7, python etc.)
+        if name is already an existing path, return name.
+        If an interpreter cannot be found, return None.
+        """
+        try:
+            return self.name2executable[name]
+        except KeyError:
+            self.name2executable[name] = e = find_executable(name)
+            return e
+
+    def get_info(self, name=None, executable=None):
+        if name is None and executable is None:
+            raise ValueError("need to specify name or executable")
+        if name:
+            if executable is not None:
+                raise ValueError("cannot specify both name, executable")
+            executable = self.get_executable(name)
+        if not executable:
+            return NoInterpreterInfo(name=name)
+        try:
+            return self.executable2info[executable]
+        except KeyError:
+            info = run_and_get_interpreter_info(name, executable)
+            self.executable2info[executable] = info
+            return info
+
+    def get_sitepackagesdir(self, info, envdir):
+        if not info.executable:
+            return ""
+        envdir = str(envdir)
+        try:
+            res = exec_on_interpreter(info.executable,
+                [inspect.getsource(sitepackagesdir),
+                 "print (sitepackagesdir(%r))" % envdir])
+        except ExecFailed:
+            val = sys.exc_info()[1]
+            print ("execution failed: %s -- %s" %(val.out, val.err))
+            return ""
+        else:
+            return res["dir"]
+
+def run_and_get_interpreter_info(name, executable):
+    assert executable
+    try:
+        result = exec_on_interpreter(executable,
+            [inspect.getsource(pyinfo), "print (pyinfo())"])
+    except ExecFailed:
+        val = sys.exc_info()[1]
+        return NoInterpreterInfo(name, **val.__dict__)
+    else:
+        return InterpreterInfo(name, executable, **result)
+
+def exec_on_interpreter(executable, source):
+    if isinstance(source, list):
+        source = "\n".join(source)
+    from subprocess import Popen, PIPE
+    args = [str(executable)]
+    popen = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
+    popen.stdin.write(source.encode("utf8"))
+    out, err = popen.communicate()
+    if popen.returncode:
+        raise ExecFailed(executable, source, out, err)
+    try:
+        result = eval(out)
+    except Exception:
+        raise ExecFailed(executable, source, out,
+                         "could not decode %r" % out)
+    return result
+
+class ExecFailed(Exception):
+    def __init__(self, executable, source, out, err):
+        self.executable = executable
+        self.source = source
+        self.out = out
+        self.err = err
+
+class InterpreterInfo:
+    runnable = True
+
+    def __init__(self, name, executable, version_info):
+        assert name and executable and version_info
+        self.name = name
+        self.executable = executable
+        self.version_info = version_info
+
+    def __str__(self):
+        return "<executable at %s, version_info %s>" % (
+                self.executable, self.version_info)
+
+class NoInterpreterInfo:
+    runnable = False
+    def __init__(self, name, executable=None,
+                 out=None, err="not found"):
+        self.name = name
+        self.executable = executable
+        self.version_info = None
+        self.out = out
+        self.err = err
+
+    def __str__(self):
+        if self.executable:
+            return "<executable at %s, not runnable>"
+        else:
+            return "<executable not found for: %s>" % self.name
+
+if sys.platform != "win32":
+    def find_executable(name):
+        return py.path.local.sysfind(name)
+
+else:
+    # Exceptions to the usual windows mapping
+    win32map = {
+            'python': sys.executable,
+            'jython': "c:\jython2.5.1\jython.bat",
+    }
+    def locate_via_py(v_maj, v_min):
+        ver = "-%s.%s" % (v_maj, v_min)
+        script = "import sys; print(sys.executable)"
+        py_exe = py.path.local.sysfind('py')
+        if py_exe:
+            try:
+                exe = py_exe.sysexec(ver, '-c', script).strip()
+            except py.process.cmdexec.Error:
+                exe = None
+            if exe:
+                exe = py.path.local(exe)
+                if exe.check():
+                    return exe
+
+    def find_executable(name):
+        p = py.path.local.sysfind(name)
+        if p:
+            return p
+        actual = None
+        # Is this a standard PythonX.Y name?
+        m = re.match(r"python(\d)\.(\d)", name)
+        if m:
+            # The standard names are in predictable places.
+            actual = r"c:\python%s%s\python.exe" % m.groups()
+        if not actual:
+            actual = win32map.get(name, None)
+        if actual:
+            actual = py.path.local(actual)
+            if actual.check():
+                return actual
+        # The standard executables can be found as a last resort via the
+        # Python launcher py.exe
+        if m:
+            locate_via_py(*m.groups())
+
+def pyinfo():
+    import sys
+    return dict(version_info=tuple(sys.version_info))
+
+def sitepackagesdir(envdir):
+    from distutils.sysconfig import get_python_lib
+    return dict(dir=get_python_lib(envdir))


https://bitbucket.org/hpk42/tox/commits/33e5e5dff406/
Changeset:   33e5e5dff406
User:        hpk42
Date:        2013-08-15 14:10:14
Summary:     refactor docs and changelog
Affected #:  11 files

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,24 +1,26 @@
-1.6.0.dev
+1.6.0
 -----------------
 
-- fix issue35: add new EXPERIMENTAL "install_command" testenv-option to 
configure the
-  installation command with options for dep/pkg install.  Thanks Carl Meyer
-  for the PR and docs.
+- fix issue35: add new EXPERIMENTAL "install_command" testenv-option to
+  configure the installation command with options for dep/pkg install.
+  Thanks Carl Meyer for the PR and docs.
 
-- address issueintroduce python2.5 support by vendoring the virtualenv-1.9.1 
script
-  and forcing pip<1.4. Also the default [py25] environment modifies the
-  default installer_command (new config option) to use pip without the "--pre" 
-  which was introduced with pip-1.4 and is required if you want to install 
non-stable releases.
-  (tox defaults to install with "--pre" otherwise).
+- fix issue91: python2.5 support by vendoring the virtualenv-1.9.1 
+  script and forcing pip<1.4. Also the default [py25] environment 
+  modifies the default installer_command (new config option)
+  to use pip without the "--pre" option which was introduced 
+  with pip-1.4 and is now required if you want to install non-stable 
+  releases.  (tox defaults to install with "--pre" everywhere).
+
+- during installation of dependencies HOME is now set to a pseudo
+  location ({envtmpdir}/pseudo-home).  If an index url was specified
+  a .pydistutils.cfg file will be written with an index_url setting
+  so that packages defining ``setup_requires`` dependencies will not
+  silently use your HOME-directory settings or https://pypi.python.org.
 
 - fix issue1: empty setup files are properly detected, thanks Anthon van
   der Neuth
 
-- during installation of dependencies HOME is set to a pseudo
-  location (envtmpdir/pseudo-home).  If an index url was specified
-  a .pydistutils.cfg file will be written so that index_url
-  is set if a package contains a ``setup_requires``. 
-
 - remove toxbootstrap.py for now because it is broken.
 
 - fix issue109 and fix issue111: multiple "-e" options are now combined

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b doc/conf.py
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -48,7 +48,7 @@
 # built documents.
 #
 # The short X.Y version.
-release = version = "1.5.0"
+release = version = "1.6.0"
 # The full version, including alpha/beta/rc tags.
 
 # The language for content autogenerated by Sphinx. Refer to documentation

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b doc/config.txt
--- a/doc/config.txt
+++ b/doc/config.txt
@@ -87,26 +87,22 @@
     the virtual environment; both the package under test
     and any defined dependencies. Must contain the substitution key
     ``{packages}`` which will be replaced by the packages to
-    install. May also contain the substitution key ``{opts}``, which
-    will be replaced by the ``-i INDEXURL`` option if an index server
-    is active (see :confval:`indexserver` and the ``:indexserver:dep``
-    syntax of :confval:`deps`) and the ``--download-cache`` option (if
-    you've specified :confval:`downloadcache`). If your installer does
-    not support ``-i`` and ``--download-cache`` command-line options,
-    you should not use :confval:`indexserver` or
-    :confval:`downloadcache`, and/or your :confval:`install_command`
-    should not include the ``{opts}`` substitution key (in which case
-    those options will have no effect).
+    install.  You should also accept "{opts}" if you are using
+    pip or easy_install -- it will contain index server options
+    if you have configured them via :confval:`indexserver`
+    and the deprecated :confval:`downloadcache` option
+    if you have configured it.
+
     **default**::
     
         pip install --pre {opts} {packages}
-
-    **default on environment names containing 'py25'**::
+         
+    **default on environments using python2.5**::
 
         pip install --insecure {opts} {packages}`` 
 
-    (this will use pip<1.4 (so no "--pre" option) and 
-    python2.5 typically has no SSL support).
+    (this will use pip<1.4 (so no ``--pre`` option) and python2.5 
+    typically has no SSL support, therefore ``--insecure``).
 
 .. confval:: whitelist_externals=MULTI-LINE-LIST
 

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b doc/example/basic.txt
--- a/doc/example/basic.txt
+++ b/doc/example/basic.txt
@@ -114,28 +114,21 @@
 
 .. versionadded:: 1.6
 
-By default tox uses `pip`_ to install packages (both the sdist of your
-package-under-test and any dependencies you specify in ``tox.ini``) into each
-test virtualenv, with a command-line like ``pip install --pre
-SomePackage==1.0``.
-
-You can fully customize tox's install-command in your ``tox.ini`` with the
-``install_command`` option. For instance, to use ``easy_install`` instead of
-`pip`_::
+By default tox uses `pip`_ to install packages, both the
+package-under-test and any dependencies you specify in ``tox.ini``.
+You can fully customize tox's install-command through the
+testenv-specific :confval:`install_command=ARGV` setting.
+For instance, to use ``easy_install`` instead of `pip`_::
 
     [testenv]
-    install_command = easy_install {packages}
+    install_command = easy_install {opts} {packages}
 
-Or to use pip's ``--find-links`` and ``--no-index`` options to specify an
-alternative source for your dependencies::
+Or to use pip's ``--find-links`` and ``--no-index`` options to specify
+an alternative source for your dependencies::
 
     [testenv]
     install_command = pip install --pre --find-links 
http://packages.example.com --no-index {opts} {packages}
 
-(Including ``{opts}`` is only necessary if you want your install command to
-also respect tox's options for setting the download cache and package index
-server).
-
 .. _pip: http://pip-installer.org
 
 forcing re-creation of virtual environments

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b doc/index.txt
--- a/doc/index.txt
+++ b/doc/index.txt
@@ -66,10 +66,13 @@
 
 * supports :ref:`using different / multiple PyPI index servers  <multiindex>`
 
-* uses pip_ and distribute_ by default.
+* uses pip_ and setuptools_ by default.  Experimental
+  support for configuring the installer command 
+  through :confval:`install_command=ARGV`.
 
-* **cross-Python compatible**: Python-2.5 up to Python-3.3, Jython and pypy_
-  support.
+* **cross-Python compatible**: Python-2.5 up to Python-3.3, 
+  Jython and pypy_ support.  Python-2.5 is supported through
+  a vendored ``virtualenv-1.9.1`` script.
 
 * **cross-platform**: Windows and Unix style environments
 
@@ -77,8 +80,9 @@
   (formerly known as Hudson) and helps you to avoid boilerplatish 
   and platform-specific build-step hacks.
 
-* **unified automatic artifact management** between ``tox`` runs both
-  in a local developer shell as well as in a CI/Jenkins context.
+* **full interoperability with devpi**: is integrated with and
+  is used for testing in the devpi_ system, a versatile pypi 
+  index server and release managing tool.
 
 * **driven by a simple ini-style config file**
 

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b doc/links.txt
--- a/doc/links.txt
+++ b/doc/links.txt
@@ -1,4 +1,5 @@
 
+.. _devpi: http://doc.devpi.net
 .. _Python: http://www.python.org
 .. _virtualenv: https://pypi.python.org/pypi/virtualenv
 .. _virtualenv3: https://pypi.python.org/pypi/virtualenv3

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b setup.py
--- a/setup.py
+++ b/setup.py
@@ -28,7 +28,7 @@
         description='virtualenv-based automation of test activities',
         long_description=open("README.rst").read(),
         url='http://tox.testrun.org/',
-        version='1.6rc2',
+        version='1.6.0',
         license='http://opensource.org/licenses/MIT',
         platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
         author='holger krekel',

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b tests/test_config.py
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -522,19 +522,19 @@
         monkeypatch.delenv("PIP_DOWNLOAD_CACHE", raising=False)
         config = newconfig("""
             [testenv]
-            downloadcache=/the/cache
+            downloadcache=thecache
         """)
         envconfig = config.envconfigs['python']
-        assert envconfig.downloadcache == '/the/cache'
+        assert envconfig.downloadcache.basename == 'thecache'
 
     def test_downloadcache_env_override(self, newconfig, monkeypatch):
-        monkeypatch.setenv("PIP_DOWNLOAD_CACHE", '/from/env')
+        monkeypatch.setenv("PIP_DOWNLOAD_CACHE", 'fromenv')
         config = newconfig("""
             [testenv]
-            downloadcache=/from/config
+            downloadcache=somepath
         """)
         envconfig = config.envconfigs['python']
-        assert envconfig.downloadcache == '/from/env'
+        assert envconfig.downloadcache.basename == "fromenv"
 
     def test_downloadcache_only_if_in_config(self, newconfig, tmpdir,
                                              monkeypatch):

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b tests/test_interpreters.py
--- a/tests/test_interpreters.py
+++ b/tests/test_interpreters.py
@@ -10,7 +10,6 @@
 
 @pytest.mark.skipif("sys.platform != 'win32'")
 def test_locate_via_py(monkeypatch):
-    from tox._venv import locate_via_py
     class PseudoPy:
         def sysexec(self, *args):
             assert args[0] == '-3.2'
@@ -75,10 +74,8 @@
         assert not interpreters.get_executable("12l3k1j23")
 
     def test_get_info__name(self, interpreters):
-        basename = os.path.basename(sys.executable)
-        info = interpreters.get_info(basename)
+        info = interpreters.get_info(executable=sys.executable)
         assert info.version_info == tuple(sys.version_info)
-        assert info.name == basename
         assert info.executable == sys.executable
         assert info.runnable
 

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b tox/__init__.py
--- a/tox/__init__.py
+++ b/tox/__init__.py
@@ -1,5 +1,5 @@
 #
-__version__ = '1.6rc2'
+__version__ = '1.6.0'
 
 class exception:
     class Error(Exception):

diff -r efe7d94c863aabd6ea2d1513b4513ce9b0d4291c -r 
33e5e5dff406e699893a65ecd5044d3eee35b69b tox/interpreters.py
--- a/tox/interpreters.py
+++ b/tox/interpreters.py
@@ -1,6 +1,7 @@
 import sys
 import os
 import py
+import re
 import subprocess
 import inspect
 
@@ -59,7 +60,8 @@
             [inspect.getsource(pyinfo), "print (pyinfo())"])
     except ExecFailed:
         val = sys.exc_info()[1]
-        return NoInterpreterInfo(name, **val.__dict__)
+        return NoInterpreterInfo(name, executable=val.executable,
+                                 out=val.out, err=val.err)
     else:
         return InterpreterInfo(name, executable, **result)
 
@@ -74,7 +76,7 @@
     if popen.returncode:
         raise ExecFailed(executable, source, out, err)
     try:
-        result = eval(out)
+        result = eval(out.strip())
     except Exception:
         raise ExecFailed(executable, source, out,
                          "could not decode %r" % out)
@@ -91,7 +93,7 @@
     runnable = True
 
     def __init__(self, name, executable, version_info):
-        assert name and executable and version_info
+        assert executable and version_info
         self.name = name
         self.executable = executable
         self.version_info = version_info

Repository URL: https://bitbucket.org/hpk42/tox/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
_______________________________________________
pytest-commit mailing list
pytest-commit@python.org
http://mail.python.org/mailman/listinfo/pytest-commit

Reply via email to