From bbc2c11dc9213d42c3ff840d672437249a83b355 Mon Sep 17 00:00:00 2001 From: Bernat Gabor Date: Mon, 21 Jan 2019 11:35:53 +0000 Subject: [PATCH] more test fixes --- src/tox/_pytestplugin.py | 45 ++-- src/tox/action.py | 16 +- src/tox/constants.py | 10 + src/tox/helper/__init__.py | 0 src/tox/helper/build_isolated.py | 14 ++ src/tox/helper/build_requires.py | 13 + src/tox/helper/get_site_package_dir.py | 8 + src/tox/helper/get_version.py | 13 + src/tox/interpreters.py | 28 +-- src/tox/logs/env.py | 15 +- src/tox/package/builder/isolated.py | 44 ++-- src/tox/reporter.py | 10 +- src/tox/session/__init__.py | 9 +- src/tox/util/lock.py | 2 +- tests/unit/package/test_package_parallel.py | 3 +- tests/unit/session/test_session.py | 34 ++- tests/unit/test_venv.py | 258 ++++++++++---------- tests/unit/test_z_cmdline.py | 15 +- 18 files changed, 307 insertions(+), 230 deletions(-) create mode 100644 src/tox/helper/__init__.py create mode 100644 src/tox/helper/build_isolated.py create mode 100644 src/tox/helper/build_requires.py create mode 100644 src/tox/helper/get_site_package_dir.py create mode 100644 src/tox/helper/get_version.py diff --git a/src/tox/_pytestplugin.py b/src/tox/_pytestplugin.py index f71bb388b5..ea59e3918a 100644 --- a/src/tox/_pytestplugin.py +++ b/src/tox/_pytestplugin.py @@ -71,6 +71,7 @@ def cmd(request, monkeypatch): request.addfinalizer(py.path.local().chdir) def run(*argv): + reset_report() key = str("PYTHONPATH") python_paths = (i for i in (os.getcwd(), os.getenv(key)) if i) monkeypatch.setenv(key, os.pathsep.join(python_paths)) @@ -107,15 +108,17 @@ def __init__(self, args): def __enter__(self): self._start = time.time() + self._out_tell = sys.stdout.tell() + self._err_tell = sys.stderr.tell() return self def __exit__(self, exc_type, exc_val, exc_tb): self.duration = time.time() - self._start - self.out = self._read(sys.stdout) - self.err = self._read(sys.stderr) + self.out = self._read(sys.stdout, self._out_tell) + self.err = self._read(sys.stderr, self._err_tell) - def _read(self, out): - out.buffer.seek(0) + def _read(self, out, pos): + out.buffer.seek(pos) return out.buffer.read().decode(out.encoding, errors=out.errors) @property @@ -138,7 +141,10 @@ def __init__(self): def clear(self): self._index = -1 - self.instance.reported_lines.clear() + if six.PY3: + self.instance.reported_lines.clear() + else: + del self.instance.reported_lines[:] def getnext(self, cat): __tracebackhide__ = True @@ -208,13 +214,16 @@ def create_mocksession(request): class MockSession(Session): def __init__(self, config): - update_default_reporter(config.option.quiet_level, config.option.verbose_level) + self.logging_levels(config.option.quiet_level, config.option.verbose_level) super(MockSession, self).__init__(config, popen=self.popen) self._pcalls = [] self.report = ReportExpectMock() def _clearmocks(self): - self._pcalls.clear() + if six.PY3: + self._pcalls.clear() + else: + del self._pcalls[:] self.report.clear() def popen(self, args, cwd, shell=None, stdout=None, stderr=None, env=None, **_): @@ -223,11 +232,17 @@ def popen(self, args, cwd, shell=None, stdout=None, stderr=None, env=None, **_): return process_call_mock def new_config(self, config): - update_default_reporter(config.option.quiet_level, config.option.verbose_level) + self.logging_levels(config.option.quiet_level, config.option.verbose_level) self.config = config self.venv_dict.clear() self.existing_venvs.clear() + def logging_levels(self, quiet, verbose): + update_default_reporter(quiet, verbose) + if hasattr(self, "config"): + self.config.option.quiet_level = quiet + self.config.option.verbose_level = verbose + return MockSession(config) @@ -494,18 +509,18 @@ def current_tox_py(): def pytest_runtest_setup(item): - from tox.reporter import _INSTANCE - - _INSTANCE._reset() + reset_report() def pytest_runtest_teardown(item): - from tox.reporter import _INSTANCE - - _INSTANCE._reset() + reset_report() def pytest_pyfunc_call(pyfuncitem): + reset_report() + + +def reset_report(quiet=0, verbose=0): from tox.reporter import _INSTANCE - _INSTANCE._reset() + _INSTANCE._reset(quiet_level=quiet, verbose_level=verbose) diff --git a/src/tox/action.py b/src/tox/action.py index fe3434da77..bda9c34324 100644 --- a/src/tox/action.py +++ b/src/tox/action.py @@ -66,13 +66,15 @@ def popen( stream_getter = self._get_standard_streams( capture_err, cmd_args_shell, redirect, returnout ) + cwd = os.getcwd() if cwd is None else cwd with stream_getter as (fin, out_path, stderr, stdout): try: + args = self._rewrite_args(cwd, args) process = self.via_popen( - self._rewrite_args(cwd, args), + args, stdout=stdout, stderr=stderr, - cwd=cwd, + cwd=str(cwd), env=os.environ.copy() if env is None else env, universal_newlines=True, shell=False, @@ -88,20 +90,20 @@ def popen( output = self.feed_stdin(fin, process, redirect) exit_code = process.wait() if exit_code and not ignore_ret: - invoked = " ".join(map(str, process.args)) + invoked = " ".join(map(str, args)) if out_path: reporter.error( "invocation failed (exit code {:d}), logfile: {}".format(exit_code, out_path) ) output = out_path.read() reporter.error(output) - self.command_log.add_command(process.args, output, exit_code) + self.command_log.add_command(args, output, exit_code) raise InvocationError(invoked, exit_code, out_path) else: raise InvocationError(invoked, exit_code) if not output and out_path: output = out_path.read() - self.command_log.add_command(process.args, output, exit_code) + self.command_log.add_command(args, output, exit_code) return output def feed_stdin(self, fin, process, redirect): @@ -149,14 +151,14 @@ def _get_standard_streams(self, capture_err, cmd_args_shell, redirect, returnout stderr = subprocess.STDOUT if capture_err else None stdout_file = None if self.generate_tox_log or redirect: - stdout_file = open(self.get_log_path(self.name), "wt") + out_path = self.get_log_path(self.name) + stdout_file = out_path.open("wt") stdout_file.write( "actionid: {}\nmsg: {}\ncmdargs: {!r}\n\n".format( self.name, self.msg, cmd_args_shell ) ) stdout_file.flush() - out_path = py.path.local(stdout_file.name) fin = out_path.open("rb") fin.read() # read the header, so it won't be written to stdout stdout = stdout_file diff --git a/src/tox/constants.py b/src/tox/constants.py index ecf0c97d03..ac72058d9e 100644 --- a/src/tox/constants.py +++ b/src/tox/constants.py @@ -2,9 +2,12 @@ They live in the tox namespace and can be accessed as tox.[NAMESPACE.]NAME """ +import os import re import sys +_THIS_FILE = os.path.realpath(os.path.abspath(__file__)) + def _construct_default_factors(cpython_versions, pypy_versions, other_interpreters): default_factors = {"py": sys.executable, "py2": "python2", "py3": "python3"} @@ -75,3 +78,10 @@ class PIP: ] INSTALL_SHORT_OPTIONS_ARGUMENT = ["-{}".format(option) for option in SHORT_OPTIONS] INSTALL_LONG_OPTIONS_ARGUMENT = ["--{}".format(option) for option in LONG_OPTIONS] + + +_HELP_DIR = os.path.join(os.path.dirname(_THIS_FILE), "helper") +VERSION_QUERY_SCRIPT = os.path.join(_HELP_DIR, "get_version.py") +SITE_PACKAGE_QUERY_SCRIPT = os.path.join(_HELP_DIR, "get_site_package_dir.py") +BUILD_REQUIRE_SCRIPT = os.path.join(_HELP_DIR, "build_requires.py") +BUILD_ISOLATED = os.path.join(_HELP_DIR, "build_isolated.py") diff --git a/src/tox/helper/__init__.py b/src/tox/helper/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/tox/helper/build_isolated.py b/src/tox/helper/build_isolated.py new file mode 100644 index 0000000000..27e4e8ba9d --- /dev/null +++ b/src/tox/helper/build_isolated.py @@ -0,0 +1,14 @@ +import sys + +backend_spec = sys.argv[1] +backend_obj = sys.argv[2] + + +backend = __import__(backend_spec, fromlist=[None]) +if backend_obj: + backend = getattr(backend, backend_obj) + +dist_folder = sys.argv[3] + +basename = backend.build_sdist(dist_folder, {"--global-option": ["--formats=gztar"]}) +print(basename) diff --git a/src/tox/helper/build_requires.py b/src/tox/helper/build_requires.py new file mode 100644 index 0000000000..3456c10f44 --- /dev/null +++ b/src/tox/helper/build_requires.py @@ -0,0 +1,13 @@ +import json +import sys + +backend_spec = sys.argv[1] +backend_obj = sys.argv[2] +backend = __import__(backend_spec, fromlist=[None]) +if backend_obj: + backend = getattr(backend, backend_obj) + + +for_build_requires = backend.get_requires_for_build_sdist(None) +output = json.dumps(for_build_requires) +print(output) diff --git a/src/tox/helper/get_site_package_dir.py b/src/tox/helper/get_site_package_dir.py new file mode 100644 index 0000000000..584f5103e6 --- /dev/null +++ b/src/tox/helper/get_site_package_dir.py @@ -0,0 +1,8 @@ +from __future__ import unicode_literals + +import distutils.sysconfig +import json +import sys + +data = json.dumps({"dir": distutils.sysconfig.get_python_lib(prefix=sys.argv[1])}) +print(data) diff --git a/src/tox/helper/get_version.py b/src/tox/helper/get_version.py new file mode 100644 index 0000000000..ef37a796f4 --- /dev/null +++ b/src/tox/helper/get_version.py @@ -0,0 +1,13 @@ +from __future__ import unicode_literals + +import json +import sys + +info = { + "executable": sys.executable, + "version_info": list(sys.version_info), + "version": sys.version, + "sysplatform": sys.platform, +} +info_as_dump = json.dumps(info) +print(info_as_dump) diff --git a/src/tox/interpreters.py b/src/tox/interpreters.py index 503b5065cc..6c6cfcc332 100644 --- a/src/tox/interpreters.py +++ b/src/tox/interpreters.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import distutils.util import json import re @@ -7,6 +9,7 @@ import py import tox +from tox.constants import SITE_PACKAGE_QUERY_SCRIPT, VERSION_QUERY_SCRIPT class Interpreters: @@ -45,13 +48,7 @@ def get_sitepackagesdir(self, info, envdir): return "" envdir = str(envdir) try: - code = ( - "import distutils.sysconfig; import json;" - "print(json.dumps(" - "{{ 'dir': distutils.sysconfig.get_python_lib(prefix={!r})}}" - "))" - ) - res = exec_on_interpreter(str(info.executable), "-c", code.format(envdir)) + res = exec_on_interpreter(str(info.executable), SITE_PACKAGE_QUERY_SCRIPT, str(envdir)) except ExecFailed as e: print("execution failed: {} -- {}".format(e.out, e.err)) return "" @@ -62,18 +59,13 @@ def get_sitepackagesdir(self, info, envdir): def run_and_get_interpreter_info(name, executable): assert executable try: - result = exec_on_interpreter( - str(executable), - "-c", - "import sys; import json;" - 'print(json.dumps({"version_info": tuple(sys.version_info),' - ' "sysplatform": sys.platform}))', - ) + result = exec_on_interpreter(str(executable), VERSION_QUERY_SCRIPT) result["version_info"] = tuple(result["version_info"]) # fix json dump transformation + del result["version"] except ExecFailed as e: return NoInterpreterInfo(name, executable=e.executable, out=e.out, err=e.err) else: - return InterpreterInfo(name, executable, **result) + return InterpreterInfo(name, **result) def exec_on_interpreter(*args): @@ -168,12 +160,12 @@ def tox_get_python_executable(envconfig): def locate_via_py(*parts): ver = "-{}".format(".".join(parts)) - script = "import sys; print(sys.executable)" py_exe = distutils.spawn.find_executable("py") if py_exe: proc = subprocess.Popen( - (py_exe, ver, "-c", script), stdout=subprocess.PIPE, stderr=subprocess.PIPE + (py_exe, ver, VERSION_QUERY_SCRIPT), stdout=subprocess.PIPE, stderr=subprocess.PIPE ) out, _ = proc.communicate() + result = json.loads(out) if not proc.returncode: - return out.decode("UTF-8").strip() + return result["executable"] diff --git a/src/tox/logs/env.py b/src/tox/logs/env.py index f4ac205951..bbdc0be52e 100644 --- a/src/tox/logs/env.py +++ b/src/tox/logs/env.py @@ -3,6 +3,8 @@ import json import subprocess +from tox.constants import VERSION_QUERY_SCRIPT + from .command import CommandLog @@ -15,17 +17,10 @@ def __init__(self, result_log, name, dict): self.dict = dict def set_python_info(self, python_executable): - cmd = [ - str(python_executable), - "-c", - "import sys; import json;" - "print(json.dumps({" - "'executable': sys.executable," - "'version_info': list(sys.version_info)," - "'version': sys.version}))", - ] + cmd = [str(python_executable), VERSION_QUERY_SCRIPT] result = subprocess.check_output(cmd, universal_newlines=True) - self.dict["python"] = json.loads(result) + answer = json.loads(result) + self.dict["python"] = answer def get_commandlog(self, name): """get the command log for a given group name""" diff --git a/src/tox/package/builder/isolated.py b/src/tox/package/builder/isolated.py index ea4d112600..8379fc5267 100644 --- a/src/tox/package/builder/isolated.py +++ b/src/tox/package/builder/isolated.py @@ -1,5 +1,5 @@ +from __future__ import unicode_literals import json -import textwrap from collections import namedtuple import pkg_resources @@ -7,6 +7,7 @@ from tox import reporter from tox.config import DepConfig, get_py_project_toml +from tox.constants import BUILD_ISOLATED, BUILD_REQUIRE_SCRIPT BuildInfo = namedtuple("BuildInfo", ["requires", "backend_module", "backend_object"]) @@ -75,32 +76,28 @@ def abort(message): args = backend.split(":") module = args[0] - obj = "" if len(args) == 1 else ".{}".format(args[1]) + obj = args[1] if len(args) > 1 else "" - return BuildInfo(requires, module, "{}{}".format(module, obj)) + return BuildInfo(requires, module, obj) def perform_isolated_build(build_info, package_venv, dist_dir, setup_dir): with package_venv.new_action( "perform-isolated-build", package_venv.envconfig.envdir ) as action: - script = textwrap.dedent( - """ - import sys - import {} - basename = {}.build_{}({!r}, {{ "--global-option": ["--formats=gztar"]}}) - print(basename)""".format( - build_info.backend_module, build_info.backend_object, "sdist", str(dist_dir) - ) - ) - # need to start with an empty (but existing) source distribution folder if dist_dir.exists(): dist_dir.remove(rec=1, ignore_errors=True) dist_dir.ensure_dir() result = package_venv._pcall( - [package_venv.envconfig.envpython, "-c", script], + [ + package_venv.envconfig.envpython, + BUILD_ISOLATED, + build_info.backend_module, + build_info.backend_object, + str(dist_dir), + ], returnout=True, action=action, cwd=setup_dir, @@ -111,20 +108,13 @@ def perform_isolated_build(build_info, package_venv, dist_dir, setup_dir): def get_build_requires(build_info, package_venv, setup_dir): with package_venv.new_action("get-build-requires", package_venv.envconfig.envdir) as action: - script = textwrap.dedent( - """ - import {} - import json - - backend = {} - for_build_requires = backend.get_requires_for_build_{}(None) - print(json.dumps(for_build_requires)) - """.format( - build_info.backend_module, build_info.backend_object, "sdist" - ) - ).strip() result = package_venv._pcall( - [package_venv.envconfig.envpython, "-c", script], + [ + package_venv.envconfig.envpython, + BUILD_REQUIRE_SCRIPT, + build_info.backend_module, + build_info.backend_object, + ], returnout=True, action=action, cwd=setup_dir, diff --git a/src/tox/reporter.py b/src/tox/reporter.py index adab06b96e..ed287957e0 100644 --- a/src/tox/reporter.py +++ b/src/tox/reporter.py @@ -36,10 +36,10 @@ def verbosity(self): def log_popen(self, cwd, outpath, cmd_args_shell): """ log information about the action.popen() created process. """ + msg = " {}$ {} ".format(cwd, cmd_args_shell) if outpath: - self.verbosity1(" {}$ {} >{}".format(cwd, cmd_args_shell, outpath)) - else: - self.verbosity1(" {}$ {} ".format(cwd, cmd_args_shell)) + msg = "{} >{}".format(msg, outpath) + self.verbosity1(msg, of="logpopen") @property def messages(self): @@ -100,8 +100,8 @@ def skip(self, msg): def verbosity0(self, msg, **opts): self.logline_if(Verbosity.DEFAULT, "verbosity0", msg, **opts) - def verbosity1(self, msg, **opts): - self.logline_if(Verbosity.INFO, "verbosity1", msg, **opts) + def verbosity1(self, msg, of="verbosity1", **opts): + self.logline_if(Verbosity.INFO, of, msg, **opts) def verbosity2(self, msg, **opts): self.logline_if(Verbosity.DEBUG, "verbosity2", msg, **opts) diff --git a/src/tox/session/__init__.py b/src/tox/session/__init__.py index 2509f2b7c3..a5ce663f40 100644 --- a/src/tox/session/__init__.py +++ b/src/tox/session/__init__.py @@ -85,7 +85,7 @@ def build_session(config): return Session(config) -class Session: +class Session(object): """The session object that ties together configuration, reporting, venv creation, testing.""" def __init__(self, config, popen=subprocess.Popen): @@ -149,9 +149,9 @@ def _evaluated_env_list(self): def hook(self): return self.config.pluginmanager.hook - def newaction(self, env, msg, *args): - new_action = Action( - env, + def newaction(self, name, msg, *args): + return Action( + name, msg, args, self.config.logdir, @@ -160,7 +160,6 @@ def newaction(self, env, msg, *args): self.popen, sys.executable, ) - return new_action def runcommand(self): reporter.using("tox-{} from {}".format(tox.__version__, tox.__file__)) diff --git a/src/tox/util/lock.py b/src/tox/util/lock.py index 7f7ad7ce1f..0cff0137be 100644 --- a/src/tox/util/lock.py +++ b/src/tox/util/lock.py @@ -34,6 +34,6 @@ def get_unique_file(path, prefix, suffix, report): max_value = max(max_value, int(candidate.name[len(prefix) : -len(suffix)])) except ValueError: continue - winner = path.join("{}-{}.log".format(prefix, max_value + 1)) + winner = path.join("{}{}.log".format(prefix, max_value + 1)) winner.ensure(dir=0) return winner diff --git a/tests/unit/package/test_package_parallel.py b/tests/unit/package/test_package_parallel.py index 7eeb162b54..8d084cd8a5 100644 --- a/tests/unit/package/test_package_parallel.py +++ b/tests/unit/package/test_package_parallel.py @@ -1,5 +1,4 @@ import traceback -from functools import partial import py @@ -15,7 +14,7 @@ def test_tox_parallel_build_safe(initproj, cmd, mock_venv, monkeypatch): envlist = py install_cmd = python -m -c 'print("ok")' -- {opts} {packages}' [testenv] - commands = python --version + commands = python -c 'import sys; print(sys.version)' """ }, ) diff --git a/tests/unit/session/test_session.py b/tests/unit/session/test_session.py index 206d7af8d0..becb6a3891 100644 --- a/tests/unit/session/test_session.py +++ b/tests/unit/session/test_session.py @@ -9,6 +9,7 @@ import tox from tox.exception import MissingDependency, MissingDirectory from tox.package import resolve_package +from tox.reporter import Verbosity def test_resolve_pkg_missing_directory(tmpdir, mocksession): @@ -27,6 +28,7 @@ def test_resolve_pkg_missing_directory_in_distshare(tmpdir, mocksession): def test_resolve_pkg_multiple_valid_versions(tmpdir, mocksession): + mocksession.logging_levels(quiet=Verbosity.DEFAULT, verbose=Verbosity.DEBUG) distshare = tmpdir.join("distshare") distshare.ensure("pkg123-1.3.5.zip") p = distshare.ensure("pkg123-1.4.5.zip") @@ -239,8 +241,8 @@ def build_session(config): monkeypatch.setattr(tox.session, "build_session", build_session) def popen(cmd, **kwargs): - activity_id = res.session._actions[-1].name - activity_name = res.session._actions[-1].activity + activity_id = _actions[-1].name + activity_name = _actions[-1].activity ret = "NOTSET" try: ret = res._popen(cmd, **kwargs) @@ -252,6 +254,25 @@ def popen(cmd, **kwargs): ) return ret + _actions = [] + from tox.action import Action + + _prev_enter = Action.__enter__ + + def enter(self): + _actions.append(self) + return _prev_enter(self) + + monkeypatch.setattr(Action, "__enter__", enter) + + _prev_exit = Action.__exit__ + + def exit_func(self, *args, **kwargs): + del _actions[_actions.index(self)] + _prev_exit(self, *args, **kwargs) + + monkeypatch.setattr(Action, "__exit__", exit_func) + res.result = cmd("-e", tox_env) res.cwd = os.getcwd() @@ -279,7 +300,7 @@ def assert_popen_env(res): assert res.result.ret == 0, res.result.out for tox_id, _, env, __, ___ in res.popens: assert env["TOX_WORK_DIR"] == os.path.join(res.cwd, ".tox") - if tox_id != "tox": + if tox_id != "GLOB": assert env["TOX_ENV_NAME"] == tox_id assert env["TOX_ENV_DIR"] == os.path.join(res.cwd, ".tox", tox_id) @@ -341,7 +362,7 @@ def test_command_prev_fail_command_skip_post_run(cmd, initproj, mock_venv): expected = textwrap.dedent( """ py run-test-pre: commands[0] | python -c 'raise SystemExit(2)' - ERROR: InvocationError for command '{} -c raise SystemExit(2)' (exited with code 2) + ERROR: InvocationError for command {} -c raise SystemExit(2) (exited with code 2) py run-test-post: commands[0] | python -c 'print("post")' post ___________________________________ summary ___________________________________{} @@ -350,5 +371,6 @@ def test_command_prev_fail_command_skip_post_run(cmd, initproj, mock_venv): sys.executable.replace("\\", "\\\\"), "_" if sys.platform != "win32" else "" ) ) - actual = result.out.replace(os.linesep, "\n") - assert expected in actual + have = result.out.replace(os.linesep, "\n") + actual = have[len(have) - len(expected) :] + assert actual == expected diff --git a/tests/unit/test_venv.py b/tests/unit/test_venv.py index 8a8d8fc4ce..2b6b932b64 100644 --- a/tests/unit/test_venv.py +++ b/tests/unit/test_venv.py @@ -66,8 +66,8 @@ def test_create(mocksession, newconfig): venv = mocksession.getvenv("py123") assert venv.path == envconfig.envdir assert not venv.path.check() - action = mocksession.newaction(venv, "getenv") - tox_testenv_create(action=action, venv=venv) + with mocksession.newaction(venv, "getenv") as action: + tox_testenv_create(action=action, venv=venv) pcalls = mocksession._pcalls assert len(pcalls) >= 1 args = pcalls[0].args @@ -113,8 +113,8 @@ def test_create_sitepackages(mocksession, newconfig): ) mocksession.new_config(config) venv = mocksession.getvenv("site") - action = mocksession.newaction(venv, "getenv") - tox_testenv_create(action=action, venv=venv) + with mocksession.newaction(venv, "getenv") as action: + tox_testenv_create(action=action, venv=venv) pcalls = mocksession._pcalls assert len(pcalls) >= 1 args = pcalls[0].args @@ -122,8 +122,8 @@ def test_create_sitepackages(mocksession, newconfig): mocksession._clearmocks() venv = mocksession.getvenv("nosite") - action = mocksession.newaction(venv, "getenv") - tox_testenv_create(action=action, venv=venv) + with mocksession.newaction(venv, "getenv") as action: + tox_testenv_create(action=action, venv=venv) pcalls = mocksession._pcalls assert len(pcalls) >= 1 args = pcalls[0].args @@ -143,18 +143,18 @@ def test_install_deps_wildcard(newmocksession): """, ) venv = mocksession.getvenv("py123") - action = mocksession.newaction(venv, "getenv") - tox_testenv_create(action=action, venv=venv) - pcalls = mocksession._pcalls - assert len(pcalls) == 1 - distshare = venv.envconfig.config.distshare - distshare.ensure("dep1-1.0.zip") - distshare.ensure("dep1-1.1.zip") + with mocksession.newaction(venv, "getenv") as action: + tox_testenv_create(action=action, venv=venv) + pcalls = mocksession._pcalls + assert len(pcalls) == 1 + distshare = venv.envconfig.config.distshare + distshare.ensure("dep1-1.0.zip") + distshare.ensure("dep1-1.1.zip") - tox_testenv_install_deps(action=action, venv=venv) - assert len(pcalls) == 2 - args = pcalls[-1].args - assert pcalls[-1].cwd == venv.envconfig.config.toxinidir + tox_testenv_install_deps(action=action, venv=venv) + assert len(pcalls) == 2 + args = pcalls[-1].args + assert pcalls[-1].cwd == venv.envconfig.config.toxinidir assert py.path.local.sysfind("python") == args[0] assert ["-m", "pip"] == args[1:3] @@ -179,25 +179,25 @@ def test_install_deps_indexserver(newmocksession): """, ) venv = mocksession.getvenv("py123") - action = mocksession.newaction(venv, "getenv") - tox_testenv_create(action=action, venv=venv) - pcalls = mocksession._pcalls - assert len(pcalls) == 1 - pcalls[:] = [] + with mocksession.newaction(venv, "getenv") as action: + tox_testenv_create(action=action, venv=venv) + pcalls = mocksession._pcalls + assert len(pcalls) == 1 + pcalls[:] = [] - tox_testenv_install_deps(action=action, venv=venv) - # two different index servers, two calls - assert len(pcalls) == 3 - args = " ".join(pcalls[0].args) - assert "-i " not in args - assert "dep1" in args + tox_testenv_install_deps(action=action, venv=venv) + # two different index servers, two calls + assert len(pcalls) == 3 + args = " ".join(pcalls[0].args) + assert "-i " not in args + assert "dep1" in args - args = " ".join(pcalls[1].args) - assert "-i ABC" in args - assert "dep2" in args - args = " ".join(pcalls[2].args) - assert "-i ABC" in args - assert "dep3" in args + args = " ".join(pcalls[1].args) + assert "-i ABC" in args + assert "dep2" in args + args = " ".join(pcalls[2].args) + assert "-i ABC" in args + assert "dep3" in args def test_install_deps_pre(newmocksession): @@ -211,8 +211,8 @@ def test_install_deps_pre(newmocksession): """, ) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "getenv") - tox_testenv_create(action=action, venv=venv) + with mocksession.newaction(venv, "getenv") as action: + tox_testenv_create(action=action, venv=venv) pcalls = mocksession._pcalls assert len(pcalls) == 1 pcalls[:] = [] @@ -254,12 +254,12 @@ def test_install_recreate(newmocksession, tmpdir): ) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "update") - venv.update(action) - installpkg(venv, pkg) - mocksession.report.expect("verbosity0", "*create*") - venv.update(action) - mocksession.report.expect("verbosity0", "*recreate*") + with mocksession.newaction(venv, "update") as action: + venv.update(action) + installpkg(venv, pkg) + mocksession.report.expect("verbosity0", "*create*") + venv.update(action) + mocksession.report.expect("verbosity0", "*recreate*") def test_install_sdist_extras(newmocksession): @@ -272,8 +272,8 @@ def test_install_sdist_extras(newmocksession): """, ) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "getenv") - tox_testenv_create(action=action, venv=venv) + with mocksession.newaction(venv, "getenv") as action: + tox_testenv_create(action=action, venv=venv) pcalls = mocksession._pcalls assert len(pcalls) == 1 pcalls[:] = [] @@ -292,8 +292,8 @@ def test_develop_extras(newmocksession, tmpdir): """, ) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "getenv") - tox_testenv_create(action=action, venv=venv) + with mocksession.newaction(venv, "getenv") as action: + tox_testenv_create(action=action, venv=venv) pcalls = mocksession._pcalls assert len(pcalls) == 1 pcalls[:] = [] @@ -318,9 +318,8 @@ def test_env_variables_added_to_needs_reinstall(tmpdir, mocksession, newconfig, ) mocksession.new_config(config) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "hello") - - venv._needs_reinstall(tmpdir, action) + with mocksession.newaction(venv, "hello") as action: + venv._needs_reinstall(tmpdir, action) pcalls = mocksession._pcalls assert len(pcalls) == 2 @@ -345,8 +344,8 @@ def test_test_hashseed_is_in_output(newmocksession, monkeypatch): monkeypatch.setattr("tox.config.make_hashseed", lambda: seed) mocksession = newmocksession([], "") venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "update") - venv.update(action) + with mocksession.newaction(venv, "update") as action: + venv.update(action) tox.venv.tox_runtest_pre(venv) mocksession.report.expect("verbosity0", "run-test-pre: PYTHONHASHSEED='{}'".format(seed)) @@ -360,8 +359,8 @@ def test_test_runtests_action_command_is_in_output(newmocksession): """, ) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "update") - venv.update(action) + with mocksession.newaction(venv, "update") as action: + venv.update(action) venv.test() mocksession.report.expect("verbosity0", "*runtests*commands?0? | echo foo bar") @@ -444,16 +443,16 @@ def test_install_python3(newmocksession): """, ) venv = mocksession.getvenv("py123") - action = mocksession.newaction(venv, "getenv") - tox_testenv_create(action=action, venv=venv) - pcalls = mocksession._pcalls - assert len(pcalls) == 1 - args = pcalls[0].args - assert str(args[2]) == "virtualenv" - pcalls[:] = [] - action = mocksession.newaction(venv, "hello") - venv._install(["hello"], action=action) - assert len(pcalls) == 1 + with mocksession.newaction(venv, "getenv") as action: + tox_testenv_create(action=action, venv=venv) + pcalls = mocksession._pcalls + assert len(pcalls) == 1 + args = pcalls[0].args + assert str(args[2]) == "virtualenv" + pcalls[:] = [] + with mocksession.newaction(venv, "hello") as action: + venv._install(["hello"], action=action) + assert len(pcalls) == 1 args = pcalls[0].args assert py.path.local.sysfind("python") == args[0] assert ["-m", "pip"] == args[1:3] @@ -543,9 +542,9 @@ def test_python_recreation(self, tmpdir, newconfig, mocksession): mocksession.new_config(config) venv = mocksession.getvenv("python") create_config = venv._getliveconfig() - action = mocksession.newaction(venv, "update") - venv.update(action) - assert not venv.path_config.check() + with mocksession.newaction(venv, "update") as action: + venv.update(action) + assert not venv.path_config.check() installpkg(venv, pkg) assert venv.path_config.check() assert mocksession._pcalls @@ -554,43 +553,43 @@ def test_python_recreation(self, tmpdir, newconfig, mocksession): mocksession.report.expect("*", "*create*") # modify config and check that recreation happens mocksession._clearmocks() - action = mocksession.newaction(venv, "update") - venv.update(action) - mocksession.report.expect("*", "*reusing*") - mocksession._clearmocks() - action = mocksession.newaction(venv, "update") - create_config.base_resolved_python_path = py.path.local("balla") - create_config.writeconfig(venv.path_config) - venv.update(action) - mocksession.report.expect("verbosity0", "*recreate*") + with mocksession.newaction(venv, "update") as action: + venv.update(action) + mocksession.report.expect("*", "*reusing*") + mocksession._clearmocks() + with mocksession.newaction(venv, "update") as action: + create_config.base_resolved_python_path = py.path.local("balla") + create_config.writeconfig(venv.path_config) + venv.update(action) + mocksession.report.expect("verbosity0", "*recreate*") def test_dep_recreation(self, newconfig, mocksession): config = newconfig([], "") mocksession.new_config(config) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "update") - venv.update(action) - cconfig = venv._getliveconfig() - cconfig.deps[:] = [("1" * 32, "xyz.zip")] - cconfig.writeconfig(venv.path_config) - mocksession._clearmocks() - action = mocksession.newaction(venv, "update") - venv.update(action) - mocksession.report.expect("*", "*recreate*") + with mocksession.newaction(venv, "update") as action: + venv.update(action) + cconfig = venv._getliveconfig() + cconfig.deps[:] = [("1" * 32, "xyz.zip")] + cconfig.writeconfig(venv.path_config) + mocksession._clearmocks() + with mocksession.newaction(venv, "update") as action: + venv.update(action) + mocksession.report.expect("*", "*recreate*") def test_develop_recreation(self, newconfig, mocksession): config = newconfig([], "") mocksession.new_config(config) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "update") - venv.update(action) - cconfig = venv._getliveconfig() - cconfig.usedevelop = True - cconfig.writeconfig(venv.path_config) - mocksession._clearmocks() - action = mocksession.newaction(venv, "update") - venv.update(action) - mocksession.report.expect("verbosity0", "*recreate*") + with mocksession.newaction(venv, "update") as action: + venv.update(action) + cconfig = venv._getliveconfig() + cconfig.usedevelop = True + cconfig.writeconfig(venv.path_config) + mocksession._clearmocks() + with mocksession.newaction(venv, "update") as action: + venv.update(action) + mocksession.report.expect("verbosity0", "*recreate*") class TestVenvTest: @@ -604,33 +603,33 @@ def test_envbindir_path(self, newmocksession, monkeypatch): """, ) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "getenv") - monkeypatch.setenv("PATH", "xyz") - sysfind_calls = [] - monkeypatch.setattr( - "py.path.local.sysfind", - classmethod(lambda *args, **kwargs: sysfind_calls.append(kwargs) or 0 / 0), - ) - - with pytest.raises(ZeroDivisionError): - venv._install(list("123"), action=action) - assert sysfind_calls.pop()["paths"] == [venv.envconfig.envbindir] - with pytest.raises(ZeroDivisionError): - venv.test(action) - assert sysfind_calls.pop()["paths"] == [venv.envconfig.envbindir] - with pytest.raises(ZeroDivisionError): - venv.run_install_command(["qwe"], action=action) - assert sysfind_calls.pop()["paths"] == [venv.envconfig.envbindir] - monkeypatch.setenv("PIP_RESPECT_VIRTUALENV", "1") - monkeypatch.setenv("PIP_REQUIRE_VIRTUALENV", "1") - monkeypatch.setenv("__PYVENV_LAUNCHER__", "1") - with pytest.raises(ZeroDivisionError): - venv.run_install_command(["qwe"], action=action) - assert "PIP_RESPECT_VIRTUALENV" not in os.environ - assert "PIP_REQUIRE_VIRTUALENV" not in os.environ - assert "__PYVENV_LAUNCHER__" not in os.environ - assert os.environ["PIP_USER"] == "0" - assert os.environ["PIP_NO_DEPS"] == "0" + with mocksession.newaction(venv, "getenv") as action: + monkeypatch.setenv("PATH", "xyz") + sysfind_calls = [] + monkeypatch.setattr( + "py.path.local.sysfind", + classmethod(lambda *args, **kwargs: sysfind_calls.append(kwargs) or 0 / 0), + ) + + with pytest.raises(ZeroDivisionError): + venv._install(list("123"), action=action) + assert sysfind_calls.pop()["paths"] == [venv.envconfig.envbindir] + with pytest.raises(ZeroDivisionError): + venv.test(action) + assert sysfind_calls.pop()["paths"] == [venv.envconfig.envbindir] + with pytest.raises(ZeroDivisionError): + venv.run_install_command(["qwe"], action=action) + assert sysfind_calls.pop()["paths"] == [venv.envconfig.envbindir] + monkeypatch.setenv("PIP_RESPECT_VIRTUALENV", "1") + monkeypatch.setenv("PIP_REQUIRE_VIRTUALENV", "1") + monkeypatch.setenv("__PYVENV_LAUNCHER__", "1") + with pytest.raises(ZeroDivisionError): + venv.run_install_command(["qwe"], action=action) + assert "PIP_RESPECT_VIRTUALENV" not in os.environ + assert "PIP_REQUIRE_VIRTUALENV" not in os.environ + assert "__PYVENV_LAUNCHER__" not in os.environ + assert os.environ["PIP_USER"] == "0" + assert os.environ["PIP_NO_DEPS"] == "0" def test_pythonpath_remove(self, newmocksession, monkeypatch, caplog): monkeypatch.setenv("PYTHONPATH", "/my/awesome/library") @@ -642,8 +641,8 @@ def test_pythonpath_remove(self, newmocksession, monkeypatch, caplog): """, ) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "getenv") - venv.run_install_command(["qwe"], action=action) + with mocksession.newaction(venv, "getenv") as action: + venv.run_install_command(["qwe"], action=action) assert "PYTHONPATH" not in os.environ mocksession.report.expect("warning", "*Discarding $PYTHONPATH from environment*") @@ -663,8 +662,8 @@ def test_pythonpath_keep(self, newmocksession, monkeypatch, caplog): """, ) venv = mocksession.getvenv("python") - action = mocksession.newaction(venv, "getenv") - venv.run_install_command(["qwe"], action=action) + with mocksession.newaction(venv, "getenv") as action: + venv.run_install_command(["qwe"], action=action) mocksession.report.not_expect("warning", "*Discarding $PYTHONPATH from environment*") assert "PYTHONPATH" in os.environ @@ -764,8 +763,8 @@ def test_run_install_command(newmocksession): venv = mocksession.getvenv("python") venv.just_created = True venv.envconfig.envdir.ensure(dir=1) - action = mocksession.newaction(venv, "hello") - venv.run_install_command(packages=["whatever"], action=action) + with mocksession.newaction(venv, "hello") as action: + venv.run_install_command(packages=["whatever"], action=action) pcalls = mocksession._pcalls assert len(pcalls) == 1 args = pcalls[0].args @@ -787,8 +786,8 @@ def test_run_custom_install_command(newmocksession): venv = mocksession.getvenv("python") venv.just_created = True venv.envconfig.envdir.ensure(dir=1) - action = mocksession.newaction(venv, "hello") - venv.run_install_command(packages=["whatever"], action=action) + with mocksession.newaction(venv, "hello") as action: + venv.run_install_command(packages=["whatever"], action=action) pcalls = mocksession._pcalls assert len(pcalls) == 1 assert "easy_install" in pcalls[0].args[0] @@ -859,7 +858,8 @@ def tox_testenv_install_deps(self, action, venv): ) venv = mocksession.getvenv("python") - venv.update(action=mocksession.newaction(venv, "getenv")) + with mocksession.newaction(venv, "getenv") as action: + venv.update(action=action) assert log == [1, 2] diff --git a/tests/unit/test_z_cmdline.py b/tests/unit/test_z_cmdline.py index 04faa22828..2e29f1b73f 100644 --- a/tests/unit/test_z_cmdline.py +++ b/tests/unit/test_z_cmdline.py @@ -11,6 +11,7 @@ import tox from tox.config import parseconfig +from tox.reporter import Verbosity from tox.session import Session pytest_plugins = "pytester" @@ -18,13 +19,16 @@ class TestSession: def test_log_pcall(self, mocksession): + mocksession.logging_levels(quiet=Verbosity.DEFAULT, verbose=Verbosity.INFO) mocksession.config.logdir.ensure(dir=1) assert not mocksession.config.logdir.listdir() - action = mocksession.newaction(None, "something") - action.popen(["echo"]) - match = mocksession.report.getnext("logpopen") - assert match[1].outpath.relto(mocksession.config.logdir) - assert match[1].shell is False + with mocksession.newaction("what", "something") as action: + action.popen(["echo"]) + match = mocksession.report.getnext("logpopen") + log_name = py.path.local(match[1].split(">")[-1].strip()).relto( + mocksession.config.logdir + ) + assert log_name == "what-0.log" def test_summary_status(self, initproj, capfd): initproj( @@ -136,6 +140,7 @@ def test_unknown_interpreter_and_env(cmd, initproj): basepython=xyz_unknown_interpreter [testenv] changedir=tests + skip_install = true """, }, )