From 38558a1942b95c16038c35c8cfb7b5c0a80fb823 Mon Sep 17 00:00:00 2001 From: vlad0337187 Date: Sat, 20 Feb 2021 23:57:36 +0200 Subject: [PATCH] feature(virtualenv): add 'system-site-packages' option --- docs/docs/configuration.md | 6 ++++++ poetry/config/config.py | 3 ++- poetry/console/commands/config.py | 15 ++++++++----- poetry/utils/env.py | 2 +- tests/console/commands/env/test_use.py | 4 +++- tests/console/commands/test_config.py | 3 +++ tests/test_factory.py | 2 ++ tests/utils/test_env.py | 30 +++++++++++++++++++------- 8 files changed, 49 insertions(+), 16 deletions(-) diff --git a/docs/docs/configuration.md b/docs/docs/configuration.md index 72310886ca7..fb085b94c57 100644 --- a/docs/docs/configuration.md +++ b/docs/docs/configuration.md @@ -35,6 +35,7 @@ cache-dir = "/path/to/cache/directory" virtualenvs.create = true virtualenvs.in-project = null virtualenvs.options.always-copy = true +virtualenvs.options.system-site-packages = false virtualenvs.path = "{cache-dir}/virtualenvs" # /path/to/cache/directory/virtualenvs ``` @@ -143,6 +144,11 @@ 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. Defaults to `false`. +### `virtualenvs.options.system-site-packages`: boolean + +Give the virtual environment access to the system site-packages directory. +Applies on virtualenv creation. +Defaults to `false`. ### `repositories.`: string diff --git a/poetry/config/config.py b/poetry/config/config.py index 37844aa1fc9..c0f794bd004 100644 --- a/poetry/config/config.py +++ b/poetry/config/config.py @@ -35,7 +35,7 @@ class Config(object): "create": True, "in-project": None, "path": os.path.join("{cache-dir}", "virtualenvs"), - "options": {"always-copy": False}, + "options": {"always-copy": False, "system-site-packages": False}, }, "experimental": {"new-installer": True}, "installer": {"parallel": True}, @@ -140,6 +140,7 @@ def _get_normalizer(self, name: str) -> Callable: "virtualenvs.create", "virtualenvs.in-project", "virtualenvs.options.always-copy", + "virtualenvs.options.system-site-packages", "installer.parallel", }: return boolean_normalizer diff --git a/poetry/console/commands/config.py b/poetry/console/commands/config.py index 1f008195444..300245955d0 100644 --- a/poetry/console/commands/config.py +++ b/poetry/console/commands/config.py @@ -62,6 +62,16 @@ def unique_config_values(self) -> Dict[str, Tuple[Any, Any, Any]]: ), "virtualenvs.create": (boolean_validator, boolean_normalizer, True), "virtualenvs.in-project": (boolean_validator, boolean_normalizer, False), + "virtualenvs.options.always-copy": ( + boolean_validator, + boolean_normalizer, + False, + ), + "virtualenvs.options.system-site-packages": ( + boolean_validator, + boolean_normalizer, + False, + ), "virtualenvs.path": ( str, lambda val: str(Path(val)), @@ -72,11 +82,6 @@ def unique_config_values(self) -> Dict[str, Tuple[Any, Any, Any]]: boolean_normalizer, True, ), - "virtualenvs.options.always-copy": ( - boolean_validator, - boolean_normalizer, - False, - ), "installer.parallel": ( boolean_validator, boolean_normalizer, diff --git a/poetry/utils/env.py b/poetry/utils/env.py index ae94d40e1aa..d930b0d0316 100644 --- a/poetry/utils/env.py +++ b/poetry/utils/env.py @@ -637,8 +637,8 @@ def create_venv( create_venv = self._poetry.config.get("virtualenvs.create") root_venv = self._poetry.config.get("virtualenvs.in-project") - venv_path = self._poetry.config.get("virtualenvs.path") + if root_venv: venv_path = cwd / ".venv" elif venv_path is None: diff --git a/tests/console/commands/env/test_use.py b/tests/console/commands/env/test_use.py index 9ae8b41f4bd..f80ff8ee20b 100644 --- a/tests/console/commands/env/test_use.py +++ b/tests/console/commands/env/test_use.py @@ -52,7 +52,9 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( venv_py37 = venv_cache / "{}-py3.7".format(venv_name) mock_build_env.assert_called_with( - venv_py37, executable="python3.7", flags={"always-copy": False} + venv_py37, + executable="python3.7", + flags={"always-copy": False, "system-site-packages": False}, ) envs_file = TOMLFile(venv_cache / "envs.toml") diff --git a/tests/console/commands/test_config.py b/tests/console/commands/test_config.py index 66b0dae9b69..9cb692b40aa 100644 --- a/tests/console/commands/test_config.py +++ b/tests/console/commands/test_config.py @@ -32,6 +32,7 @@ def test_list_displays_default_value_if_not_set(tester, config, config_cache_dir virtualenvs.create = true virtualenvs.in-project = null virtualenvs.options.always-copy = false +virtualenvs.options.system-site-packages = false virtualenvs.path = {path} # {virtualenvs} """.format( cache=json.dumps(str(config_cache_dir)), @@ -53,6 +54,7 @@ def test_list_displays_set_get_setting(tester, config, config_cache_dir): virtualenvs.create = false virtualenvs.in-project = null virtualenvs.options.always-copy = false +virtualenvs.options.system-site-packages = false virtualenvs.path = {path} # {virtualenvs} """.format( cache=json.dumps(str(config_cache_dir)), @@ -96,6 +98,7 @@ def test_list_displays_set_get_local_setting(tester, config, config_cache_dir): virtualenvs.create = false virtualenvs.in-project = null virtualenvs.options.always-copy = false +virtualenvs.options.system-site-packages = false virtualenvs.path = {path} # {virtualenvs} """.format( cache=json.dumps(str(config_cache_dir)), diff --git a/tests/test_factory.py b/tests/test_factory.py index d213d808405..7a4e9d5ac4a 100644 --- a/tests/test_factory.py +++ b/tests/test_factory.py @@ -222,3 +222,5 @@ def test_create_poetry_with_local_config(fixture_dir): assert not poetry.config.get("virtualenvs.in-project") assert not poetry.config.get("virtualenvs.create") + assert not poetry.config.get("virtualenvs.options.always-copy") + assert not poetry.config.get("virtualenvs.options.system-site-packages") diff --git a/tests/utils/test_env.py b/tests/utils/test_env.py index c929f443caa..945a4d47844 100644 --- a/tests/utils/test_env.py +++ b/tests/utils/test_env.py @@ -159,7 +159,7 @@ def test_activate_activates_non_existing_virtualenv_no_envs_file( m.assert_called_with( Path(tmp_dir) / "{}-py3.7".format(venv_name), executable="python3.7", - flags={"always-copy": False}, + flags={"always-copy": False, "system-site-packages": False}, ) envs_file = TOMLFile(Path(tmp_dir) / "envs.toml") @@ -279,7 +279,7 @@ def test_activate_activates_different_virtualenv_with_envs_file( m.assert_called_with( Path(tmp_dir) / "{}-py3.6".format(venv_name), executable="python3.6", - flags={"always-copy": False}, + flags={"always-copy": False, "system-site-packages": False}, ) assert envs_file.exists() @@ -333,7 +333,7 @@ def test_activate_activates_recreates_for_different_patch( build_venv_m.assert_called_with( Path(tmp_dir) / "{}-py3.7".format(venv_name), executable="python3.7", - flags={"always-copy": False}, + flags={"always-copy": False, "system-site-packages": False}, ) remove_venv_m.assert_called_with(Path(tmp_dir) / "{}-py3.7".format(venv_name)) @@ -661,7 +661,7 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_generic_ m.assert_called_with( config_virtualenvs_path / "{}-py3.7".format(venv_name), executable="python3", - flags={"always-copy": False}, + flags={"always-copy": False, "system-site-packages": False}, ) @@ -685,7 +685,7 @@ def test_create_venv_tries_to_find_a_compatible_python_executable_using_specific m.assert_called_with( config_virtualenvs_path / "{}-py3.9".format(venv_name), executable="python3.9", - flags={"always-copy": False}, + flags={"always-copy": False, "system-site-packages": False}, ) @@ -769,7 +769,7 @@ def test_create_venv_uses_patch_version_to_detect_compatibility( config_virtualenvs_path / "{}-py{}.{}".format(venv_name, version.major, version.minor), executable=None, - flags={"always-copy": False}, + flags={"always-copy": False, "system-site-packages": False}, ) @@ -804,7 +804,7 @@ def test_create_venv_uses_patch_version_to_detect_compatibility_with_executable( config_virtualenvs_path / "{}-py{}.{}".format(venv_name, version.major, version.minor - 1), executable="python{}.{}".format(version.major, version.minor - 1), - flags={"always-copy": False}, + flags={"always-copy": False, "system-site-packages": False}, ) @@ -838,7 +838,7 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir( m.assert_called_with( poetry.file.parent / ".venv", executable="python3.7", - flags={"always-copy": False}, + flags={"always-copy": False, "system-site-packages": False}, ) envs_file = TOMLFile(Path(tmp_dir) / "virtualenvs" / "envs.toml") @@ -875,3 +875,17 @@ def test_venv_has_correct_paths(tmp_venv): assert paths.get("platlib") is not None assert paths.get("scripts") is not None assert tmp_venv.site_packages.path == Path(paths["purelib"]) + + +def test_env_system_packages(tmp_path, config): + venv_path = tmp_path / "venv" + pyvenv_cfg = venv_path / "pyvenv.cfg" + + EnvManager(config).build_venv(path=venv_path, flags={"system-site-packages": True}) + + if sys.version_info >= (3, 3): + assert "include-system-site-packages = true" in pyvenv_cfg.read_text() + elif (2, 6) < sys.version_info < (3, 0): + assert not venv_path.joinpath( + "lib", "python2.7", "no-global-site-packages.txt" + ).exists()