diff options
author | Bruno Oliveira <nicoddemus@gmail.com> | 2013-11-21 20:15:14 -0200 |
---|---|---|
committer | Bruno Oliveira <nicoddemus@gmail.com> | 2013-11-21 20:15:14 -0200 |
commit | 8f1b64a35a51a81ee85f65d3a6776297169e135b (patch) | |
tree | ff09470b80dbaeed8b492d87ff4152305f0fce42 | |
parent | e20548ba593c3726a93ac46d885d96eca4c77fce (diff) | |
download | tox-8f1b64a35a51a81ee85f65d3a6776297169e135b.tar.gz |
Added --force-dep-version command-line option
-rw-r--r-- | CONTRIBUTORS | 1 | ||||
-rw-r--r-- | tests/test_config.py | 59 | ||||
-rw-r--r-- | tox/_config.py | 31 |
3 files changed, 89 insertions, 2 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index c65d497..9d8784a 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -11,3 +11,4 @@ Ronny Pfannschmidt Lukasz Balcerzak Philip Thiem Monty Taylor +Bruno Oliveira diff --git a/tests/test_config.py b/tests/test_config.py index f07f191..517ec29 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -62,6 +62,41 @@ class TestVenvConfig: envconfig = config.envconfigs['devenv'] assert envconfig.envdir == config.toxworkdir.join('foobar') + def test_force_dep_version(self, initproj): + """ + Make sure we can override dependencies configured in tox.ini when using the command line option + --force-dep-version. + """ + initproj("example123-0.5", filedefs={ + 'tox.ini': ''' + [tox] + + [testenv] + deps= + dep1==1.0 + dep2>=2.0 + dep3 + dep4==4.0 + ''' + }) + config = parseconfig( + ['--force-dep-version=dep1==1.5', '--force-dep-version=dep2==2.1', '--force-dep-version=dep3==3.0']) + assert config.option.force_dep_version == ['dep1==1.5', 'dep2==2.1', 'dep3==3.0'] + assert [str(x) for x in config.envconfigs['python'].deps] == [ + 'dep1==1.5', 'dep2==2.1', 'dep3==3.0', 'dep4==4.0', + ] + + def test_is_same_dep(self): + """ + Ensure correct parseini._is_same_dep is working with a few samples. + """ + assert parseini._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3') + assert parseini._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3>=2.0') + assert parseini._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3>2.0') + assert parseini._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3<2.0') + assert parseini._is_same_dep('pkg_hello-world3==1.0', 'pkg_hello-world3<=2.0') + assert not parseini._is_same_dep('pkg_hello-world3==1.0', 'otherpkg>=2.0') + class TestConfigPackage: def test_defaults(self, tmpdir, newconfig): config = newconfig([], "") @@ -1142,6 +1177,28 @@ class TestCmdInvocation: "*ERROR*tox.ini*not*found*", ]) + def test_showconfig_with_force_dep_version(self, cmd, initproj): + initproj('force_dep_version', filedefs={ + 'tox.ini': ''' + [tox] + + [testenv] + deps= + dep1==2.3 + dep2 + ''', + }) + result = cmd.run("tox", "--showconfig") + assert result.ret == 0 + result.stdout.fnmatch_lines([ + r'*deps=*dep1==2.3, dep2*', + ]) + # override dep1 specific version, and force version for dep2 + result = cmd.run("tox", "--showconfig", "--force-dep-version=dep1", "--force-dep-version=dep2==5.0") + assert result.ret == 0 + result.stdout.fnmatch_lines([ + r'*deps=*dep1, dep2==5.0*', + ]) class TestArgumentParser: @@ -1229,5 +1286,3 @@ class TestCommandParser: """) envconfig = config.envconfigs["py26"] assert envconfig.commands[0] == ["some", r"hello\world"] - - diff --git a/tox/_config.py b/tox/_config.py index e1cc966..0348080 100644 --- a/tox/_config.py +++ b/tox/_config.py @@ -8,6 +8,7 @@ import shlex import string import subprocess import textwrap +import pkg_resources from tox.interpreters import Interpreters @@ -124,6 +125,10 @@ def prepare_parse(pkgname): help="set PYTHONHASHSEED to SEED before running commands. " "Defaults to a random integer in the range 1 to 4294967295. " "Passing 'noset' suppresses this behavior.") + parser.add_argument("--force-dep-version", action="append", + metavar="DEP==VER", default=None, + help="Forces a certain version of one of the dependencies " + "when configuring the virtual environment.") parser.add_argument("args", nargs="*", help="additional arguments available to command positional substitution") return parser @@ -343,6 +348,7 @@ class parseini: else: name = depline.strip() ixserver = None + name = self._replace_forced_dep(name, config) vc.deps.append(DepConfig(name, ixserver)) vc.distribute = reader.getbool(section, "distribute", False) vc.sitepackages = reader.getbool(section, "sitepackages", False) @@ -385,6 +391,31 @@ class parseini: envlist.sort() return envlist + def _replace_forced_dep(self, name, config): + """ + Override the given dependency config name taking --force-dep-version + option into account. + + :param name: dep config, for example ["pkg==1.0", "other==2.0"]. + :param config: Config instance + :return: the new dependency that should be used for virtual environments + """ + if not config.option.force_dep_version: + return name + for forced_dep in config.option.force_dep_version: + if self._is_same_dep(forced_dep, name): + return forced_dep + return name + + @classmethod + def _is_same_dep(cls, dep1, dep2): + """ + Returns True if both dependency definitions refer to the same package, even if versions differ. + """ + dep1_name = pkg_resources.Requirement.parse(dep1).project_name + dep2_name = pkg_resources.Requirement.parse(dep2).project_name + return dep1_name == dep2_name + def _split_env(env): """if handed a list, action="append" was used for -e """ envlist = [] |