summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGábor Bernát <jokerjokerer@gmail.com>2017-12-12 14:36:04 +0000
committerGitHub <noreply@github.com>2017-12-12 14:36:04 +0000
commit6b16b095f8b603c23aefe8155cb4e6867db8c178 (patch)
tree206e208eb1bee9d79bab9153415267dc9fa67d13
parent087ed06a73ce78b229660ff79c83706fbeacbca7 (diff)
downloadtox-git-6b16b095f8b603c23aefe8155cb4e6867db8c178.tar.gz
cmd simplify, use pytest stderr/stdout management, and use regex instead of fnmatch (#711)
* Python 2.6 support dropped, this line can never be reached * main args is required, set at entry level * fix pypy failure * remove dead code
-rw-r--r--tests/conftest.py4
-rw-r--r--tests/test_config.py132
-rw-r--r--tests/test_interpreters.py5
-rw-r--r--tests/test_pytest_plugins.py50
-rw-r--r--tests/test_venv.py5
-rw-r--r--tests/test_z_cmdline.py439
-rw-r--r--tox.ini3
-rw-r--r--tox/__init__.py8
-rw-r--r--tox/__main__.py4
-rw-r--r--tox/_pytestplugin.py173
-rw-r--r--tox/_quickstart.py4
-rw-r--r--tox/_verlib.py1
-rwxr-xr-xtox/config.py44
-rw-r--r--tox/session.py23
-rwxr-xr-xtox/venv.py2
15 files changed, 389 insertions, 508 deletions
diff --git a/tests/conftest.py b/tests/conftest.py
index 8b36b3b6..120a44bf 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1 +1,3 @@
-from tox._pytestplugin import * # noqa
+from __future__ import unicode_literals
+
+pytest_plugins = ['tox._pytestplugin']
diff --git a/tests/test_config.py b/tests/test_config.py
index 119220b0..e8e8d559 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -1,4 +1,5 @@
import os
+import re
import sys
from textwrap import dedent
@@ -2085,18 +2086,16 @@ class TestParseEnv:
class TestCmdInvocation:
def test_help(self, cmd):
- result = cmd.run("tox", "-h")
+ result = cmd("-h")
assert not result.ret
- result.stdout.fnmatch_lines([
- "*help*"
- ])
+ assert not result.err
+ assert re.match(r'usage:.*help.*', result.out, re.DOTALL)
def test_version_simple(self, cmd):
- result = cmd.run("tox", "--version")
+ result = cmd("--version")
assert not result.ret
- stdout = result.stdout.str()
- assert tox.__version__ in stdout
- assert "imported from" in stdout
+ from tox import __version__
+ assert "{} imported from".format(__version__) in result.out
def test_version_no_plugins(self):
pm = PluginManager('fakeprject')
@@ -2163,14 +2162,8 @@ class TestCmdInvocation:
changedir = docs
'''
})
- result = cmd.run("tox", "-l")
- result.stdout.fnmatch_lines("""
- py36
- py27
- py34
- pypy
- docs
- """)
+ result = cmd("-l")
+ assert result.outlines == ['py36', 'py27', 'py34', 'pypy', 'docs']
def test_listenvs_verbose_description(self, cmd, initproj):
initproj('listenvs_verbose_description', filedefs={
@@ -2193,15 +2186,14 @@ class TestCmdInvocation:
description = let me overwrite that
'''
})
- result = cmd.run("tox", "-lv")
- result.stdout.fnmatch_lines("""
- default environments:
- py36 -> run pytest on Python 3.6
- py27 -> run pytest on Python 2.7
- py34 -> run pytest on Python 3.4
- pypy -> publish to pypy
- docs -> let me overwrite that
- """)
+ result = cmd("-lv")
+ assert result.outlines[2:] == [
+ 'default environments:',
+ 'py36 -> run pytest on Python 3.6',
+ 'py27 -> run pytest on Python 2.7',
+ 'py34 -> run pytest on Python 3.4',
+ 'pypy -> publish to pypy',
+ 'docs -> let me overwrite that']
def test_listenvs_all(self, cmd, initproj):
initproj('listenvs_all', filedefs={
@@ -2216,15 +2208,8 @@ class TestCmdInvocation:
changedir = docs
'''
})
- result = cmd.run("tox", "-a")
- result.stdout.fnmatch_lines("""
- py36
- py27
- py34
- pypy
- docs
- notincluded
- """)
+ result = cmd("-a")
+ assert result.outlines == ['py36', 'py27', 'py34', 'pypy', 'docs', 'notincluded']
def test_listenvs_all_verbose_description(self, cmd, initproj):
initproj('listenvs_all_verbose_description', filedefs={
@@ -2241,19 +2226,19 @@ class TestCmdInvocation:
[testenv:docs]
changedir = docs
- '''
+ ''',
})
- result = cmd.run("tox", "-av")
- result.stdout.fnmatch_lines("""
- default environments:
- py27-windows -> run pytest on Python 2.7 on Windows platform
- py27-linux -> run pytest on Python 2.7 on Linux platform
- py36-windows -> run pytest on Python 3.6 on Windows platform
- py36-linux -> run pytest on Python 3.6 on Linux platform
-
- additional environments:
- docs -> generate documentation
- """)
+ result = cmd("-av")
+ expected = [
+ "default environments:",
+ "py27-windows -> run pytest on Python 2.7 on Windows platform",
+ "py27-linux -> run pytest on Python 2.7 on Linux platform",
+ "py36-windows -> run pytest on Python 3.6 on Windows platform",
+ "py36-linux -> run pytest on Python 3.6 on Linux platform",
+ "",
+ "additional environments:",
+ "docs -> generate documentation"]
+ assert result.outlines[-len(expected):] == expected
def test_listenvs_all_verbose_description_no_additional_environments(self, cmd, initproj):
initproj('listenvs_all_verbose_description', filedefs={
@@ -2262,29 +2247,25 @@ class TestCmdInvocation:
envlist=py27,py36
'''
})
- result = cmd.run("tox", "-av")
- result.stdout.fnmatch_lines("""
- default environments:
- py27 -> [no description]
- py36 -> [no description]
- """)
- assert 'additional environments' not in result.stdout.str()
+ result = cmd("-av")
+ expected = ["default environments:",
+ "py27 -> [no description]",
+ "py36 -> [no description]"]
+ assert result.out.splitlines()[-3:] == expected
+ assert 'additional environments' not in result.out
def test_config_specific_ini(self, tmpdir, cmd):
ini = tmpdir.ensure("hello.ini")
- result = cmd.run("tox", "-c", ini, "--showconfig")
+ result = cmd("-c", ini, "--showconfig")
assert not result.ret
- result.stdout.fnmatch_lines([
- "*config-file*hello.ini*"
- ])
+ assert result.outlines[1] == 'config-file: {}'.format(ini)
def test_no_tox_ini(self, cmd, initproj):
- initproj("noini-0.5")
- result = cmd.run("tox")
+ initproj("noini-0.5", )
+ result = cmd()
assert result.ret
- result.stderr.fnmatch_lines([
- "*ERROR*tox.ini*not*found*"
- ])
+ assert result.out == ''
+ assert result.err == "ERROR: toxini file 'tox.ini' not found\n"
def test_override_workdir(self, tmpdir, cmd, initproj):
baddir = "badworkdir-123"
@@ -2293,13 +2274,12 @@ class TestCmdInvocation:
'tox.ini': '''
[tox]
toxworkdir=%s
- ''' % baddir
+ ''' % baddir,
})
- result = cmd.run("tox", "--workdir", gooddir, "--showconfig")
+ result = cmd("--workdir", gooddir, "--showconfig")
assert not result.ret
- stdout = result.stdout.str()
- assert gooddir in stdout
- assert baddir not in stdout
+ assert gooddir in result.out
+ assert baddir not in result.out
assert py.path.local(gooddir).check()
assert not py.path.local(baddir).check()
@@ -2312,20 +2292,16 @@ class TestCmdInvocation:
deps=
dep1==2.3
dep2
- '''
+ ''',
})
- result = cmd.run("tox", "--showconfig")
+ result = cmd("--showconfig")
assert result.ret == 0
- result.stdout.fnmatch_lines([
- r'*deps*dep1==2.3, dep2*'
- ])
+ assert any(re.match(r'.*deps.*dep1==2.3, dep2.*', l) for l in result.outlines)
# override dep1 specific version, and force version for dep2
- result = cmd.run("tox", "--showconfig", "--force-dep=dep1",
- "--force-dep=dep2==5.0")
+ result = cmd("--showconfig", "--force-dep=dep1",
+ "--force-dep=dep2==5.0")
assert result.ret == 0
- result.stdout.fnmatch_lines([
- r'*deps*dep1, dep2==5.0*'
- ])
+ assert any(re.match(r'.*deps.*dep1, dep2==5.0.*', l) for l in result.outlines)
@pytest.mark.xfail(
"'pypy' not in sys.executable",
@@ -2340,7 +2316,7 @@ class TestCmdInvocation:
commands = pip --version
'''
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret == 0
diff --git a/tests/test_interpreters.py b/tests/test_interpreters.py
index fcc5a7a1..8d3cdcaf 100644
--- a/tests/test_interpreters.py
+++ b/tests/test_interpreters.py
@@ -47,6 +47,7 @@ def test_locate_via_py(monkeypatch):
@staticmethod
def communicate():
return sys.executable.encode(), None
+
return proc
# Monkeypatch modules to return our faked value
@@ -59,6 +60,7 @@ def test_tox_get_python_executable():
class envconfig:
basepython = sys.executable
envname = "pyxx"
+
p = tox_get_python_executable(envconfig)
assert p == py.path.local(sys.executable)
for ver in "2.7 3.4 3.5 3.6".split():
@@ -86,6 +88,7 @@ def test_find_executable_extra(monkeypatch):
@staticmethod
def sysfind(x):
return "hello"
+
monkeypatch.setattr(py.path.local, "sysfind", sysfind)
class envconfig:
@@ -122,6 +125,7 @@ class TestInterpreters:
class envconfig:
basepython = "1lkj23"
envname = "pyxx"
+
assert not interpreters.get_executable(envconfig)
info = interpreters.get_info(envconfig)
assert not info.version_info
@@ -133,6 +137,7 @@ class TestInterpreters:
class envconfig:
basepython = sys.executable
envname = "123"
+
info = interpreters.get_info(envconfig)
s = interpreters.get_sitepackagesdir(info, "")
assert s
diff --git a/tests/test_pytest_plugins.py b/tests/test_pytest_plugins.py
index d5e943a5..3eb1a12f 100644
--- a/tests/test_pytest_plugins.py
+++ b/tests/test_pytest_plugins.py
@@ -12,10 +12,10 @@ from tox._pytestplugin import _path_parts
class TestInitProj:
@pytest.mark.parametrize('kwargs', (
- {},
- {'src_root': None},
- {'src_root': ''},
- {'src_root': '.'}))
+ {},
+ {'src_root': None},
+ {'src_root': ''},
+ {'src_root': '.'}))
def test_no_src_root(self, kwargs, tmpdir, initproj):
initproj('black_knight-42', **kwargs)
init_file = tmpdir.join('black_knight', 'black_knight', '__init__.py')
@@ -64,14 +64,14 @@ class TestInitProj:
class TestPathParts:
@pytest.mark.parametrize('input, expected', (
- ('', []),
- ('/', ['/']),
- ('//', ['//']),
- ('/a', ['/', 'a']),
- ('/a/', ['/', 'a']),
- ('/a/b', ['/', 'a', 'b']),
- ('a', ['a']),
- ('a/b', ['a', 'b'])))
+ ('', []),
+ ('/', ['/']),
+ ('//', ['//']),
+ ('/a', ['/', 'a']),
+ ('/a/', ['/', 'a']),
+ ('/a/b', ['/', 'a', 'b']),
+ ('a', ['a']),
+ ('a/b', ['a', 'b'])))
def test_path_parts(self, input, expected):
assert _path_parts(input) == expected
@@ -82,18 +82,18 @@ class TestPathParts:
@pytest.mark.parametrize('base, filedefs, target, expected', (
- ('/base', {}, '', False),
- ('/base', {}, '/base', False),
- ('/base', {'a': {'b': 'data'}}, '', True),
- ('/base', {'a': {'b': 'data'}}, 'a', True),
- ('/base', {'a': {'b': 'data'}}, 'a/b', True),
- ('/base', {'a': {'b': 'data'}}, 'a/x', False),
- ('/base', {'a': {'b': 'data'}}, 'a/b/c', False),
- ('/base', {'a': {'b': 'data'}}, '/base', True),
- ('/base', {'a': {'b': 'data'}}, '/base/a', True),
- ('/base', {'a': {'b': 'data'}}, '/base/a/b', True),
- ('/base', {'a': {'b': 'data'}}, '/base/a/x', False),
- ('/base', {'a': {'b': 'data'}}, '/base/a/b/c', False),
- ('/base', {'a': {'b': 'data'}}, '/a', False)))
+ ('/base', {}, '', False),
+ ('/base', {}, '/base', False),
+ ('/base', {'a': {'b': 'data'}}, '', True),
+ ('/base', {'a': {'b': 'data'}}, 'a', True),
+ ('/base', {'a': {'b': 'data'}}, 'a/b', True),
+ ('/base', {'a': {'b': 'data'}}, 'a/x', False),
+ ('/base', {'a': {'b': 'data'}}, 'a/b/c', False),
+ ('/base', {'a': {'b': 'data'}}, '/base', True),
+ ('/base', {'a': {'b': 'data'}}, '/base/a', True),
+ ('/base', {'a': {'b': 'data'}}, '/base/a/b', True),
+ ('/base', {'a': {'b': 'data'}}, '/base/a/x', False),
+ ('/base', {'a': {'b': 'data'}}, '/base/a/b/c', False),
+ ('/base', {'a': {'b': 'data'}}, '/a', False)))
def test_filedefs_contains(base, filedefs, target, expected):
assert bool(_filedefs_contains(base, filedefs, target)) == expected
diff --git a/tests/test_venv.py b/tests/test_venv.py
index af6a84b9..c2ca3e46 100644
--- a/tests/test_venv.py
+++ b/tests/test_venv.py
@@ -14,6 +14,7 @@ from tox.venv import tox_testenv_create
from tox.venv import tox_testenv_install_deps
from tox.venv import VirtualEnv
+
# def test_global_virtualenv(capfd):
# v = VirtualEnv()
# assert v.list()
@@ -544,7 +545,7 @@ class TestVenvTest:
monkeypatch.setenv("PATH", "xyz")
sysfind_calls = []
monkeypatch.setattr("py.path.local.sysfind", classmethod(
- lambda *args, **kwargs: sysfind_calls.append(kwargs) or 0 / 0))
+ lambda *args, **kwargs: sysfind_calls.append(kwargs) or 0 / 0))
with pytest.raises(ZeroDivisionError):
venv._install(list('123'), action=action)
@@ -633,7 +634,7 @@ def test_env_variables_added_to_pcall(tmpdir, mocksession, newconfig, monkeypatc
assert pcalls[0].env["YY"] == "456"
assert "YY" not in pcalls[1].env
- assert {"ENV_VAR", "VIRTUAL_ENV", "PYTHONHASHSEED", "X123", "PATH"}\
+ assert {"ENV_VAR", "VIRTUAL_ENV", "PYTHONHASHSEED", "X123", "PATH"} \
.issubset(pcalls[1].env)
# setenv does not trigger PYTHONPATH warnings
diff --git a/tests/test_z_cmdline.py b/tests/test_z_cmdline.py
index 5acb57a4..bdcc68d0 100644
--- a/tests/test_z_cmdline.py
+++ b/tests/test_z_cmdline.py
@@ -1,11 +1,13 @@
import os
import platform
+import re
import py
import pytest
import tox
from tox._pytestplugin import ReportExpectMock
+
try:
import json
except ImportError:
@@ -179,11 +181,9 @@ def XXX_test_package(cmd, initproj):
""",
'tox.ini': ''
})
- result = cmd.run("tox", "package")
+ result = cmd("package")
assert not result.ret
- result.stdout.fnmatch_lines([
- "*created sdist package at*",
- ])
+ assert any(re.match(r'.*created sdist package at.*', l) for l in result.outlines)
def test_minversion(cmd, initproj):
@@ -194,10 +194,9 @@ def test_minversion(cmd, initproj):
minversion = 6.0
'''
})
- result = cmd.run("tox", "-v")
- result.stdout.fnmatch_lines([
- "*ERROR*tox version is * required is at least 6.0*"
- ])
+ result = cmd("-v")
+ assert re.match(r'ERROR: MinVersionError: tox version is .*,'
+ r' required is at least 6.0', result.out)
assert result.ret
@@ -205,13 +204,10 @@ def test_notoxini_help_still_works(initproj, cmd):
initproj("example123-0.5", filedefs={
'tests': {'test_hello.py': "def test_hello(): pass"},
})
- result = cmd.run("tox", "-h")
- result.stderr.fnmatch_lines([
- "*ERROR*tox.ini*"
- ])
- result.stdout.fnmatch_lines([
- "*--help*"
- ])
+ result = cmd("-h")
+ assert result.err == "ERROR: toxini file 'tox.ini' not found\n"
+ assert result.out.startswith('usage: ')
+ assert any('--help' in l for l in result.outlines)
assert not result.ret
@@ -219,13 +215,8 @@ def test_notoxini_help_ini_still_works(initproj, cmd):
initproj("example123-0.5", filedefs={
'tests': {'test_hello.py': "def test_hello(): pass"},
})
- result = cmd.run("tox", "--help-ini")
- result.stderr.fnmatch_lines([
- "*ERROR*tox.ini*"
- ])
- result.stdout.fnmatch_lines([
- "*setenv*"
- ])
+ result = cmd("--help-ini")
+ assert any('setenv' in l for l in result.outlines)
assert not result.ret
@@ -236,11 +227,9 @@ def test_envdir_equals_toxini_errors_out(cmd, initproj):
envdir={toxinidir}
'''
})
- result = cmd.run("tox")
- result.stdout.fnmatch_lines([
- "ERROR*venv*delete*",
- "*ConfigError*envdir must not equal toxinidir*",
- ])
+ result = cmd()
+ assert result.outlines[1] == "ERROR: ConfigError: envdir must not equal toxinidir"
+ assert re.match(r'ERROR: venv \'python\' in .* would delete project', result.outlines[0])
assert result.ret
@@ -251,10 +240,9 @@ def test_run_custom_install_command_error(cmd, initproj):
install_command=./tox.ini {opts} {packages}
'''
})
- result = cmd.run("tox")
- result.stdout.fnmatch_lines([
- "ERROR: invocation failed (errno *), args: ['*/tox.ini*",
- ])
+ result = cmd()
+ assert re.match(r"ERROR: invocation failed \(errno \d+\), args: \['.*[/\\]tox\.ini",
+ result.outlines[-1])
assert result.ret
@@ -268,17 +256,13 @@ def test_unknown_interpreter_and_env(cmd, initproj):
changedir=tests
'''
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*InterpreterNotFound*xyz_unknown_interpreter*",
- ])
+ assert any('ERROR: InterpreterNotFound: xyz_unknown_interpreter' == l for l in result.outlines)
- result = cmd.run("tox", "-exyz")
+ result = cmd("-exyz")
assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*unknown*",
- ])
+ assert result.out == "ERROR: unknown environment 'xyz'\n"
def test_unknown_interpreter(cmd, initproj):
@@ -291,11 +275,9 @@ def test_unknown_interpreter(cmd, initproj):
changedir=tests
'''
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*InterpreterNotFound*xyz_unknown_interpreter*",
- ])
+ assert any('ERROR: InterpreterNotFound: xyz_unknown_interpreter' == l for l in result.outlines)
def test_skip_platform_mismatch(cmd, initproj):
@@ -307,11 +289,9 @@ def test_skip_platform_mismatch(cmd, initproj):
platform=x123
'''
})
- result = cmd.run("tox")
+ result = cmd()
assert not result.ret
- result.stdout.fnmatch_lines("""
- SKIPPED*platform mismatch*
- """)
+ assert any('SKIPPED: python: platform mismatch' == l for l in result.outlines)
def test_skip_unknown_interpreter(cmd, initproj):
@@ -324,11 +304,10 @@ def test_skip_unknown_interpreter(cmd, initproj):
changedir=tests
'''
})
- result = cmd.run("tox", "--skip-missing-interpreters")
+ result = cmd("--skip-missing-interpreters")
assert not result.ret
- result.stdout.fnmatch_lines([
- "*SKIPPED*InterpreterNotFound*xyz_unknown_interpreter*",
- ])
+ msg = 'SKIPPED: python: InterpreterNotFound: xyz_unknown_interpreter'
+ assert any(msg == l for l in result.outlines)
def test_unknown_dep(cmd, initproj):
@@ -340,11 +319,9 @@ def test_unknown_dep(cmd, initproj):
changedir=tests
'''
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*could not install*qweqwe123*",
- ])
+ assert result.outlines[-1].startswith('ERROR: python: could not install deps [qweqwe123];')
def test_venv_special_chars_issue252(cmd, initproj):
@@ -357,22 +334,19 @@ def test_venv_special_chars_issue252(cmd, initproj):
changedir=tests
'''
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*installed*pkg123*"
- ])
+ pattern = re.compile('special&&1 installed: .*pkg123==0.7.*')
+ assert any(pattern.match(line) for line in result.outlines)
def test_unknown_environment(cmd, initproj):
initproj("env123-0.7", filedefs={
'tox.ini': ''
})
- result = cmd.run("tox", "-e", "qpwoei")
+ result = cmd("-e", "qpwoei")
assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*unknown*environment*qpwoei*",
- ])
+ assert result.out == "ERROR: unknown environment 'qpwoei'\n"
def test_skip_sdist(cmd, initproj):
@@ -388,7 +362,7 @@ def test_skip_sdist(cmd, initproj):
commands=python -c "print('done')"
'''
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret == 0
@@ -398,13 +372,10 @@ def test_minimal_setup_py_empty(cmd, initproj):
'setup.py': """
""",
'tox.ini': ''
-
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*ERROR*empty*",
- ])
+ assert result.outlines[-1] == 'ERROR: setup.py is empty'
def test_minimal_setup_py_comment_only(cmd, initproj):
@@ -416,11 +387,9 @@ def test_minimal_setup_py_comment_only(cmd, initproj):
'tox.ini': ''
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*ERROR*empty*",
- ])
+ assert result.outlines[-1] == 'ERROR: setup.py is empty'
def test_minimal_setup_py_non_functional(cmd, initproj):
@@ -433,11 +402,9 @@ def test_minimal_setup_py_non_functional(cmd, initproj):
'tox.ini': ''
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*ERROR*check setup.py*",
- ])
+ assert any(re.match(r'.*ERROR.*check setup.py.*', l) for l in result.outlines)
def test_sdist_fails(cmd, initproj):
@@ -448,11 +415,9 @@ def test_sdist_fails(cmd, initproj):
""",
'tox.ini': '',
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret
- result.stdout.fnmatch_lines([
- "*FAIL*could not package project*",
- ])
+ assert any(re.match(r'.*FAIL.*could not package project.*', l) for l in result.outlines)
def test_no_setup_py_exits(cmd, initproj):
@@ -463,11 +428,9 @@ def test_no_setup_py_exits(cmd, initproj):
"""
})
os.remove("setup.py")
- result = cmd.run("tox")
+ result = cmd()
assert result.ret
- result.stdout.fnmatch_lines([
- "*ERROR*No setup.py file found*"
- ])
+ assert any(re.match(r'.*ERROR.*No setup.py file found.*', l) for l in result.outlines)
def test_package_install_fails(cmd, initproj):
@@ -487,81 +450,73 @@ def test_package_install_fails(cmd, initproj):
""",
'tox.ini': '',
})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret
- result.stdout.fnmatch_lines([
- "*InvocationError*",
- ])
+ assert result.outlines[-1].startswith('ERROR: python: InvocationError: ')
-class TestToxRun:
- @pytest.fixture
- def example123(self, initproj):
- initproj("example123-0.5", filedefs={
- 'tests': {
- 'test_hello.py': """
- def test_hello(pytestconfig):
- pass
- """,
- },
- 'tox.ini': '''
- [testenv]
- changedir=tests
- commands= pytest --basetemp={envtmpdir} \
- --junitxml=junit-{envname}.xml
- deps=pytest
- '''
- })
+@pytest.fixture
+def example123(initproj):
+ yield initproj("example123-0.5", filedefs={
+ 'tests': {
+ 'test_hello.py': """
+ def test_hello(pytestconfig):
+ pass
+ """,
+ },
+ 'tox.ini': '''
+ [testenv]
+ changedir=tests
+ commands= pytest --basetemp={envtmpdir} \
+ --junitxml=junit-{envname}.xml
+ deps=pytest
+ '''
+ })
+
+
+def test_toxuone_env(cmd, example123):
+ result = cmd()
+ assert not result.ret
+ assert re.match(r'.*generated\W+xml\W+file.*junit-python\.xml'
+ r'.*\W+1\W+passed.*', result.out, re.DOTALL)
+ result = cmd("-epython", )
+ assert not result.ret
+ assert re.match(r'.*\W+1\W+passed.*'
+ r'summary.*'
+ r'python:\W+commands\W+succeeded.*', result.out, re.DOTALL)
+
+
+def test_different_config_cwd(cmd, example123, monkeypatch):
+ # see that things work with a different CWD
+ monkeypatch.chdir(example123.dirname)
+ result = cmd("-c", "example123/tox.ini")
+ assert not result.ret
+ assert re.match(r'.*\W+1\W+passed.*'
+ r'summary.*'
+ r'python:\W+commands\W+succeeded.*', result.out, re.DOTALL)
+
+
+def test_json(cmd, example123):
+ # see that tests can also fail and retcode is correct
+ testfile = py.path.local("tests").join("test_hello.py")
+ assert testfile.check()
+ testfile.write("def test_fail(): assert 0")
+ jsonpath = example123.join("res.json")
+ result = cmd("--result-json", jsonpath)
+ assert result.ret == 1
+ data = json.load(jsonpath.open("r"))
+ verify_json_report_format(data)
+ assert re.match(r'.*\W+1\W+failed.*'
+ r'summary.*'
+ r'python:\W+commands\W+failed.*', result.out, re.DOTALL)
+
- def test_toxuone_env(self, cmd, example123):
- result = cmd.run("tox")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*junit-python.xml*",
- "*1 passed*",
- ])
- result = cmd.run("tox", "-epython")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*1 passed*",
- "*summary*",
- "*python: commands succeeded"
- ])
-
- def test_different_config_cwd(self, cmd, example123, monkeypatch):
- # see that things work with a different CWD
- monkeypatch.chdir(cmd.tmpdir)
- result = cmd.run("tox", "-c", "example123/tox.ini")
- assert not result.ret
- result.stdout.fnmatch_lines([
- "*1 passed*",
- "*summary*",
- "*python: commands succeeded"
- ])
-
- def test_json(self, cmd, example123):
- # see that tests can also fail and retcode is correct
- testfile = py.path.local("tests").join("test_hello.py")
- assert testfile.check()
- testfile.write("def test_fail(): assert 0")
- jsonpath = cmd.tmpdir.join("res.json")
- result = cmd.run("tox", "--result-json", jsonpath)
- assert result.ret == 1
- data = json.load(jsonpath.open("r"))
- verify_json_report_format(data)
- result.stdout.fnmatch_lines([
- "*1 failed*",
- "*summary*",
- "*python: *failed*",
- ])
-
-
-def test_develop(initproj, cmd):
+def test_developz(initproj, cmd):
initproj("example123", filedefs={'tox.ini': """
"""})
- result = cmd.run("tox", "-vv", "--develop")
+ result = cmd("-vv", "--develop")
assert not result.ret
- assert "sdist-make" not in result.stdout.str()
+ assert "sdist-make" not in result.out
def test_usedevelop(initproj, cmd):
@@ -569,9 +524,9 @@ def test_usedevelop(initproj, cmd):
[testenv]
usedevelop=True
"""})
- result = cmd.run("tox", "-vv")
+ result = cmd("-vv")
assert not result.ret
- assert "sdist-make" not in result.stdout.str()
+ assert "sdist-make" not in result.out
def test_usedevelop_mixed(initproj, cmd):
@@ -583,19 +538,19 @@ def test_usedevelop_mixed(initproj, cmd):
"""})
# running only 'devenv' should not do sdist
- result = cmd.run("tox", "-vv", "-e", "devenv")
+ result = cmd("-vv", "-e", "devenv")
assert not result.ret
- assert "sdist-make" not in result.stdout.str()
+ assert "sdist-make" not in result.out
# running all envs should do sdist
- result = cmd.run("tox", "-vv")
+ result = cmd("-vv")
assert not result.ret
- assert "sdist-make" in result.stdout.str()
+ assert "sdist-make" in result.out
@pytest.mark.parametrize("src_root", [".", "src"])
-def test_test_usedevelop(cmd, initproj, src_root):
- initproj("example123-0.5", src_root=src_root, filedefs={
+def test_test_usedevelop(cmd, initproj, src_root, monkeypatch):
+ base = initproj("example123-0.5", src_root=src_root, filedefs={
'tests': {
'test_hello.py': """
def test_hello(pytestconfig):
@@ -611,50 +566,45 @@ def test_test_usedevelop(cmd, initproj, src_root):
deps=pytest
'''
})
- result = cmd.run("tox", "-v")
+ result = cmd("-v")
assert not result.ret
- result.stdout.fnmatch_lines([
- "*junit-python.xml*",
- "*1 passed*",
- ])
- assert "sdist-make" not in result.stdout.str()
- result = cmd.run("tox", "-epython")
+ assert re.match(r'.*generated\W+xml\W+file.*junit-python\.xml'
+ r'.*\W+1\W+passed.*', result.out, re.DOTALL)
+ assert "sdist-make" not in result.out
+ result = cmd("-epython", )
assert not result.ret
- assert "develop-inst-noop" in result.stdout.str()
- result.stdout.fnmatch_lines([
- "*1 passed*",
- "*summary*",
- "*python: commands succeeded"
- ])
+ assert "develop-inst-noop" in result.out
+ assert re.match(r'.*\W+1\W+passed.*'
+ r'summary.*'
+ r'python:\W+commands\W+succeeded.*', result.out, re.DOTALL)
+
# see that things work with a different CWD
- old = cmd.tmpdir.chdir()
- result = cmd.run("tox", "-c", "example123/tox.ini")
+ monkeypatch.chdir(base.dirname)
+ result = cmd("-c", "example123/tox.ini")
assert not result.ret
- assert "develop-inst-noop" in result.stdout.str()
- result.stdout.fnmatch_lines([
- "*1 passed*",
- "*summary*",
- "*python: commands succeeded"
- ])
- old.chdir()
+ assert "develop-inst-noop" in result.out
+ assert re.match(r'.*\W+1\W+passed.*'
+ r'summary.*'
+ r'python:\W+commands\W+succeeded.*', result.out, re.DOTALL)
+ monkeypatch.chdir(base)
+
# see that tests can also fail and retcode is correct
testfile = py.path.local("tests").join("test_hello.py")
assert testfile.check()
testfile.write("def test_fail(): assert 0")
- result = cmd.run("tox")
+ result = cmd()
assert result.ret
- assert "develop-inst-noop" in result.stdout.str()
- result.stdout.fnmatch_lines([
- "*1 failed*",
- "*summary*",
- "*python: *failed*",
- ])
+ assert "develop-inst-noop" in result.out
+ assert re.match(r'.*\W+1\W+failed.*'
+ r'summary.*'
+ r'python:\W+commands\W+failed.*', result.out, re.DOTALL)
+
# test develop is called if setup.py changes
setup_py = py.path.local("setup.py")
setup_py.write(setup_py.read() + ' ')
- result = cmd.run("tox")
+ result = cmd()
assert result.ret
- assert "develop-inst-nodeps" in result.stdout.str()
+ assert "develop-inst-nodeps" in result.out
def _alwayscopy_not_supported():
@@ -667,16 +617,16 @@ def _alwayscopy_not_supported():
return False
-@pytest.mark.skipif(_alwayscopy_not_supported(), reason="Platform doesn't support alwayscopy")
+@pytest.mark.skipif(_alwayscopy_not_supported(), reason="Platform doesnt support alwayscopy")
def test_alwayscopy(initproj, cmd):
initproj("example123", filedefs={'tox.ini': """
[testenv]
commands={envpython} --version
alwayscopy=True
"""})
- result = cmd.run("tox", "-vv")
+ result = cmd("-vv")
assert not result.ret
- assert "virtualenv --always-copy" in result.stdout.str()
+ assert "virtualenv --always-copy" in result.out
def test_alwayscopy_default(initproj, cmd):
@@ -684,9 +634,9 @@ def test_alwayscopy_default(initproj, cmd):
[testenv]
commands={envpython} --version
"""})
- result = cmd.run("tox", "-vv")
+ result = cmd("-vv")
assert not result.ret
- assert "virtualenv --always-copy" not in result.stdout.str()
+ assert "virtualenv --always-copy" not in result.out
def test_empty_activity_ignored(initproj, cmd):
@@ -695,9 +645,9 @@ def test_empty_activity_ignored(initproj, cmd):
list_dependencies_command=echo
commands={envpython} --version
"""})
- result = cmd.run("tox")
+ result = cmd()
assert not result.ret
- assert "installed:" not in result.stdout.str()
+ assert "installed:" not in result.out
def test_empty_activity_shown_verbose(initproj, cmd):
@@ -706,9 +656,9 @@ def test_empty_activity_shown_verbose(initproj, cmd):
list_dependencies_command=echo
commands={envpython} --version
"""})
- result = cmd.run("tox", "-v")
+ result = cmd("-v")
assert not result.ret
- assert "installed:" in result.stdout.str()
+ assert "installed:" in result.out
def test_test_piphelp(initproj, cmd):
@@ -716,74 +666,64 @@ def test_test_piphelp(initproj, cmd):
# content of: tox.ini
[testenv]
commands=pip -h
- [testenv:py36]
+ [testenv:py26]
basepython=python
[testenv:py27]
basepython=python
"""})
- result = cmd.run("tox")
+ result = cmd()
assert not result.ret
def test_notest(initproj, cmd):
initproj("example123", filedefs={'tox.ini': """
# content of: tox.ini
- [testenv:py36]
+ [testenv:py26]
basepython=python
"""})
- result = cmd.run("tox", "-v", "--notest")
+ result = cmd("-v", "--notest")
assert not result.ret
- result.stdout.fnmatch_lines([
- "*summary*",
- "*py36*skipped tests*",
- ])
- result = cmd.run("tox", "-v", "--notest", "-epy36")
+ assert re.match(r'.*summary.*'
+ r'py26\W+skipped\W+tests.*', result.out, re.DOTALL)
+ result = cmd("-v", "--notest", "-epy26")
assert not result.ret
- result.stdout.fnmatch_lines([
- "*py36*reusing*",
- ])
+ assert re.match(r'.*py26\W+reusing.*', result.out, re.DOTALL)
def test_PYC(initproj, cmd, monkeypatch):
initproj("example123", filedefs={'tox.ini': ''})
monkeypatch.setenv("PYTHONDOWNWRITEBYTECODE", 1)
- result = cmd.run("tox", "-v", "--notest")
+ result = cmd("-v", "--notest")
assert not result.ret
- result.stdout.fnmatch_lines([
- "*create*",
- ])
+ assert 'create' in result.out
def test_env_VIRTUALENV_PYTHON(initproj, cmd, monkeypatch):
initproj("example123", filedefs={'tox.ini': ''})
monkeypatch.setenv("VIRTUALENV_PYTHON", '/FOO')
- result = cmd.run("tox", "-v", "--notest")
- assert not result.ret, result.stdout.lines
- result.stdout.fnmatch_lines([
- "*create*",
- ])
+ result = cmd("-v", "--notest")
+ assert not result.ret, result.outlines
+ assert 'create' in result.out
def test_sdistonly(initproj, cmd):
initproj("example123", filedefs={'tox.ini': """
"""})
- result = cmd.run("tox", "-v", "--sdistonly")
+ result = cmd("-v", "--sdistonly")
assert not result.ret
- result.stdout.fnmatch_lines([
- "*sdist-make*setup.py*",
- ])
- assert "-mvirtualenv" not in result.stdout.str()
+ assert re.match(r'.*sdist-make.*setup.py.*', result.out, re.DOTALL)
+ assert "-mvirtualenv" not in result.out
-def test_separate_sdist_no_sdistfile(cmd, initproj):
- distshare = cmd.tmpdir.join("distshare")
+def test_separate_sdist_no_sdistfile(cmd, initproj, tmpdir):
+ distshare = tmpdir.join("distshare")
initproj(("pkg123-foo", "0.7"), filedefs={
'tox.ini': """
[tox]
- distshare=%s
- """ % distshare
+ distshare={}
+ """.format(distshare)
})
- result = cmd.run("tox", "--sdistonly")
+ result = cmd("--sdistonly")
assert not result.ret
distshare_files = distshare.listdir()
assert len(distshare_files) == 1
@@ -791,8 +731,8 @@ def test_separate_sdist_no_sdistfile(cmd, initproj):
assert 'pkg123-foo-0.7.zip' in str(sdistfile)
-def test_separate_sdist(cmd, initproj):
- distshare = cmd.tmpdir.join("distshare")
+def test_separate_sdist(cmd, initproj, tmpdir):
+ distshare = tmpdir.join("distshare")
initproj("pkg123-0.7", filedefs={
'tox.ini': """
[tox]
@@ -800,16 +740,14 @@ def test_separate_sdist(cmd, initproj):
sdistsrc={distshare}/pkg123-0.7.zip
""" % distshare
})
- result = cmd.run("tox", "--sdistonly")
+ result = cmd("--sdistonly")
assert not result.ret
sdistfiles = distshare.listdir()
assert len(sdistfiles) == 1
sdistfile = sdistfiles[0]
- result = cmd.run("tox", "-v", "--notest")
+ result = cmd("-v", "--notest")
assert not result.ret
- result.stdout.fnmatch_lines([
- "*inst*%s*" % sdistfile,
- ])
+ assert "python inst: {}".format(sdistfile) in result.out
def test_sdist_latest(tmpdir, newconfig):
@@ -841,11 +779,9 @@ def test_envsitepackagesdir(cmd, initproj):
commands=
python -c "print(r'X:{envsitepackagesdir}')"
"""})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret == 0
- result.stdout.fnmatch_lines("""
- X:*tox*site-packages*
- """)
+ assert re.match(r'.*\nX:.*tox.*site-packages.*', result.out, re.DOTALL)
def test_envsitepackagesdir_skip_missing_issue280(cmd, initproj):
@@ -856,11 +792,9 @@ def test_envsitepackagesdir_skip_missing_issue280(cmd, initproj):
commands=
{envsitepackagesdir}
"""})
- result = cmd.run("tox", "--skip-missing-interpreters")
+ result = cmd("--skip-missing-interpreters")
assert result.ret == 0
- result.stdout.fnmatch_lines("""
- SKIPPED:*qwelkj*
- """)
+ assert re.match(r'.*SKIPPED:.*qwelkj.*', result.out, re.DOTALL)
@pytest.mark.parametrize('verbosity', ['', '-v', '-vv'])
@@ -869,7 +803,7 @@ def test_verbosity(cmd, initproj, verbosity):
'tox.ini': """
[testenv]
"""})
- result = cmd.run("tox", verbosity)
+ result = cmd(verbosity)
assert result.ret == 0
needle = "Successfully installed pkgX-0.0.5"
@@ -918,15 +852,16 @@ def test_envtmpdir(initproj, cmd):
'''
})
- result = cmd.run("tox")
+ result = cmd()
assert not result.ret
- result = cmd.run("tox")
+ result = cmd()
assert not result.ret
def test_missing_env_fails(initproj, cmd):
initproj("foo", filedefs={'tox.ini': "[testenv:foo]\ncommands={env:VAR}"})
- result = cmd.run("tox")
+ result = cmd()
assert result.ret == 1
- result.stdout.fnmatch_lines(["*foo: unresolvable substitution(s): 'VAR'*"])
+ assert result.out.endswith("foo: unresolvable substitution(s): 'VAR'."
+ " Environment variables are missing or defined recursively.\n")
diff --git a/tox.ini b/tox.ini
index a8f06276..b06ed81a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -68,9 +68,10 @@ commands = echo {posargs}
[testenv:dev]
description = generate a DEV environment
-extras = testing, docs, lint
+extras = testing, docs
# required to make looponfail reload on every source code change
usedevelop = True
+basepython = python3.6
commands = python -m pip list --format=columns
python -c 'import sys; print(sys.executable)'
diff --git a/tox/__init__.py b/tox/__init__.py
index 4f2c0bdb..83b0e80d 100644
--- a/tox/__init__.py
+++ b/tox/__init__.py
@@ -19,23 +19,31 @@ class exception:
class MissingSubstitution(Error):
FLAG = 'TOX_MISSING_SUBSTITUTION'
"""placeholder for debugging configurations"""
+
def __init__(self, name):
self.name = name
class ConfigError(Error):
""" error in tox configuration. """
+
class UnsupportedInterpreter(Error):
"""signals an unsupported Interpreter"""
+
class InterpreterNotFound(Error):
"""signals that an interpreter could not be found"""
+
class InvocationError(Error):
""" an error while invoking a script. """
+
class MissingFile(Error):
""" an error while invoking a script. """
+
class MissingDirectory(Error):
""" a directory did not exist. """
+
class MissingDependency(Error):
""" a dependency could not be found or determined. """
+
class MinVersionError(Error):
""" the installed tox version is lower than requested minversion. """
diff --git a/tox/__main__.py b/tox/__main__.py
index 04719886..d1509550 100644
--- a/tox/__main__.py
+++ b/tox/__main__.py
@@ -1,4 +1,6 @@
+import sys
+
from tox.session import main
if __name__ == '__main__':
- main()
+ main(sys.argv[1:])
diff --git a/tox/_pytestplugin.py b/tox/_pytestplugin.py
index e63acc75..77ee7711 100644
--- a/tox/_pytestplugin.py
+++ b/tox/_pytestplugin.py
@@ -1,8 +1,7 @@
from __future__ import print_function
+from __future__ import unicode_literals
import os
-import os.path
-import subprocess
import sys
import textwrap
import time
@@ -15,7 +14,7 @@ import six
import tox
from .config import parseconfig
from .result import ResultLog
-from .session import Action
+from .session import main
from .venv import VirtualEnv
@@ -33,7 +32,7 @@ def pytest_addoption(parser):
def pytest_report_header():
- return "tox comes from: %r" % (tox.__file__)
+ return "tox comes from: {}".format(repr(tox.__file__))
@pytest.fixture
@@ -50,14 +49,62 @@ def newconfig(request, tmpdir):
return parseconfig(args, plugins=plugins)
finally:
old.chdir()
+
return newconfig
@pytest.fixture
-def cmd(request):
+def cmd(request, capfd, monkeypatch):
if request.config.option.no_network:
pytest.skip("--no-network was specified, test cannot run")
- return Cmd(request)
+ request.addfinalizer(py.path.local().chdir)
+
+ def run(*argv):
+ if sys.version_info[:2] < (2, 7):
+ pytest.skip("can not run tests involving calling tox on python2.6. "
+ "(and python2.6 is about to be deprecated anyway)")
+ key = str(b'PYTHONPATH')
+ python_paths = (i for i in (str(os.getcwd()), os.getenv(key)) if i)
+ monkeypatch.setenv(key, os.pathsep.join(python_paths))
+ with RunResult(capfd, argv) as result:
+ try:
+ main([str(x) for x in argv])
+ assert False # this should always exist with SystemExit
+ except SystemExit as exception:
+ result.ret = exception.code
+ except OSError as e:
+ result.ret = e.errno
+ return result
+
+ yield run
+
+
+class RunResult:
+ def __init__(self, capfd, args):
+ self._capfd = capfd
+ self.args = args
+ self.ret = None
+ self.duration = None
+ self.out = None
+ self.err = None
+
+ def __enter__(self):
+ self._start = time.time()
+ # noinspection PyProtectedMember
+ self._capfd._start()
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.duration = time.time() - self._start
+ self.out, self.err = self._capfd.readouterr()
+
+ @property
+ def outlines(self):
+ return self.out.splitlines()
+
+ def __repr__(self):
+ return 'RunResult(ret={}, args={}, out=\n{}\n, err=\n{})'.format(
+ self.ret, ' '.join(str(i) for i in self.args), self.out, self.err)
class ReportExpectMock:
@@ -78,13 +125,9 @@ class ReportExpectMock:
def generic_report(*args, **kwargs):
self._calls.append((name,) + args)
- print("%s" % (self._calls[-1], ))
- return generic_report
+ print("%s" % (self._calls[-1],))
- def action(self, venv, msg, *args):
- self._calls.append(("action", venv, msg))
- print("%s" % (self._calls[-1], ))
- return Action(self.session, venv, msg, args)
+ return generic_report
def getnext(self, cat):
__tracebackhide__ = True
@@ -170,6 +213,7 @@ def mocksession(request):
pm = pcallMock(args, cwd, env, stdout, stderr, shell)
self._pcalls.append(pm)
return pm
+
return MockSession()
@@ -181,55 +225,8 @@ def newmocksession(request):
def newmocksession(args, source, plugins=()):
mocksession.config = newconfig(args, source, plugins=plugins)
return mocksession
- return newmocksession
-
-class Cmd:
- def __init__(self, request):
- self.tmpdir = request.getfixturevalue("tmpdir")
- self.request = request
- current = py.path.local()
- self.request.addfinalizer(current.chdir)
-
- def chdir(self, target):
- target.chdir()
-
- def popen(self, argv, stdout, stderr, **kw):
- env = os.environ.copy()
- env['PYTHONPATH'] = ":".join(filter(None, [
- str(os.getcwd()), env.get('PYTHONPATH', '')]))
- kw['env'] = env
- # print "env", env
- return subprocess.Popen(argv, stdout=stdout, stderr=stderr, **kw)
-
- def run(self, *argv):
- argv = [str(x) for x in argv]
- assert py.path.local.sysfind(str(argv[0])), argv[0]
- p1 = self.tmpdir.join("stdout")
- p2 = self.tmpdir.join("stderr")
- print("%s$ %s" % (os.getcwd(), " ".join(argv)))
- f1 = p1.open("wb")
- f2 = p2.open("wb")
- now = time.time()
- popen = self.popen(argv, stdout=f1, stderr=f2,
- close_fds=(sys.platform != "win32"))
- ret = popen.wait()
- f1.close()
- f2.close()
- out = p1.read("rb")
- out = getdecoded(out).splitlines()
- err = p2.read("rb")
- err = getdecoded(err).splitlines()
-
- def dump_lines(lines, fp):
- try:
- for line in lines:
- print(line, file=fp)
- except UnicodeEncodeError:
- print("couldn't print to %s because of encoding" % (fp,))
- dump_lines(out, sys.stdout)
- dump_lines(err, sys.stderr)
- return RunResult(ret, out, err, time.time() - now)
+ return newmocksession
def getdecoded(out):
@@ -240,55 +237,6 @@ def getdecoded(out):
py.io.saferepr(out),)
-class RunResult:
- def __init__(self, ret, outlines, errlines, duration):
- self.ret = ret
- self.outlines = outlines
- self.errlines = errlines
- self.stdout = LineMatcher(outlines)
- self.stderr = LineMatcher(errlines)
- self.duration = duration
-
-
-class LineMatcher:
- def __init__(self, lines):
- self.lines = lines
-
- def str(self):
- return "\n".join(self.lines)
-
- def fnmatch_lines(self, lines2):
- if isinstance(lines2, str):
- lines2 = py.code.Source(lines2)
- if isinstance(lines2, py.code.Source):
- lines2 = lines2.strip().lines
-
- from fnmatch import fnmatch
- lines1 = self.lines[:]
- nextline = None
- extralines = []
- __tracebackhide__ = True
- for line in lines2:
- nomatchprinted = False
- while lines1:
- nextline = lines1.pop(0)
- if line == nextline:
- print("exact match:", repr(line))
- break
- elif fnmatch(nextline, line):
- print("fnmatch:", repr(line))
- print(" with:", repr(nextline))
- break
- else:
- if not nomatchprinted:
- print("nomatch:", repr(line))
- nomatchprinted = True
- print(" and:", repr(nextline))
- extralines.append(nextline)
- else:
- assert line == nextline
-
-
@pytest.fixture
def initproj(request, tmpdir):
"""Create a factory function for creating example projects
@@ -315,13 +263,14 @@ def initproj(request, tmpdir):
setup.py
"""
+
def initproj(nameversion, filedefs=None, src_root="."):
if filedefs is None:
filedefs = {}
if not src_root:
src_root = '.'
if isinstance(nameversion, six.string_types):
- parts = nameversion.split("-")
+ parts = nameversion.split(str("-"))
if len(parts) == 1:
parts.append("0.1")
name, version = parts
@@ -362,6 +311,8 @@ def initproj(request, tmpdir):
print("created project in %s" % (base,))
base.chdir()
+ return base
+
return initproj
@@ -414,6 +365,6 @@ def create_files(base, filedefs):
for key, value in filedefs.items():
if isinstance(value, dict):
create_files(base.ensure(key, dir=1), value)
- elif isinstance(value, str):
+ elif isinstance(value, six.string_types):
s = textwrap.dedent(value)
base.join(key).write(s)
diff --git a/tox/_quickstart.py b/tox/_quickstart.py
index 4d3c683f..d685f12a 100644
--- a/tox/_quickstart.py
+++ b/tox/_quickstart.py
@@ -55,7 +55,6 @@ try:
except NameError:
term_input = input
-
all_envs = ['py27', 'py34', 'py35', 'py36', 'pypy', 'jython']
PROMPT_PREFIX = '> '
@@ -90,6 +89,7 @@ def choice(*l):
if x not in l:
raise ValidationError('Please enter one of %s.' % ', '.join(l))
return x
+
return val
@@ -119,7 +119,7 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
x = term_input(prompt)
if default and not x:
x = default
- if sys.version_info < (3, ) and not isinstance(x, unicode): # noqa
+ if sys.version_info < (3,) and not isinstance(x, unicode): # noqa
# for Python 2.x, try to get a Unicode string out of it
if x.decode('ascii', 'replace').encode('ascii', 'replace') != x:
if TERM_ENCODING:
diff --git a/tox/_verlib.py b/tox/_verlib.py
index dca82156..79f9a11e 100644
--- a/tox/_verlib.py
+++ b/tox/_verlib.py
@@ -73,6 +73,7 @@ class NormalizedVersion(object):
1.2a # release level must have a release serial
1.2.3b
"""
+
def __init__(self, s, error_on_huge_major_num=True):
"""Create a NormalizedVersion instance from a version string.
diff --git a/tox/config.py b/tox/config.py
index abbe3d87..d03c97e0 100755
--- a/tox/config.py
+++ b/tox/config.py
@@ -224,19 +224,15 @@ class InstallcmdOption:
return value
-def parseconfig(args=None, plugins=()):
+def parseconfig(args, plugins=()):
"""
- :param list[str] args: Optional list of arguments.
+ :param list[str] args: list of arguments.
:type pkg: str
:rtype: :class:`Config`
:raise SystemExit: toxinit file is not found
"""
pm = get_plugin_manager(plugins)
-
- if args is None:
- args = sys.argv[1:]
-
# prepare command line options
parser = Parser()
pm.hook.tox_addoption(parser=parser)
@@ -357,7 +353,7 @@ def tox_addoption(parser):
help="show help about ini-names")
parser.add_argument("-v", action='count', dest="verbose_level", default=0,
help="increase verbosity of reporting output. -vv mode turns off "
- "output redirection for package installation")
+ "output redirection for package installation")
parser.add_argument("-q", action="count", dest="quiet_level", default=0,
help="progressively silence reporting output.")
parser.add_argument("--showconfig", action="store_true",
@@ -400,7 +396,7 @@ def tox_addoption(parser):
parser.add_argument("--result-json", action="store",
dest="resultjson", metavar="PATH",
help="write a json file with detailed information "
- "about all commands and results involved.")
+ "about all commands and results involved.")
# We choose 1 to 4294967295 because it is the range of PYTHONHASHSEED.
parser.add_argument("--hashseed", action="store",
@@ -526,16 +522,16 @@ def tox_addoption(parser):
# so we just pass it on by default for now.
if sys.platform == "win32":
passenv.add("SYSTEMDRIVE") # needed for pip6
- passenv.add("SYSTEMROOT") # needed for python's crypto module
- passenv.add("PATHEXT") # needed for discovering executables
- passenv.add("COMSPEC") # needed for distutils cygwincompiler
+ passenv.add("SYSTEMROOT") # needed for python's crypto module
+ passenv.add("PATHEXT") # needed for discovering executables
+ passenv.add("COMSPEC") # needed for distutils cygwincompiler
passenv.add("TEMP")
passenv.add("TMP")
# for `multiprocessing.cpu_count()` on Windows
# (prior to Python 3.4).
passenv.add("NUMBER_OF_PROCESSORS")
passenv.add("USERPROFILE") # needed for `os.path.expanduser()`
- passenv.add("MSYSTEM") # fixes #429
+ passenv.add("MSYSTEM") # fixes #429
else:
passenv.add("TMPDIR")
for spec in value:
@@ -621,6 +617,7 @@ def tox_addoption(parser):
class Config(object):
""" Global Tox config object. """
+
def __init__(self, pluginmanager, option, interpreters):
#: dictionary containing envname to envconfig mappings
self.envconfigs = {}
@@ -643,6 +640,7 @@ class TestenvConfig:
In addition to some core attributes/properties this config object holds all
per-testenv ini attributes as attributes, see "tox --help-ini" for an overview.
"""
+
def __init__(self, envname, config, factors, reader):
#: test environment name
self.envname = envname
@@ -662,7 +660,7 @@ class TestenvConfig:
def get_envbindir(self):
""" path to directory where scripts/binaries reside. """
if sys.platform == "win32" and "jython" not in self.basepython and \
- "pypy" not in self.basepython:
+ "pypy" not in self.basepython:
return self.envdir.join("Scripts")
else:
return self.envdir.join("bin")
@@ -709,9 +707,6 @@ class TestenvConfig:
if not info.version_info:
raise tox.exception.InvocationError(
'Failed to get version_info for %s: %s' % (info.name, info.err))
- if info.version_info < (2, 6):
- raise tox.exception.UnsupportedInterpreter(
- "python2.5 is not supported anymore, sorry")
return info.executable
@@ -885,10 +880,10 @@ class parseini:
return tc
def _getenvdata(self, reader):
- envstr = self.config.option.env \
- or os.environ.get("TOXENV") \
- or reader.getstring("envlist", replace=False) \
- or []
+ envstr = self.config.option.env \
+ or os.environ.get("TOXENV") \
+ or reader.getstring("envlist", replace=False) \
+ or []
envlist = _split_env(envstr)
# collect section envs
@@ -970,6 +965,7 @@ class DepConfig:
return self.name
return ":%s:%s" % (self.indexserver.name, self.name)
return str(self.name)
+
__repr__ = __str__
@@ -1048,7 +1044,7 @@ class SectionReader:
s = default
if s is None:
raise KeyError("no config value [%s] %s found" % (
- self.section_name, name))
+ self.section_name, name))
if not isinstance(s, bool):
if s.lower() == "true":
@@ -1094,8 +1090,8 @@ class SectionReader:
expr, line = m.groups()
if any(included <= self.factors
- and not any(x in self.factors for x in excluded)
- for included, excluded in _split_factor_expr(expr)):
+ and not any(x in self.factors for x in excluded)
+ for included, excluded in _split_factor_expr(expr)):
return line
lines = s.strip().splitlines()
@@ -1137,6 +1133,7 @@ class Replacer:
'''
Recursively expand substitutions starting from the innermost expression
'''
+
def substitute_once(x):
return self.RE_ITEM_REF.sub(self._replace_match, x)
@@ -1294,7 +1291,6 @@ class _ArgvlistReader:
class CommandParser(object):
-
class State(object):
def __init__(self):
self.word = ''
diff --git a/tox/session.py b/tox/session.py
index c50f1690..51794e40 100644
--- a/tox/session.py
+++ b/tox/session.py
@@ -34,10 +34,12 @@ def prepare(args):
return config
-def main(args=None):
+def main(args):
try:
config = prepare(args)
retcode = Session(config).runcommand()
+ if retcode is None:
+ retcode = 0
raise SystemExit(retcode)
except KeyboardInterrupt:
raise SystemExit(2)
@@ -198,7 +200,7 @@ class Action(object):
raise tox.exception.InvocationError(
"%s (see %s)" % (invoked, outpath), ret)
else:
- raise tox.exception.InvocationError("%r" % (invoked, ), ret)
+ raise tox.exception.InvocationError("%r" % (invoked,), ret)
if not out and outpath:
out = outpath.read()
if hasattr(self, "commandlog"):
@@ -462,9 +464,9 @@ class Session:
def setupenv(self, venv):
if venv.envconfig.missing_subs:
venv.status = (
- "unresolvable substitution(s): %s. "
- "Environment variables are missing or defined recursively." %
- (','.join(["'%s'" % m for m in venv.envconfig.missing_subs])))
+ "unresolvable substitution(s): %s. "
+ "Environment variables are missing or defined recursively." %
+ (','.join(["'%s'" % m for m in venv.envconfig.missing_subs])))
return
if not venv.matching_platform():
venv.status = "platform mismatch"
@@ -479,13 +481,13 @@ class Session:
if e.args[0] != 2:
raise
status = (
- "Error creating virtualenv. Note that spaces in paths are "
- "not supported by virtualenv. Error details: %r" % e)
+ "Error creating virtualenv. Note that spaces in paths are "
+ "not supported by virtualenv. Error details: %r" % e)
except tox.exception.InvocationError as e:
status = (
- "Error creating virtualenv. Note that some special "
- "characters (e.g. ':' and unicode symbols) in paths are "
- "not supported by virtualenv. Error details: %r" % e)
+ "Error creating virtualenv. Note that some special "
+ "characters (e.g. ':' and unicode symbols) in paths are "
+ "not supported by virtualenv. Error details: %r" % e)
if status:
commandlog = envlog.get_commandlog("setup")
commandlog.add_command(["setup virtualenv"], str(status), 1)
@@ -681,6 +683,7 @@ class Session:
else:
msg = e
self.report.line(msg)
+
for e in default:
report_env(e)
if all_envs and extra:
diff --git a/tox/venv.py b/tox/venv.py
index 851a330d..26bb42ae 100755
--- a/tox/venv.py
+++ b/tox/venv.py
@@ -158,7 +158,7 @@ class VirtualEnv(object):
"""
rconfig = CreationConfig.readconfig(self.path_config)
if not self.envconfig.recreate and rconfig and \
- rconfig.matches(self._getliveconfig()):
+ rconfig.matches(self._getliveconfig()):
action.info("reusing", self.envconfig.envdir)
return
if rconfig is None: