Skip to content

Commit

Permalink
Add --no-provision flag
Browse files Browse the repository at this point in the history
tox can now be invoked with a new --no-provision flag that prevents provision,
if requires or minversion are not satisfied, tox will fail;
if a path is specified as an argument to the flag
(e.g. as `tox --no-provision missing.json`) and provision is prevented,
provision metadata are written as JSON to that path.

Fixes #1921
  • Loading branch information
hroncok committed Mar 2, 2021
1 parent a586b2a commit ab293cf
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
6 changes: 6 additions & 0 deletions docs/changelog/1921.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
tox can now be invoked with a new ``--no-provision`` flag that prevents provision,
if :conf:`requires` or :conf:`minversion` are not satisfied,
tox will fail;
if a path is specified as an argument to the flag
(e.g. as ``tox --no-provision missing.json``) and provision is prevented,
provision metadata are written as JSON to that path - by :user:`hroncok`
15 changes: 15 additions & 0 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ Global settings are defined under the ``tox`` section as:
than this the tool will create an environment and provision it with a version of
tox that satisfies this under :conf:`provision_tox_env`.

.. versionchanged:: 3.23.0

When tox is invoked with the ``--no-provision`` flag,
the provision won't be attempted, tox will fail instead.

.. conf:: requires ^ LIST of PEP-508

.. versionadded:: 3.2.0
Expand All @@ -54,13 +59,23 @@ Global settings are defined under the ``tox`` section as:
requires = tox-pipenv
setuptools >= 30.0.0
.. versionchanged:: 3.23.0

When tox is invoked with the ``--no-provision`` flag,
the provision won't be attempted, tox will fail instead.

.. conf:: provision_tox_env ^ string ^ .tox

.. versionadded:: 3.8.0

Name of the virtual environment used to provision a tox having all dependencies specified
inside :conf:`requires` and :conf:`minversion`.

.. versionchanged:: 3.23.0

When tox is invoked with the ``--no-provision`` flag,
the provision won't be attempted, tox will fail instead.

.. conf:: toxworkdir ^ PATH ^ {toxinidir}/.tox

Directory for tox to generate its environments into, will be created if it does not exist.
Expand Down
32 changes: 30 additions & 2 deletions src/tox/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import argparse
import itertools
import json
import os
import random
import re
Expand Down Expand Up @@ -572,6 +573,16 @@ def tox_addoption(parser):
action="store_true",
help="override alwayscopy setting to True in all envs",
)
parser.add_argument(
"--no-provision",
action="store",
nargs="?",
default=False,
const=True,
metavar="REQUIRES_JSON",
help="do not perform provision, but fail and if a path was provided "
"write provision metadata as JSON to it",
)

cli_skip_missing_interpreter(parser)
parser.add_argument("--workdir", metavar="PATH", help="tox working directory")
Expand Down Expand Up @@ -1318,8 +1329,8 @@ def handle_provision(self, config, reader):
# raise on unknown args
self.config._parser.parse_cli(args=self.config.args, strict=True)

@staticmethod
def ensure_requires_satisfied(config, requires, min_version):
@classmethod
def ensure_requires_satisfied(cls, config, requires, min_version):
missing_requirements = []
failed_to_parse = False
deps = []
Expand All @@ -1346,12 +1357,29 @@ def ensure_requires_satisfied(config, requires, min_version):
missing_requirements.append(str(requirements.Requirement(require)))
if failed_to_parse:
raise tox.exception.BadRequirement()
if config.option.no_provision and missing_requirements:
msg = "provisioning explicitly disabled within {}, but missing {}"
if config.option.no_provision is not True: # it's a path
msg += " and wrote to {}"
cls.write_requires_to_json_file(config)
raise tox.exception.Error(
msg.format(sys.executable, missing_requirements, config.option.no_provision)
)
if WITHIN_PROVISION and missing_requirements:
msg = "break infinite loop provisioning within {} missing {}"
raise tox.exception.Error(msg.format(sys.executable, missing_requirements))
config.run_provision = bool(len(missing_requirements))
return deps

@staticmethod
def write_requires_to_json_file(config):
requires_dict = {
"minversion": config.minversion,
"requires": config.requires,
}
with open(config.option.no_provision, "w", encoding="utf-8") as outfile:
json.dump(requires_dict, outfile, indent=4)

def parse_build_isolation(self, config, reader):
config.isolated_build = reader.getbool("isolated_build", False)
config.isolated_build_env = reader.getstring("isolated_build_env", ".package")
Expand Down

0 comments on commit ab293cf

Please sign in to comment.