Commit f0408d61 by Arun Babu Neelicattu

env: default to enabling pip/wheels/setuptools

For project virtual environments, default to enabling pip, setuptools
and wheel packages to retain existing stable behaviour to prevent
unexpected breakages caused by development environments making
assumptions of base package availability in virtual environments.

Poetry itself does not require the use of these packages and will
execute correctly within environments that do not have these packages.

This change retains the ability to manage these packages as direct
project dependency as introduced in #2826. All poetry internal
execution of pip is retaining the use of the wheel embedded within
the virtualenv package used by poetry.

In cases where a one of these reserved packages are being managed as a
project dependency, the will be treated as any other project
dependency. Executing `poetry install --remove-untracked` will not
remove any of these reserved packages. However, `poetry add pip` and
`poetry remove pip` will trigger the update and removal of `pip`
respectively.

Relates-to: #2826
Relates-to: #3916
parent 3dceee38
...@@ -63,10 +63,31 @@ class Solver: ...@@ -63,10 +63,31 @@ class Solver:
self._overrides = [] self._overrides = []
self._remove_untracked = remove_untracked self._remove_untracked = remove_untracked
self._preserved_package_names = None
@property @property
def provider(self) -> Provider: def provider(self) -> Provider:
return self._provider return self._provider
@property
def preserved_package_names(self):
if self._preserved_package_names is None:
self._preserved_package_names = {
self._package.name,
*Provider.UNSAFE_PACKAGES,
}
deps = {package.name for package in self._locked.packages}
# preserve pip/setuptools/wheel when not managed by poetry, this is so
# to avoid externally managed virtual environments causing unnecessary
# removals.
for name in {"pip", "wheel", "setuptools"}:
if name not in deps:
self._preserved_package_names.add(name)
return self._preserved_package_names
@contextmanager @contextmanager
def use_environment(self, env: Env) -> None: def use_environment(self, env: Env) -> None:
with self.provider.use_environment(env): with self.provider.use_environment(env):
...@@ -190,11 +211,9 @@ class Solver: ...@@ -190,11 +211,9 @@ class Solver:
locked_names = {locked.name for locked in self._locked.packages} locked_names = {locked.name for locked in self._locked.packages}
for installed in self._installed.packages: for installed in self._installed.packages:
if installed.name == self._package.name: if installed.name in self.preserved_package_names:
continue
if installed.name in Provider.UNSAFE_PACKAGES:
# Never remove pip, setuptools etc.
continue continue
if installed.name not in locked_names: if installed.name not in locked_names:
operations.append(Uninstall(installed)) operations.append(Uninstall(installed))
......
...@@ -877,13 +877,8 @@ class EnvManager: ...@@ -877,13 +877,8 @@ class EnvManager:
io.write_line( io.write_line(
"Creating virtualenv <c1>{}</> in {}".format(name, str(venv_path)) "Creating virtualenv <c1>{}</> in {}".format(name, str(venv_path))
) )
self.build_venv(
venv,
executable=executable,
flags=self._poetry.config.get("virtualenvs.options"),
)
else: else:
create_venv = False
if force: if force:
if not env.is_sane(): if not env.is_sane():
io.write_line( io.write_line(
...@@ -895,13 +890,22 @@ class EnvManager: ...@@ -895,13 +890,22 @@ class EnvManager:
"Recreating virtualenv <c1>{}</> in {}".format(name, str(venv)) "Recreating virtualenv <c1>{}</> in {}".format(name, str(venv))
) )
self.remove_venv(venv) self.remove_venv(venv)
create_venv = True
elif io.is_very_verbose():
io.write_line(f"Virtualenv <c1>{name}</> already exists.")
if create_venv:
self.build_venv( self.build_venv(
venv, venv,
executable=executable, executable=executable,
flags=self._poetry.config.get("virtualenvs.options"), flags=self._poetry.config.get("virtualenvs.options"),
# TODO: in a future version switch remove pip/setuptools/wheel
# poetry does not need them these exists today to not break developer
# environment assumptions
with_pip=True,
with_setuptools=True,
with_wheel=True,
) )
elif io.is_very_verbose():
io.write_line(f"Virtualenv <c1>{name}</> already exists.")
# venv detection: # venv detection:
# stdlib venv may symlink sys.executable, so we can't use realpath. # stdlib venv may symlink sys.executable, so we can't use realpath.
...@@ -927,12 +931,29 @@ class EnvManager: ...@@ -927,12 +931,29 @@ class EnvManager:
path: Union[Path, str], path: Union[Path, str],
executable: Optional[Union[str, Path]] = None, executable: Optional[Union[str, Path]] = None,
flags: Dict[str, bool] = None, flags: Dict[str, bool] = None,
with_pip: bool = False, with_pip: Optional[bool] = None,
with_wheel: Optional[bool] = None, with_wheel: Optional[bool] = None,
with_setuptools: Optional[bool] = None, with_setuptools: Optional[bool] = None,
) -> virtualenv.run.session.Session: ) -> virtualenv.run.session.Session:
flags = flags or {} flags = flags or {}
flags["no-pip"] = (
not with_pip if with_pip is not None else flags.pop("no-pip", True)
)
flags["no-setuptools"] = (
not with_setuptools
if with_setuptools is not None
else flags.pop("no-setuptools", True)
)
# we want wheels to be enabled when pip is required and it has not been explicitly disabled
flags["no-wheel"] = (
not with_wheel
if with_wheel is not None
else flags.pop("no-wheel", flags["no-pip"])
)
if isinstance(executable, Path): if isinstance(executable, Path):
executable = executable.resolve().as_posix() executable = executable.resolve().as_posix()
...@@ -943,20 +964,6 @@ class EnvManager: ...@@ -943,20 +964,6 @@ class EnvManager:
executable or sys.executable, executable or sys.executable,
] ]
if not with_pip:
args.append("--no-pip")
else:
if with_wheel is None:
# we want wheels to be enabled when pip is required and it has
# not been explicitly disabled
with_wheel = True
if with_wheel is None or not with_wheel:
args.append("--no-wheel")
if with_setuptools is None or not with_setuptools:
args.append("--no-setuptools")
for flag, value in flags.items(): for flag, value in flags.items():
if value is True: if value is True:
args.append(f"--{flag}") args.append(f"--{flag}")
...@@ -1039,6 +1046,8 @@ class Env: ...@@ -1039,6 +1046,8 @@ class Env:
self._platlib = None self._platlib = None
self._script_dirs = None self._script_dirs = None
self._embedded_pip_path = None
@property @property
def path(self) -> Path: def path(self) -> Path:
return self._path return self._path
...@@ -1075,6 +1084,12 @@ class Env: ...@@ -1075,6 +1084,12 @@ class Env:
).path ).path
@property @property
def pip_embedded(self) -> str:
if self._embedded_pip_path is None:
self._embedded_pip_path = str(self.get_embedded_wheel("pip") / "pip")
return self._embedded_pip_path
@property
def pip(self) -> str: def pip(self) -> str:
""" """
Path to current pip executable Path to current pip executable
...@@ -1082,7 +1097,7 @@ class Env: ...@@ -1082,7 +1097,7 @@ class Env:
# we do not use as_posix() here due to issues with windows pathlib2 implementation # we do not use as_posix() here due to issues with windows pathlib2 implementation
path = self._bin("pip") path = self._bin("pip")
if not Path(path).exists(): if not Path(path).exists():
return str(self.get_embedded_wheel("pip") / "pip") return str(self.pip_embedded)
return path return path
@property @property
...@@ -1187,7 +1202,7 @@ class Env: ...@@ -1187,7 +1202,7 @@ class Env:
def get_marker_env(self) -> Dict[str, Any]: def get_marker_env(self) -> Dict[str, Any]:
raise NotImplementedError() raise NotImplementedError()
def get_pip_command(self) -> List[str]: def get_pip_command(self, embedded: bool = False) -> List[str]:
raise NotImplementedError() raise NotImplementedError()
def get_supported_tags(self) -> List[Tag]: def get_supported_tags(self) -> List[Tag]:
...@@ -1208,16 +1223,20 @@ class Env: ...@@ -1208,16 +1223,20 @@ class Env:
""" """
return True return True
def run(self, bin: str, *args: str, **kwargs: Any) -> Union[str, int]: def get_command_from_bin(self, bin: str) -> List[str]:
if bin == "pip": if bin == "pip":
return self.run_pip(*args, **kwargs) # when pip is required we need to ensure that we fallback to
# embedded pip when pip is not available in the environment
return self.get_pip_command()
return [self._bin(bin)]
bin = self._bin(bin) def run(self, bin: str, *args: str, **kwargs: Any) -> Union[str, int]:
cmd = [bin] + list(args) cmd = self.get_command_from_bin(bin) + list(args)
return self._run(cmd, **kwargs) return self._run(cmd, **kwargs)
def run_pip(self, *args: str, **kwargs: Any) -> Union[int, str]: def run_pip(self, *args: str, **kwargs: Any) -> Union[int, str]:
pip = self.get_pip_command() pip = self.get_pip_command(embedded=True)
cmd = pip + list(args) cmd = pip + list(args)
return self._run(cmd, **kwargs) return self._run(cmd, **kwargs)
...@@ -1260,17 +1279,13 @@ class Env: ...@@ -1260,17 +1279,13 @@ class Env:
return decode(output) return decode(output)
def execute(self, bin: str, *args: str, **kwargs: Any) -> Optional[int]: def execute(self, bin: str, *args: str, **kwargs: Any) -> Optional[int]:
if bin == "pip": command = self.get_command_from_bin(bin) + list(args)
return self.run_pip(*args, **kwargs)
bin = self._bin(bin)
env = kwargs.pop("env", {k: v for k, v in os.environ.items()}) env = kwargs.pop("env", {k: v for k, v in os.environ.items()})
if not self._is_windows: if not self._is_windows:
args = [bin] + list(args) return os.execvpe(command[0], command, env=env)
return os.execvpe(bin, args, env=env)
else: else:
exe = subprocess.Popen([bin] + list(args), env=env, **kwargs) exe = subprocess.Popen([command[0]] + command[1:], env=env, **kwargs)
exe.communicate() exe.communicate()
return exe.returncode return exe.returncode
...@@ -1338,10 +1353,10 @@ class SystemEnv(Env): ...@@ -1338,10 +1353,10 @@ class SystemEnv(Env):
def get_python_implementation(self) -> str: def get_python_implementation(self) -> str:
return platform.python_implementation() return platform.python_implementation()
def get_pip_command(self) -> List[str]: def get_pip_command(self, embedded: bool = False) -> List[str]:
# If we're not in a venv, assume the interpreter we're running on # If we're not in a venv, assume the interpreter we're running on
# has a pip and use that # has a pip and use that
return [sys.executable, self.pip] return [sys.executable, self.pip_embedded if embedded else self.pip]
def get_paths(self) -> Dict[str, str]: def get_paths(self) -> Dict[str, str]:
# We can't use sysconfig.get_paths() because # We can't use sysconfig.get_paths() because
...@@ -1445,10 +1460,10 @@ class VirtualEnv(Env): ...@@ -1445,10 +1460,10 @@ class VirtualEnv(Env):
def get_python_implementation(self) -> str: def get_python_implementation(self) -> str:
return self.marker_env["platform_python_implementation"] return self.marker_env["platform_python_implementation"]
def get_pip_command(self) -> List[str]: def get_pip_command(self, embedded: bool = False) -> List[str]:
# We're in a virtualenv that is known to be sane, # We're in a virtualenv that is known to be sane,
# so assume that we have a functional pip # so assume that we have a functional pip
return [self._bin("python"), self.pip] return [self._bin("python"), self.pip_embedded if embedded else self.pip]
def get_supported_tags(self) -> List[Tag]: def get_supported_tags(self) -> List[Tag]:
file_path = Path(packaging.tags.__file__) file_path = Path(packaging.tags.__file__)
...@@ -1560,8 +1575,8 @@ class NullEnv(SystemEnv): ...@@ -1560,8 +1575,8 @@ class NullEnv(SystemEnv):
self._execute = execute self._execute = execute
self.executed = [] self.executed = []
def get_pip_command(self) -> List[str]: def get_pip_command(self, embedded: bool = False) -> List[str]:
return [self._bin("python"), self.pip] return [self._bin("python"), self.pip_embedded if embedded else self.pip]
def _run(self, cmd: List[str], **kwargs: Any) -> int: def _run(self, cmd: List[str], **kwargs: Any) -> int:
self.executed.append(cmd) self.executed.append(cmd)
......
...@@ -53,7 +53,7 @@ def pip_install( ...@@ -53,7 +53,7 @@ def pip_install(
executable=environment.python, with_pip=True, with_setuptools=True executable=environment.python, with_pip=True, with_setuptools=True
) as env: ) as env:
return environment.run( return environment.run(
env._bin("pip"), *env.get_pip_command(),
*args, *args,
env={**os.environ, "PYTHONPATH": str(env.purelib)}, env={**os.environ, "PYTHONPATH": str(env.purelib)},
) )
......
...@@ -55,6 +55,9 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( ...@@ -55,6 +55,9 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file(
venv_py37, venv_py37,
executable="python3.7", executable="python3.7",
flags={"always-copy": False, "system-site-packages": False}, flags={"always-copy": False, "system-site-packages": False},
with_pip=True,
with_setuptools=True,
with_wheel=True,
) )
envs_file = TOMLFile(venv_cache / "envs.toml") envs_file = TOMLFile(venv_cache / "envs.toml")
......
...@@ -217,7 +217,7 @@ def test_info_setup_missing_mandatory_should_trigger_pep517( ...@@ -217,7 +217,7 @@ def test_info_setup_missing_mandatory_should_trigger_pep517(
except PackageInfoError: except PackageInfoError:
assert spy.call_count == 3 assert spy.call_count == 3
else: else:
assert spy.call_count == 1 assert spy.call_count == 2
def test_info_prefer_poetry_config_over_egg_info(): def test_info_prefer_poetry_config_over_egg_info():
......
from __future__ import unicode_literals from __future__ import unicode_literals
import itertools
import json import json
import sys import sys
...@@ -35,6 +36,9 @@ from tests.repositories.test_legacy_repository import ( ...@@ -35,6 +36,9 @@ from tests.repositories.test_legacy_repository import (
from tests.repositories.test_pypi_repository import MockRepository from tests.repositories.test_pypi_repository import MockRepository
RESERVED_PACKAGES = ("pip", "setuptools", "wheel")
class Installer(BaseInstaller): class Installer(BaseInstaller):
def _get_installer(self): def _get_installer(self):
return NoopInstaller() return NoopInstaller()
...@@ -367,59 +371,88 @@ def test_run_install_no_dev_and_dev_only(installer, locker, repo, package, insta ...@@ -367,59 +371,88 @@ def test_run_install_no_dev_and_dev_only(installer, locker, repo, package, insta
assert 1 == installer.executor.removals_count assert 1 == installer.executor.removals_count
def test_run_install_remove_untracked(installer, locker, repo, package, installed): @pytest.mark.parametrize(
"managed_reserved_package_names",
[
i
for i in itertools.chain(
[tuple()],
itertools.permutations(RESERVED_PACKAGES, 1),
itertools.permutations(RESERVED_PACKAGES, 2),
[RESERVED_PACKAGES],
)
],
)
def test_run_install_remove_untracked(
managed_reserved_package_names, installer, locker, repo, package, installed
):
package_a = get_package("a", "1.0")
package_b = get_package("b", "1.1")
package_c = get_package("c", "1.2")
package_pip = get_package("pip", "20.0.0")
package_setuptools = get_package("setuptools", "20.0.0")
package_wheel = get_package("wheel", "20.0.0")
all_packages = [
package_a,
package_b,
package_c,
package_pip,
package_setuptools,
package_wheel,
]
managed_reserved_packages = [
pkg for pkg in all_packages if pkg.name in managed_reserved_package_names
]
locked_packages = [package_a, *managed_reserved_packages]
for pkg in all_packages:
repo.add_package(pkg)
installed.add_package(pkg)
installed.add_package(package) # Root package never removed.
package.add_dependency(Factory.create_dependency(package_a.name, package_a.version))
locker.locked(True) locker.locked(True)
locker.mock_lock_data( locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
"name": "a", "name": pkg.name,
"version": "1.0", "version": pkg.version,
"category": "main", "category": "main",
"optional": False, "optional": False,
"platform": "*", "platform": "*",
"python-versions": "*", "python-versions": "*",
"checksum": [], "checksum": [],
} }
for pkg in locked_packages
], ],
"metadata": { "metadata": {
"python-versions": "*", "python-versions": "*",
"platform": "*", "platform": "*",
"content-hash": "123456789", "content-hash": "123456789",
"hashes": {"a": []}, "hashes": {pkg.name: [] for pkg in locked_packages},
}, },
} }
) )
package_a = get_package("a", "1.0")
package_b = get_package("b", "1.1")
package_c = get_package("c", "1.2")
package_pip = get_package("pip", "20.0.0")
package_setuptools = get_package("setuptools", "20.0.0")
repo.add_package(package_a)
repo.add_package(package_b)
repo.add_package(package_c)
repo.add_package(package_pip)
repo.add_package(package_setuptools)
installed.add_package(package_a)
installed.add_package(package_b)
installed.add_package(package_c)
installed.add_package(package_pip)
installed.add_package(package_setuptools)
installed.add_package(package) # Root package never removed.
package.add_dependency(Factory.create_dependency("A", "~1.0"))
installer.dev_mode(True).remove_untracked(True) installer.dev_mode(True).remove_untracked(True)
installer.run() installer.run()
assert 0 == installer.executor.installations_count assert 0 == installer.executor.installations_count
assert 0 == installer.executor.updates_count assert 0 == installer.executor.updates_count
assert 4 == installer.executor.removals_count assert 2 + len(managed_reserved_packages) == installer.executor.removals_count
assert {"b", "c", "pip", "setuptools"} == set(
r.name for r in installer.executor.removals expected_removals = {
) package_b.name,
package_c.name,
*managed_reserved_package_names,
}
assert expected_removals == set(r.name for r in installer.executor.removals)
def test_run_whitelist_add(installer, locker, repo, package): def test_run_whitelist_add(installer, locker, repo, package):
......
from __future__ import unicode_literals from __future__ import unicode_literals
import itertools
import sys import sys
from pathlib import Path from pathlib import Path
...@@ -28,6 +29,9 @@ from tests.repositories.test_legacy_repository import ( ...@@ -28,6 +29,9 @@ from tests.repositories.test_legacy_repository import (
from tests.repositories.test_pypi_repository import MockRepository from tests.repositories.test_pypi_repository import MockRepository
RESERVED_PACKAGES = ("pip", "setuptools", "wheel")
class Installer(BaseInstaller): class Installer(BaseInstaller):
def _get_installer(self): def _get_installer(self):
return NoopInstaller() return NoopInstaller()
...@@ -292,49 +296,73 @@ def test_run_install_no_dev(installer, locker, repo, package, installed): ...@@ -292,49 +296,73 @@ def test_run_install_no_dev(installer, locker, repo, package, installed):
assert len(removals) == 1 assert len(removals) == 1
def test_run_install_remove_untracked(installer, locker, repo, package, installed): @pytest.mark.parametrize(
"managed_reserved_package_names",
[
i
for i in itertools.chain(
[tuple()],
itertools.permutations(RESERVED_PACKAGES, 1),
itertools.permutations(RESERVED_PACKAGES, 2),
[RESERVED_PACKAGES],
)
],
)
def test_run_install_remove_untracked(
managed_reserved_package_names, installer, locker, repo, package, installed
):
package_a = get_package("a", "1.0")
package_b = get_package("b", "1.1")
package_c = get_package("c", "1.2")
package_pip = get_package("pip", "20.0.0")
package_setuptools = get_package("setuptools", "20.0.0")
package_wheel = get_package("wheel", "20.0.0")
all_packages = [
package_a,
package_b,
package_c,
package_pip,
package_setuptools,
package_wheel,
]
managed_reserved_packages = [
pkg for pkg in all_packages if pkg.name in managed_reserved_package_names
]
locked_packages = [package_a, *managed_reserved_packages]
for pkg in all_packages:
repo.add_package(pkg)
installed.add_package(pkg)
installed.add_package(package) # Root package never removed.
package.add_dependency(Factory.create_dependency(package_a.name, package_a.version))
locker.locked(True) locker.locked(True)
locker.mock_lock_data( locker.mock_lock_data(
{ {
"package": [ "package": [
{ {
"name": "a", "name": pkg.name,
"version": "1.0", "version": pkg.version,
"category": "main", "category": "main",
"optional": False, "optional": False,
"platform": "*", "platform": "*",
"python-versions": "*", "python-versions": "*",
"checksum": [], "checksum": [],
} }
for pkg in locked_packages
], ],
"metadata": { "metadata": {
"python-versions": "*", "python-versions": "*",
"platform": "*", "platform": "*",
"content-hash": "123456789", "content-hash": "123456789",
"hashes": {"a": []}, "hashes": {pkg.name: [] for pkg in locked_packages},
}, },
} }
) )
package_a = get_package("a", "1.0")
package_b = get_package("b", "1.1")
package_c = get_package("c", "1.2")
package_pip = get_package("pip", "20.0.0")
package_setuptools = get_package("setuptools", "20.0.0")
repo.add_package(package_a)
repo.add_package(package_b)
repo.add_package(package_c)
repo.add_package(package_pip)
repo.add_package(package_setuptools)
installed.add_package(package_a)
installed.add_package(package_b)
installed.add_package(package_c)
installed.add_package(package_pip)
installed.add_package(package_setuptools)
installed.add_package(package) # Root package never removed.
package.add_dependency(Factory.create_dependency("A", "~1.0"))
installer.dev_mode(True).remove_untracked(True) installer.dev_mode(True).remove_untracked(True)
installer.run() installer.run()
...@@ -346,7 +374,12 @@ def test_run_install_remove_untracked(installer, locker, repo, package, installe ...@@ -346,7 +374,12 @@ def test_run_install_remove_untracked(installer, locker, repo, package, installe
assert len(updates) == 0 assert len(updates) == 0
removals = installer.installer.removals removals = installer.installer.removals
assert set(r.name for r in removals) == {"b", "c", "pip", "setuptools"} expected_removals = {
package_b.name,
package_c.name,
*managed_reserved_package_names,
}
assert set(r.name for r in removals) == expected_removals
def test_run_whitelist_add(installer, locker, repo, package): def test_run_whitelist_add(installer, locker, repo, package):
......
...@@ -4,7 +4,7 @@ import subprocess ...@@ -4,7 +4,7 @@ import subprocess
import sys import sys
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Any
from typing import Union from typing import Union
import pytest import pytest
...@@ -118,9 +118,7 @@ def test_env_get_venv_with_venv_folder_present( ...@@ -118,9 +118,7 @@ def test_env_get_venv_with_venv_folder_present(
assert venv.path == in_project_venv_dir assert venv.path == in_project_venv_dir
def build_venv( def build_venv(path: Union[Path, str], **__: Any) -> ():
path: Union[Path, str], executable: Optional[str] = None, flags: bool = None
) -> ():
os.mkdir(str(path)) os.mkdir(str(path))
...@@ -161,6 +159,9 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( ...@@ -161,6 +159,9 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file(
Path(tmp_dir) / "{}-py3.7".format(venv_name), Path(tmp_dir) / "{}-py3.7".format(venv_name),
executable="python3.7", executable="python3.7",
flags={"always-copy": False, "system-site-packages": False}, flags={"always-copy": False, "system-site-packages": False},
with_pip=True,
with_setuptools=True,
with_wheel=True,
) )
envs_file = TOMLFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
...@@ -281,6 +282,9 @@ def test_activate_activates_different_virtualenv_with_envs_file( ...@@ -281,6 +282,9 @@ def test_activate_activates_different_virtualenv_with_envs_file(
Path(tmp_dir) / "{}-py3.6".format(venv_name), Path(tmp_dir) / "{}-py3.6".format(venv_name),
executable="python3.6", executable="python3.6",
flags={"always-copy": False, "system-site-packages": False}, flags={"always-copy": False, "system-site-packages": False},
with_pip=True,
with_setuptools=True,
with_wheel=True,
) )
assert envs_file.exists() assert envs_file.exists()
...@@ -335,6 +339,9 @@ def test_activate_activates_recreates_for_different_patch( ...@@ -335,6 +339,9 @@ def test_activate_activates_recreates_for_different_patch(
Path(tmp_dir) / "{}-py3.7".format(venv_name), Path(tmp_dir) / "{}-py3.7".format(venv_name),
executable="python3.7", executable="python3.7",
flags={"always-copy": False, "system-site-packages": False}, flags={"always-copy": False, "system-site-packages": False},
with_pip=True,
with_setuptools=True,
with_wheel=True,
) )
remove_venv_m.assert_called_with(Path(tmp_dir) / "{}-py3.7".format(venv_name)) remove_venv_m.assert_called_with(Path(tmp_dir) / "{}-py3.7".format(venv_name))
...@@ -715,6 +722,9 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_generic_ ...@@ -715,6 +722,9 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_generic_
config_virtualenvs_path / "{}-py3.7".format(venv_name), config_virtualenvs_path / "{}-py3.7".format(venv_name),
executable="python3", executable="python3",
flags={"always-copy": False, "system-site-packages": False}, flags={"always-copy": False, "system-site-packages": False},
with_pip=True,
with_setuptools=True,
with_wheel=True,
) )
...@@ -739,6 +749,9 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_specific ...@@ -739,6 +749,9 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_specific
config_virtualenvs_path / "{}-py3.9".format(venv_name), config_virtualenvs_path / "{}-py3.9".format(venv_name),
executable="python3.9", executable="python3.9",
flags={"always-copy": False, "system-site-packages": False}, flags={"always-copy": False, "system-site-packages": False},
with_pip=True,
with_setuptools=True,
with_wheel=True,
) )
...@@ -823,6 +836,9 @@ def test_create_venv_uses_patch_version_to_detect_compatibility( ...@@ -823,6 +836,9 @@ def test_create_venv_uses_patch_version_to_detect_compatibility(
/ "{}-py{}.{}".format(venv_name, version.major, version.minor), / "{}-py{}.{}".format(venv_name, version.major, version.minor),
executable=None, executable=None,
flags={"always-copy": False, "system-site-packages": False}, flags={"always-copy": False, "system-site-packages": False},
with_pip=True,
with_setuptools=True,
with_wheel=True,
) )
...@@ -858,6 +874,9 @@ def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable( ...@@ -858,6 +874,9 @@ def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable(
/ "{}-py{}.{}".format(venv_name, version.major, version.minor - 1), / "{}-py{}.{}".format(venv_name, version.major, version.minor - 1),
executable="python{}.{}".format(version.major, version.minor - 1), executable="python{}.{}".format(version.major, version.minor - 1),
flags={"always-copy": False, "system-site-packages": False}, flags={"always-copy": False, "system-site-packages": False},
with_pip=True,
with_setuptools=True,
with_wheel=True,
) )
...@@ -892,6 +911,9 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir( ...@@ -892,6 +911,9 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir(
poetry.file.parent / ".venv", poetry.file.parent / ".venv",
executable="python3.7", executable="python3.7",
flags={"always-copy": False, "system-site-packages": False}, flags={"always-copy": False, "system-site-packages": False},
with_pip=True,
with_setuptools=True,
with_wheel=True,
) )
envs_file = TOMLFile(Path(tmp_dir) / "virtualenvs" / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "virtualenvs" / "envs.toml")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment