Commit d2474b63 by Arun Babu Neelicattu

make no-pip and no-setuptools config explicit

This makes the `virtualenv.options.no-pip` and
`virtualenv.options.no-setuptools` options explicitly available to
users.

We default these to false as otherwise it can cause breakages for
certain development tools.
parent a9af9123
...@@ -46,6 +46,8 @@ cache-dir = "/path/to/cache/directory" ...@@ -46,6 +46,8 @@ cache-dir = "/path/to/cache/directory"
virtualenvs.create = true virtualenvs.create = true
virtualenvs.in-project = null virtualenvs.in-project = null
virtualenvs.options.always-copy = true virtualenvs.options.always-copy = true
virtualenvs.options.no-pip = false
virtualenvs.options.no-setuptools = false
virtualenvs.options.system-site-packages = false virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}/virtualenvs" # /path/to/cache/directory/virtualenvs virtualenvs.path = "{cache-dir}/virtualenvs" # /path/to/cache/directory/virtualenvs
virtualenvs.prefer-active-python = false virtualenvs.prefer-active-python = false
...@@ -148,11 +150,6 @@ Defaults to `true`. ...@@ -148,11 +150,6 @@ Defaults to `true`.
If set to `false`, poetry will install dependencies into the current python environment. If set to `false`, poetry will install dependencies into the current python environment.
{{% note %}}
When setting this configuration to `false`, the Python environment used must have `pip`
installed and available.
{{% /note %}}
### `virtualenvs.in-project` ### `virtualenvs.in-project`
**Type**: boolean **Type**: boolean
...@@ -181,6 +178,37 @@ Defaults to `{cache-dir}/virtualenvs` (`{cache-dir}\virtualenvs` on Windows). ...@@ -181,6 +178,37 @@ Defaults to `{cache-dir}/virtualenvs` (`{cache-dir}\virtualenvs` on Windows).
If set to `true` the `--always-copy` parameter is passed to `virtualenv` on creation of the venv. Thus all needed files are copied into the venv instead of symlinked. If set to `true` the `--always-copy` parameter is passed to `virtualenv` on creation of the venv. Thus all needed files are copied into the venv instead of symlinked.
Defaults to `false`. Defaults to `false`.
### `virtualenvs.options.no-pip`
**Type**: boolean
If set to `true` the `--no-pip` parameter is passed to `virtualenv` on creation of the venv. This means when a new
virtual environment is created, `pip` will not be installed in the environment.
Defaults to `false`.
{{% note %}}
Poetry, for its internal operations, uses the `pip` wheel embedded in the `virtualenv` package installed as a dependency
in Poetry's runtime environment. If a user runs `poetry run pip` when this option is set to `true`, the `pip` the
embedded instance of `pip` is used.
You can safely set this, along with `no-setuptools`, to `true`, if you desire a virtual environment with no additional
packages. This is desirable for production environments.
{{% /note %}}
### `virtualenvs.options.no-setuptools`
**Type**: boolean
If set to `true` the `--no-setuptools` parameter is passed to `virtualenv` on creation of the venv. This means when a new
virtual environment is created, `setuptools` will not be installed in the environment. Poetry, for its internal operations,
does not require `setuptools` and this can safely be set to `true`.
Defaults to `false`.
{{% warning %}}
Some development tools like IDEs, make an assumption that `setuptools` (and other) packages are always present and
available within a virtual environment. This can cause some features in these tools to not work as expected.
{{% /warning %}}
### `virtualenvs.options.system-site-packages` ### `virtualenvs.options.system-site-packages`
**Type**: boolean **Type**: boolean
......
...@@ -37,7 +37,16 @@ class Config: ...@@ -37,7 +37,16 @@ class Config:
"create": True, "create": True,
"in-project": None, "in-project": None,
"path": os.path.join("{cache-dir}", "virtualenvs"), "path": os.path.join("{cache-dir}", "virtualenvs"),
"options": {"always-copy": False, "system-site-packages": False}, "options": {
"always-copy": False,
"system-site-packages": False,
# we default to False here in order to prevent development environment
# breakages for IDEs etc. as when working in these environments
# assumptions are often made about virtual environments having pip and
# setuptools.
"no-pip": False,
"no-setuptools": False,
},
"prefer-active-python": False, "prefer-active-python": False,
}, },
"experimental": {"new-installer": True, "system-git-client": False}, "experimental": {"new-installer": True, "system-git-client": False},
......
...@@ -72,6 +72,16 @@ To remove a repository (repo is a short alias for repositories): ...@@ -72,6 +72,16 @@ To remove a repository (repo is a short alias for repositories):
boolean_normalizer, boolean_normalizer,
False, False,
), ),
"virtualenvs.options.no-pip": (
boolean_validator,
boolean_normalizer,
False,
),
"virtualenvs.options.no-setuptools": (
boolean_validator,
boolean_normalizer,
False,
),
"virtualenvs.path": ( "virtualenvs.path": (
str, str,
lambda val: str(Path(val)), lambda val: str(Path(val)),
......
...@@ -465,7 +465,7 @@ class PackageInfo: ...@@ -465,7 +465,7 @@ class PackageInfo:
pass pass
with ephemeral_environment( with ephemeral_environment(
with_pip=True, with_wheel=True, with_setuptools=True flags={"no-pip": False, "no-setuptools": False, "no-wheel": False}
) as venv: ) as venv:
# TODO: cache PEP 517 build environment corresponding to each project venv # TODO: cache PEP 517 build environment corresponding to each project venv
dest_dir = venv.path.parent / "dist" dest_dir = venv.path.parent / "dist"
......
...@@ -990,12 +990,6 @@ class EnvManager: ...@@ -990,12 +990,6 @@ class EnvManager:
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,
) )
# venv detection: # venv detection:
...@@ -1833,9 +1827,6 @@ class NullEnv(SystemEnv): ...@@ -1833,9 +1827,6 @@ class NullEnv(SystemEnv):
def ephemeral_environment( def ephemeral_environment(
executable: str | Path | None = None, executable: str | Path | None = None,
flags: dict[str, bool] = None, flags: dict[str, bool] = None,
with_pip: bool = False,
with_wheel: bool | None = None,
with_setuptools: bool | None = None,
) -> ContextManager[VirtualEnv]: ) -> ContextManager[VirtualEnv]:
with temporary_directory() as tmp_dir: with temporary_directory() as tmp_dir:
# TODO: cache PEP 517 build environment corresponding to each project venv # TODO: cache PEP 517 build environment corresponding to each project venv
...@@ -1844,9 +1835,6 @@ def ephemeral_environment( ...@@ -1844,9 +1835,6 @@ def ephemeral_environment(
path=venv_dir.as_posix(), path=venv_dir.as_posix(),
executable=executable, executable=executable,
flags=flags, flags=flags,
with_pip=with_pip,
with_wheel=with_wheel,
with_setuptools=with_setuptools,
) )
yield VirtualEnv(venv_dir, venv_dir) yield VirtualEnv(venv_dir, venv_dir)
......
...@@ -71,10 +71,12 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( ...@@ -71,10 +71,12 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file(
mock_build_env.assert_called_with( mock_build_env.assert_called_with(
venv_py37, venv_py37,
executable="/usr/bin/python3.7", executable="/usr/bin/python3.7",
flags={"always-copy": False, "system-site-packages": False}, flags={
with_pip=True, "always-copy": False,
with_setuptools=True, "system-site-packages": False,
with_wheel=True, "no-pip": False,
"no-setuptools": False,
},
) )
envs_file = TOMLFile(venv_cache / "envs.toml") envs_file = TOMLFile(venv_cache / "envs.toml")
......
...@@ -57,6 +57,8 @@ installer.parallel = true ...@@ -57,6 +57,8 @@ installer.parallel = true
virtualenvs.create = true virtualenvs.create = true
virtualenvs.in-project = null virtualenvs.in-project = null
virtualenvs.options.always-copy = false virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.no-setuptools = false
virtualenvs.options.system-site-packages = false virtualenvs.options.system-site-packages = false
virtualenvs.path = {venv_path} # {config_cache_dir / 'virtualenvs'} virtualenvs.path = {venv_path} # {config_cache_dir / 'virtualenvs'}
virtualenvs.prefer-active-python = false virtualenvs.prefer-active-python = false
...@@ -82,6 +84,8 @@ installer.parallel = true ...@@ -82,6 +84,8 @@ installer.parallel = true
virtualenvs.create = false virtualenvs.create = false
virtualenvs.in-project = null virtualenvs.in-project = null
virtualenvs.options.always-copy = false virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.no-setuptools = false
virtualenvs.options.system-site-packages = false virtualenvs.options.system-site-packages = false
virtualenvs.path = {venv_path} # {config_cache_dir / 'virtualenvs'} virtualenvs.path = {venv_path} # {config_cache_dir / 'virtualenvs'}
virtualenvs.prefer-active-python = false virtualenvs.prefer-active-python = false
...@@ -131,6 +135,8 @@ installer.parallel = true ...@@ -131,6 +135,8 @@ installer.parallel = true
virtualenvs.create = false virtualenvs.create = false
virtualenvs.in-project = null virtualenvs.in-project = null
virtualenvs.options.always-copy = false virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.no-setuptools = false
virtualenvs.options.system-site-packages = false virtualenvs.options.system-site-packages = false
virtualenvs.path = {venv_path} # {config_cache_dir / 'virtualenvs'} virtualenvs.path = {venv_path} # {config_cache_dir / 'virtualenvs'}
virtualenvs.prefer-active-python = false virtualenvs.prefer-active-python = false
......
...@@ -299,6 +299,8 @@ def test_create_poetry_with_local_config(fixture_dir: FixtureDirGetter): ...@@ -299,6 +299,8 @@ def test_create_poetry_with_local_config(fixture_dir: FixtureDirGetter):
assert not poetry.config.get("virtualenvs.in-project") assert not poetry.config.get("virtualenvs.in-project")
assert not poetry.config.get("virtualenvs.create") assert not poetry.config.get("virtualenvs.create")
assert not poetry.config.get("virtualenvs.options.always-copy") assert not poetry.config.get("virtualenvs.options.always-copy")
assert not poetry.config.get("virtualenvs.options.no-pip")
assert not poetry.config.get("virtualenvs.options.no-setuptools")
assert not poetry.config.get("virtualenvs.options.system-site-packages") assert not poetry.config.get("virtualenvs.options.system-site-packages")
......
...@@ -18,6 +18,7 @@ from poetry.core.semver.version import Version ...@@ -18,6 +18,7 @@ from poetry.core.semver.version import Version
from poetry.core.toml.file import TOMLFile from poetry.core.toml.file import TOMLFile
from poetry.factory import Factory from poetry.factory import Factory
from poetry.repositories.installed_repository import InstalledRepository
from poetry.utils._compat import WINDOWS from poetry.utils._compat import WINDOWS
from poetry.utils.env import GET_BASE_PREFIX from poetry.utils.env import GET_BASE_PREFIX
from poetry.utils.env import EnvCommandError from poetry.utils.env import EnvCommandError
...@@ -208,10 +209,12 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( ...@@ -208,10 +209,12 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file(
m.assert_called_with( m.assert_called_with(
Path(tmp_dir) / f"{venv_name}-py3.7", Path(tmp_dir) / f"{venv_name}-py3.7",
executable="/usr/bin/python3.7", executable="/usr/bin/python3.7",
flags={"always-copy": False, "system-site-packages": False}, flags={
with_pip=True, "always-copy": False,
with_setuptools=True, "system-site-packages": False,
with_wheel=True, "no-pip": False,
"no-setuptools": False,
},
) )
envs_file = TOMLFile(Path(tmp_dir) / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "envs.toml")
...@@ -343,10 +346,12 @@ def test_activate_activates_different_virtualenv_with_envs_file( ...@@ -343,10 +346,12 @@ def test_activate_activates_different_virtualenv_with_envs_file(
m.assert_called_with( m.assert_called_with(
Path(tmp_dir) / f"{venv_name}-py3.6", Path(tmp_dir) / f"{venv_name}-py3.6",
executable="/usr/bin/python3.6", executable="/usr/bin/python3.6",
flags={"always-copy": False, "system-site-packages": False}, flags={
with_pip=True, "always-copy": False,
with_setuptools=True, "system-site-packages": False,
with_wheel=True, "no-pip": False,
"no-setuptools": False,
},
) )
assert envs_file.exists() assert envs_file.exists()
...@@ -404,10 +409,12 @@ def test_activate_activates_recreates_for_different_patch( ...@@ -404,10 +409,12 @@ def test_activate_activates_recreates_for_different_patch(
build_venv_m.assert_called_with( build_venv_m.assert_called_with(
Path(tmp_dir) / f"{venv_name}-py3.7", Path(tmp_dir) / f"{venv_name}-py3.7",
executable="/usr/bin/python3.7", executable="/usr/bin/python3.7",
flags={"always-copy": False, "system-site-packages": False}, flags={
with_pip=True, "always-copy": False,
with_setuptools=True, "system-site-packages": False,
with_wheel=True, "no-pip": False,
"no-setuptools": False,
},
) )
remove_venv_m.assert_called_with(Path(tmp_dir) / f"{venv_name}-py3.7") remove_venv_m.assert_called_with(Path(tmp_dir) / f"{venv_name}-py3.7")
...@@ -839,10 +846,12 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_generic_ ...@@ -839,10 +846,12 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_generic_
m.assert_called_with( m.assert_called_with(
config_virtualenvs_path / f"{venv_name}-py3.7", config_virtualenvs_path / f"{venv_name}-py3.7",
executable="python3", executable="python3",
flags={"always-copy": False, "system-site-packages": False}, flags={
with_pip=True, "always-copy": False,
with_setuptools=True, "system-site-packages": False,
with_wheel=True, "no-pip": False,
"no-setuptools": False,
},
) )
...@@ -870,10 +879,12 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_specific ...@@ -870,10 +879,12 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_specific
m.assert_called_with( m.assert_called_with(
config_virtualenvs_path / f"{venv_name}-py3.9", config_virtualenvs_path / f"{venv_name}-py3.9",
executable="python3.9", executable="python3.9",
flags={"always-copy": False, "system-site-packages": False}, flags={
with_pip=True, "always-copy": False,
with_setuptools=True, "system-site-packages": False,
with_wheel=True, "no-pip": False,
"no-setuptools": False,
},
) )
...@@ -960,10 +971,12 @@ def test_create_venv_uses_patch_version_to_detect_compatibility( ...@@ -960,10 +971,12 @@ def test_create_venv_uses_patch_version_to_detect_compatibility(
m.assert_called_with( m.assert_called_with(
config_virtualenvs_path / f"{venv_name}-py{version.major}.{version.minor}", config_virtualenvs_path / f"{venv_name}-py{version.major}.{version.minor}",
executable=None, executable=None,
flags={"always-copy": False, "system-site-packages": False}, flags={
with_pip=True, "always-copy": False,
with_setuptools=True, "system-site-packages": False,
with_wheel=True, "no-pip": False,
"no-setuptools": False,
},
) )
...@@ -999,10 +1012,12 @@ def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable( ...@@ -999,10 +1012,12 @@ def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable(
m.assert_called_with( m.assert_called_with(
config_virtualenvs_path / f"{venv_name}-py{version.major}.{version.minor - 1}", config_virtualenvs_path / f"{venv_name}-py{version.major}.{version.minor - 1}",
executable=f"python{version.major}.{version.minor - 1}", executable=f"python{version.major}.{version.minor - 1}",
flags={"always-copy": False, "system-site-packages": False}, flags={
with_pip=True, "always-copy": False,
with_setuptools=True, "system-site-packages": False,
with_wheel=True, "no-pip": False,
"no-setuptools": False,
},
) )
...@@ -1067,10 +1082,12 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir( ...@@ -1067,10 +1082,12 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir(
m.assert_called_with( m.assert_called_with(
poetry.file.parent / ".venv", poetry.file.parent / ".venv",
executable="/usr/bin/python3.7", executable="/usr/bin/python3.7",
flags={"always-copy": False, "system-site-packages": False}, flags={
with_pip=True, "always-copy": False,
with_setuptools=True, "system-site-packages": False,
with_wheel=True, "no-pip": False,
"no-setuptools": False,
},
) )
envs_file = TOMLFile(Path(tmp_dir) / "virtualenvs" / "envs.toml") envs_file = TOMLFile(Path(tmp_dir) / "virtualenvs" / "envs.toml")
...@@ -1118,6 +1135,36 @@ def test_env_system_packages(tmp_path: Path, poetry: Poetry): ...@@ -1118,6 +1135,36 @@ def test_env_system_packages(tmp_path: Path, poetry: Poetry):
assert "include-system-site-packages = true" in pyvenv_cfg.read_text() assert "include-system-site-packages = true" in pyvenv_cfg.read_text()
@pytest.mark.parametrize(
("flags", "packages"),
[
({"no-pip": False}, {"pip", "wheel"}),
({"no-pip": False, "no-wheel": True}, {"pip"}),
({"no-pip": True}, set()),
({"no-setuptools": False}, {"setuptools"}),
({"no-setuptools": True}, set()),
({"no-pip": True, "no-setuptools": False}, {"setuptools"}),
({"no-wheel": False}, {"wheel"}),
({}, set()),
],
)
def test_env_no_pip(
tmp_path: Path, poetry: Poetry, flags: dict[str, bool], packages: set[str]
):
venv_path = tmp_path / "venv"
EnvManager(poetry).build_venv(path=venv_path, flags=flags)
env = VirtualEnv(venv_path)
installed_repository = InstalledRepository.load(env=env, with_dependencies=True)
installed_packages = {
package.name
for package in installed_repository.packages
# workaround for BSD test environments
if package.name != "sqlite3"
}
assert installed_packages == packages
def test_env_finds_the_correct_executables(tmp_dir: str, manager: EnvManager): def test_env_finds_the_correct_executables(tmp_dir: str, manager: EnvManager):
venv_path = Path(tmp_dir) / "Virtual Env" venv_path = Path(tmp_dir) / "Virtual Env"
manager.build_venv(str(venv_path), with_pip=True) manager.build_venv(str(venv_path), with_pip=True)
...@@ -1268,10 +1315,12 @@ def test_create_venv_accepts_fallback_version_w_nonzero_patchlevel( ...@@ -1268,10 +1315,12 @@ def test_create_venv_accepts_fallback_version_w_nonzero_patchlevel(
m.assert_called_with( m.assert_called_with(
config_virtualenvs_path / f"{venv_name}-py3.5", config_virtualenvs_path / f"{venv_name}-py3.5",
executable="python3.5", executable="python3.5",
flags={"always-copy": False, "system-site-packages": False}, flags={
with_pip=True, "always-copy": False,
with_setuptools=True, "system-site-packages": False,
with_wheel=True, "no-pip": False,
"no-setuptools": False,
},
) )
......
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