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 *
+
[email protected]
+def interpreters():
+ return Interpreters()
+
[email protected]("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
[email protected]("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
[email protected]
http://mail.python.org/mailman/listinfo/pytest-commit