summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBernát Gábor <bgabor8@bloomberg.net>2021-01-30 11:25:17 +0000
committerGitHub <noreply@github.com>2021-01-30 11:25:17 +0000
commit6d9b2dff59f220f6b3bae1fedcb888fd113bf269 (patch)
tree9e01f09b8f09425e5fe74d20b0e7c233d7a2df9f /src
parent1e4b3cd8891fd42231ced02c6f953209a0a0f5b7 (diff)
downloadtox-git-6d9b2dff59f220f6b3bae1fedcb888fd113bf269.tar.gz
Add support for install_command virtualenv settings (#1886)
Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
Diffstat (limited to 'src')
-rw-r--r--src/tox/config/of_type.py4
-rw-r--r--src/tox/config/sets.py4
-rw-r--r--src/tox/provision.py9
-rw-r--r--src/tox/tox_env/api.py3
-rw-r--r--src/tox/tox_env/python/virtual_env/api.py56
-rw-r--r--src/tox/tox_env/python/virtual_env/runner.py2
6 files changed, 56 insertions, 22 deletions
diff --git a/src/tox/config/of_type.py b/src/tox/config/of_type.py
index ba369e62..3c42dc49 100644
--- a/src/tox/config/of_type.py
+++ b/src/tox/config/of_type.py
@@ -70,7 +70,7 @@ class ConfigDynamicDefinition(ConfigDefinition[T]):
env_name: Optional[str],
of_type: Type[T],
default: Union[Callable[["Config", Optional[str]], T], T],
- post_process: Optional[Callable[[T, "Config"], T]] = None,
+ post_process: Optional[Callable[[T], T]] = None,
kwargs: Optional[Mapping[str, Any]] = None,
) -> None:
super().__init__(keys, desc, env_name)
@@ -96,7 +96,7 @@ class ConfigDynamicDefinition(ConfigDefinition[T]):
else:
value = self.default(conf, self.env_name) if callable(self.default) else self.default
if self.post_process is not None:
- value = self.post_process(value, conf) # noqa
+ value = self.post_process(value) # noqa
self._cache = value
return cast(T, self._cache)
diff --git a/src/tox/config/sets.py b/src/tox/config/sets.py
index 08735f62..6e31a664 100644
--- a/src/tox/config/sets.py
+++ b/src/tox/config/sets.py
@@ -44,7 +44,7 @@ class ConfigSet:
of_type: Type[V],
default: Union[Callable[["Config", Optional[str]], V], V],
desc: str,
- post_process: Optional[Callable[[V, "Config"], V]] = None,
+ post_process: Optional[Callable[[V], V]] = None,
kwargs: Optional[Mapping[str, Any]] = None,
) -> ConfigDynamicDefinition[V]:
"""
@@ -149,7 +149,7 @@ class EnvConfigSet(ConfigSet):
super().__init__(conf, name=name)
self.default_set_env_loader: Callable[[], Mapping[str, str]] = lambda: {}
- def set_env_post_process(values: SetEnv, config: "Config") -> SetEnv:
+ def set_env_post_process(values: SetEnv) -> SetEnv:
values.update_if_not_present(self.default_set_env_loader())
return values
diff --git a/src/tox/provision.py b/src/tox/provision.py
index 2a00acdb..9710a70e 100644
--- a/src/tox/provision.py
+++ b/src/tox/provision.py
@@ -11,8 +11,7 @@ from packaging.utils import canonicalize_name
from packaging.version import Version
from tox.config.loader.memory import MemoryLoader
-from tox.config.main import Config
-from tox.config.sets import ConfigSet
+from tox.config.sets import CoreConfigSet
from tox.execute.api import StdinSource
from tox.plugin.impl import impl
from tox.session.state import State
@@ -45,7 +44,7 @@ def tox_add_option(parser: ArgumentParser) -> None:
@impl
-def tox_add_core_config(core: ConfigSet) -> None:
+def tox_add_core_config(core: CoreConfigSet) -> None:
core.add_config(
keys=["min_version", "minversion"],
of_type=Version,
@@ -60,8 +59,8 @@ def tox_add_core_config(core: ConfigSet) -> None:
desc="Name of the virtual environment used to provision a tox.",
)
- def add_tox_requires_min_version(requires: List[Requirement], conf: Config) -> List[Requirement]:
- min_version: Version = conf.core["min_version"]
+ def add_tox_requires_min_version(requires: List[Requirement]) -> List[Requirement]: # noqa
+ min_version: Version = core["min_version"]
requires.append(Requirement(f"tox >= {min_version.public}"))
return requires
diff --git a/src/tox/tox_env/api.py b/src/tox/tox_env/api.py
index 0555a286..5b9391c7 100644
--- a/src/tox/tox_env/api.py
+++ b/src/tox/tox_env/api.py
@@ -12,7 +12,6 @@ from io import BytesIO
from pathlib import Path
from typing import TYPE_CHECKING, Dict, Iterator, List, Optional, Sequence, Tuple, Union, cast
-from tox.config.main import Config
from tox.config.set_env import SetEnv
from tox.config.sets import CoreConfigSet, EnvConfigSet
from tox.execute.api import Execute, ExecuteStatus, Outcome, StdinSource
@@ -94,7 +93,7 @@ class ToxEnv(ABC):
)
self.conf.default_set_env_loader = self.default_set_env
- def pass_env_post_process(values: List[str], config: Config) -> List[str]:
+ def pass_env_post_process(values: List[str]) -> List[str]:
values.extend(self.default_pass_env())
return sorted(list({k: None for k in values}.keys()))
diff --git a/src/tox/tox_env/python/virtual_env/api.py b/src/tox/tox_env/python/virtual_env/api.py
index 5f4afe98..ac0902cf 100644
--- a/src/tox/tox_env/python/virtual_env/api.py
+++ b/src/tox/tox_env/python/virtual_env/api.py
@@ -12,7 +12,9 @@ from virtualenv.run.session import Session
from tox.config.cli.parser import DEFAULT_VERBOSITY, Parsed
from tox.config.loader.str_convert import StrConvert
+from tox.config.main import Config
from tox.config.sets import CoreConfigSet, EnvConfigSet
+from tox.config.types import Command
from tox.execute.api import Execute, Outcome, StdinSource
from tox.execute.local_sub_process import LocalSubProcessExecutor
from tox.journal import EnvJournal
@@ -66,6 +68,33 @@ class VirtualEnv(Python, ABC):
desc="install the latest available pre-release (alpha/beta/rc) of dependencies without a specified version",
)
+ self.conf.add_config(
+ keys=["install_command"],
+ of_type=Command,
+ default=self.default_install_command,
+ post_process=self.post_process_install_command,
+ desc="install the latest available pre-release (alpha/beta/rc) of dependencies without a specified version",
+ )
+
+ def post_process_install_command(self, cmd: Command) -> Command:
+ install_command = cmd.args
+ pip_pre: bool = self.conf["pip_pre"]
+ try:
+ opts_at = install_command.index("{opts}")
+ except ValueError:
+ if pip_pre:
+ install_command.append("--pre")
+ else:
+ if pip_pre:
+ install_command[opts_at] = "--pre"
+ else:
+ install_command.pop(opts_at)
+ return cmd
+
+ def default_install_command(self, conf: Config, env_name: Optional[str]) -> Command: # noqa
+ cmd = Command(["python", "-I", "-m", "pip", "install", "{opts}", "{packages}"])
+ return self.post_process_install_command(cmd)
+
def setup(self) -> None:
with self._cache.compare({"version": virtualenv_version}, VirtualEnv.__name__) as (eq, old):
if eq is False and old is not None: # if changed create
@@ -153,23 +182,30 @@ class VirtualEnv(Python, ABC):
) -> None:
if not packages:
return
- install_command = self.base_install_cmd
+
+ args: List[str] = []
if no_deps:
- install_command.append("--no-deps")
+ args.append("--no-deps")
if force_reinstall:
- install_command.append("--force-reinstall")
+ args.append("--force-reinstall")
if develop is True:
- install_command.extend(("--no-build-isolation", "-e"))
+ args.extend(("--no-build-isolation", "-e"))
+ args.extend(str(i) for i in packages)
+ install_command = self.build_install_cmd(args)
- install_command.extend(str(i) for i in packages)
result = self.perform_install(install_command, f"install_{of_type}")
result.assert_success()
- @property
- def base_install_cmd(self) -> List[str]:
- result = [str(self.creator.exe), "-I", "-m", "pip", "install"]
- if self.conf["pip_pre"]:
- result.append("--pre")
+ def build_install_cmd(self, args: Sequence[str]) -> List[str]:
+ cmd: Command = self.conf["install_command"]
+ install_command = cmd.args
+ try:
+ opts_at = install_command.index("{packages}")
+ except ValueError:
+ opts_at = len(install_command)
+ result = install_command[:opts_at]
+ result.extend(args)
+ result.extend(install_command[opts_at + 1 :])
return result
def perform_install(self, install_command: Sequence[str], run_id: str) -> Outcome:
diff --git a/src/tox/tox_env/python/virtual_env/runner.py b/src/tox/tox_env/python/virtual_env/runner.py
index d724aae7..ed712ce3 100644
--- a/src/tox/tox_env/python/virtual_env/runner.py
+++ b/src/tox/tox_env/python/virtual_env/runner.py
@@ -121,7 +121,7 @@ class VirtualEnvRunner(VirtualEnv, PythonRun):
}
def install_requirement_file(self, path: Path) -> None:
- install_command = self.base_install_cmd + ["-r", str(path)]
+ install_command = self.build_install_cmd(["-r", str(path)])
result = self.perform_install(install_command, "install_deps")
result.assert_success()