Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/changelog/1270.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tox ignores unknown CLI arguments when provisioning is on and outside of the provisioned environment (allowing
provisioning arguments to be forwarded freely) - by :user:`gaborbernat`
12 changes: 10 additions & 2 deletions src/tox/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
default_factors = tox.PYTHON.DEFAULT_FACTORS
"""DEPRECATED MOVE - please update to new location."""

WITHIN_PROVISION = os.environ.get(str("TOX_PROVISION")) == "1"


def get_plugin_manager(plugins=()):
# initialize plugin manager
Expand Down Expand Up @@ -114,8 +116,11 @@ def add_testenv_attribute_obj(self, obj):
assert hasattr(obj, "postprocess")
self._testenv_attr.append(obj)

def parse_cli(self, args):
return self.argparser.parse_args(args)
def parse_cli(self, args, strict=False):
if strict or WITHIN_PROVISION:
return self.argparser.parse_args(args)
else:
return self.argparser.parse_known_args(args)[0]

def _format_help(self):
return self.argparser.format_help()
Expand Down Expand Up @@ -1106,6 +1111,9 @@ def handle_provision(self, config, reader):
env_config.deps = deps
config.envconfigs[config.provision_tox_env] = env_config
raise tox.exception.MissingRequirement(config)
# if provisioning is not on, now we need do a strict argument evaluation
# raise on unknown args
self.config._parser.parse_cli(args=self.config.args, strict=True)

@staticmethod
def ensure_requires_satisfied(config, requires, min_version):
Expand Down
6 changes: 5 additions & 1 deletion src/tox/session/commands/provision.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""In case the tox environment is not correctly setup provision it and delegate execution"""
from __future__ import absolute_import, unicode_literals

import os

from tox.exception import InvocationError


Expand All @@ -9,7 +11,9 @@ def provision_tox(provision_venv, args):
with provision_venv.new_action("provision") as action:
provision_args = [str(provision_venv.envconfig.envpython), "-m", "tox"] + args
try:
action.popen(provision_args, redirect=False, report_fail=False)
env = os.environ.copy()
env[str("TOX_PROVISION")] = str("1")
action.popen(provision_args, redirect=False, report_fail=False, env=env)
return 0
except InvocationError as exception:
return exception.exit_code
Expand Down
Empty file added tests/unit/__init__.py
Empty file.
8 changes: 8 additions & 0 deletions tests/unit/session/plugin/a/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import pluggy

hookimpl = pluggy.HookimplMarker("tox")


@hookimpl
def tox_addoption(parser):
parser.add_argument("--option", choices=["a", "b"], default="a", required=False)
10 changes: 10 additions & 0 deletions tests/unit/session/plugin/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[metadata]
name = plugin
description = test stuff
version = 0.1
[options]
zip_safe = True
packages = find:

[options.entry_points]
tox = plugin = a
3 changes: 3 additions & 0 deletions tests/unit/session/plugin/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from setuptools import setup

setup()
47 changes: 47 additions & 0 deletions tests/unit/session/test_provision.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import shutil
import subprocess
import sys

import py
import pytest

from tox.exception import BadRequirement, MissingRequirement
Expand Down Expand Up @@ -94,3 +97,47 @@ def test_provision_bad_requires(newconfig, capsys, monkeypatch):
out, err = capsys.readouterr()
assert "ERROR: failed to parse RequirementParseError" in out
assert not err


@pytest.fixture()
def plugin(monkeypatch, tmp_path):
dest = tmp_path / "a"
shutil.copytree(str(py.path.local(__file__).dirpath().join("plugin")), str(dest))
subprocess.check_output([sys.executable, "setup.py", "egg_info"], cwd=str(dest))
monkeypatch.setenv(str("PYTHONPATH"), str(dest))


def test_provision_cli_args_ignore(cmd, initproj, monkeypatch, plugin):
import tox.config
import tox.session

prev_ensure = tox.config.ParseIni.ensure_requires_satisfied

@staticmethod
def ensure_requires_satisfied(config, requires, min_version):
result = prev_ensure(config, requires, min_version)
config.run_provision = True
return result

monkeypatch.setattr(
tox.config.ParseIni, "ensure_requires_satisfied", ensure_requires_satisfied
)
prev_get_venv = tox.session.Session.getvenv

def getvenv(self, name):
venv = prev_get_venv(self, name)
venv.envconfig.envdir = py.path.local(sys.executable).dirpath().dirpath()
venv.setupenv = lambda: True
venv.finishvenv = lambda: True
return venv

monkeypatch.setattr(tox.session.Session, "getvenv", getvenv)
initproj("test-0.1", {"tox.ini": "[tox]"})
result = cmd("-a", "--option", "b")
result.assert_success(is_run_test_env=False)


def test_provision_cli_args_not_ignored_if_provision_false(cmd, initproj):
initproj("test-0.1", {"tox.ini": "[tox]"})
result = cmd("-a", "--option", "b")
result.assert_fail(is_run_test_env=False)