#47 F33: Backport provision related changes needed for future pyproject-rpm-macros changes
Closed 3 years ago by churchyard. Opened 3 years ago by churchyard.
rpms/ churchyard/python-tox f33-backports  into  f33

@@ -0,0 +1,235 @@ 

+ diff --git a/src/tox/config/__init__.py b/src/tox/config/__init__.py

+ index c21222c..93805ba 100644

+ --- a/src/tox/config/__init__.py

+ +++ b/src/tox/config/__init__.py

+ @@ -2,6 +2,7 @@ from __future__ import print_function

+  

+  import argparse

+  import itertools

+ +import json

+  import os

+  import random

+  import re

+ @@ -538,6 +539,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")

+ @@ -1234,11 +1245,11 @@ class ParseIni(object):

+              feedback("--devenv requires only a single -e", sysexit=True)

+  

+      def handle_provision(self, config, reader):

+ -        requires_list = reader.getlist("requires")

+ +        config.requires = reader.getlist("requires")

+          config.minversion = reader.getstring("minversion", None)

+          config.provision_tox_env = name = reader.getstring("provision_tox_env", ".tox")

+          min_version = "tox >= {}".format(config.minversion or tox.__version__)

+ -        deps = self.ensure_requires_satisfied(config, requires_list, min_version)

+ +        deps = self.ensure_requires_satisfied(config, config.requires, min_version)

+          if config.run_provision:

+              section_name = "testenv:{}".format(name)

+              if section_name not in self._cfg.sections:

+ @@ -1254,8 +1265,8 @@ class ParseIni(object):

+          # 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 = []

+ @@ -1282,12 +1293,33 @@ class ParseIni(object):

+                  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,

+ +        }

+ +        try:

+ +            with open(config.option.no_provision, "w", encoding="utf-8") as outfile:

+ +                json.dump(requires_dict, outfile, indent=4)

+ +        except TypeError:  # Python 2

+ +            with open(config.option.no_provision, "w") as outfile:

+ +                json.dump(requires_dict, outfile, indent=4, encoding="utf-8")

+ +

+      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")

+ diff --git a/tests/unit/session/test_provision.py b/tests/unit/session/test_provision.py

+ index aa631c0..710df60 100644

+ --- a/tests/unit/session/test_provision.py

+ +++ b/tests/unit/session/test_provision.py

+ @@ -1,5 +1,6 @@

+  from __future__ import absolute_import, unicode_literals

+  

+ +import json

+  import os

+  import shutil

+  import subprocess

+ @@ -42,6 +43,35 @@ def test_provision_min_version_is_requires(newconfig, next_tox_major):

+      assert config.ignore_basepython_conflict is False

+  

+  

+ +def test_provision_config_has_minversion_and_requires(newconfig, next_tox_major):

+ +    with pytest.raises(MissingRequirement) as context:

+ +        newconfig(

+ +            [],

+ +            """\

+ +            [tox]

+ +            minversion = {}

+ +            requires =

+ +                setuptools > 2

+ +                pip > 3

+ +            """.format(

+ +                next_tox_major,

+ +            ),

+ +        )

+ +    config = context.value.config

+ +

+ +    assert config.run_provision is True

+ +    assert config.minversion == next_tox_major

+ +    assert config.requires == ["setuptools > 2", "pip > 3"]

+ +

+ +

+ +def test_provision_config_empty_minversion_and_requires(newconfig, next_tox_major):

+ +    config = newconfig([], "")

+ +

+ +    assert config.run_provision is False

+ +    assert config.minversion is None

+ +    assert config.requires == []

+ +

+ +

+  def test_provision_tox_change_name(newconfig):

+      config = newconfig(

+          [],

+ @@ -149,6 +179,99 @@ def test_provision_cli_args_not_ignored_if_provision_false(cmd, initproj):

+      result.assert_fail(is_run_test_env=False)

+  

+  

+ +parametrize_json_path = pytest.mark.parametrize("json_path", [None, "missing.json"])

+ +

+ +

+ +@parametrize_json_path

+ +def test_provision_does_not_fail_with_no_provision_no_reason(cmd, initproj, json_path):

+ +    p = initproj("test-0.1", {"tox.ini": "[tox]"})

+ +    result = cmd("--no-provision", *([json_path] if json_path else []))

+ +    result.assert_success(is_run_test_env=True)

+ +    assert not (p / "missing.json").exists()

+ +

+ +

+ +@parametrize_json_path

+ +def test_provision_fails_with_no_provision_next_tox(cmd, initproj, next_tox_major, json_path):

+ +    p = initproj(

+ +        "test-0.1",

+ +        {

+ +            "tox.ini": """\

+ +                             [tox]

+ +                             minversion = {}

+ +                             """.format(

+ +                next_tox_major,

+ +            )

+ +        },

+ +    )

+ +    result = cmd("--no-provision", *([json_path] if json_path else []))

+ +    result.assert_fail(is_run_test_env=False)

+ +    if json_path:

+ +        missing = json.loads((p / json_path).read_text("utf-8"))

+ +        assert missing["minversion"] == next_tox_major

+ +

+ +

+ +@parametrize_json_path

+ +def test_provision_fails_with_no_provision_missing_requires(cmd, initproj, json_path):

+ +    p = initproj(

+ +        "test-0.1",

+ +        {

+ +            "tox.ini": """\

+ +                             [tox]

+ +                             requires =

+ +                                 virtualenv > 99999999

+ +                             """

+ +        },

+ +    )

+ +    result = cmd("--no-provision", *([json_path] if json_path else []))

+ +    result.assert_fail(is_run_test_env=False)

+ +    if json_path:

+ +        missing = json.loads((p / json_path).read_text("utf-8"))

+ +        assert missing["requires"] == ["virtualenv > 99999999"]

+ +

+ +

+ +@parametrize_json_path

+ +def test_provision_does_not_fail_with_satisfied_requires(cmd, initproj, next_tox_major, json_path):

+ +    p = initproj(

+ +        "test-0.1",

+ +        {

+ +            "tox.ini": """\

+ +                             [tox]

+ +                             minversion = 0

+ +                             requires =

+ +                                 setuptools > 2

+ +                                 pip > 3

+ +                             """

+ +        },

+ +    )

+ +    result = cmd("--no-provision", *([json_path] if json_path else []))

+ +    result.assert_success(is_run_test_env=True)

+ +    assert not (p / "missing.json").exists()

+ +

+ +

+ +@parametrize_json_path

+ +def test_provision_fails_with_no_provision_combined(cmd, initproj, next_tox_major, json_path):

+ +    p = initproj(

+ +        "test-0.1",

+ +        {

+ +            "tox.ini": """\

+ +                             [tox]

+ +                             minversion = {}

+ +                             requires =

+ +                                 setuptools > 2

+ +                                 pip > 3

+ +                             """.format(

+ +                next_tox_major,

+ +            )

+ +        },

+ +    )

+ +    result = cmd("--no-provision", *([json_path] if json_path else []))

+ +    result.assert_fail(is_run_test_env=False)

+ +    if json_path:

+ +        missing = json.loads((p / json_path).read_text("utf-8"))

+ +        assert missing["minversion"] == next_tox_major

+ +        assert missing["requires"] == ["setuptools > 2", "pip > 3"]

+ +

+ +

+  @pytest.fixture(scope="session")

+  def wheel(tmp_path_factory):

+      """create a wheel for a project"""

file modified
+11 -1
@@ -15,13 +15,19 @@ 

  %global pypi_name tox

  Name:           python-%{pypi_name}

  Version:        3.19.0

- Release:        1%{?dist}

+ Release:        2%{?dist}

  Summary:        Virtualenv-based automation of test activities

  

  License:        MIT

  URL:            https://tox.readthedocs.io/

  Source0:        %{pypi_source}

  

+ # Expose tox requires via the config object

+ # https://github.com/tox-dev/tox/pull/1919

+ # Add --no-provision flag

+ # https://github.com/tox-dev/tox/pull/1922

+ Patch1:         provision-backports.patch

+ 

  BuildArch:      noarch

  

  %description
@@ -137,6 +143,10 @@ 

  %{python3_sitelib}/%{pypi_name}-%{version}-py%{python3_version}.egg-info/

  

  %changelog

+ * Thu Mar 18 2021 Miro Hrončok <mhroncok@redhat.com> - 3.19.0-2

+ - Expose tox requires via the config object

+ - Add --no-provision flag

+ 

  * Fri Aug 07 2020 Miro Hrončok <mhroncok@redhat.com> - 3.19.0-1

  - Update to 3.19.0

  - Fixes rhbz#1861313

Pull-Request has been closed by churchyard

3 years ago