Commit 0e6404ef by Sébastien Eustace Committed by Arun Babu Neelicattu

Add a paths property to environments

parent 0885841d
...@@ -101,6 +101,13 @@ import sys ...@@ -101,6 +101,13 @@ import sys
print(json.dumps(sys.path)) print(json.dumps(sys.path))
""" """
GET_PATHS = """\
import json
import sysconfig
print(json.dumps(sysconfig.get_paths()))
"""
CREATE_VENV_COMMAND = """\ CREATE_VENV_COMMAND = """\
path = {!r} path = {!r}
...@@ -734,6 +741,7 @@ class Env(object): ...@@ -734,6 +741,7 @@ class Env(object):
self._marker_env = None self._marker_env = None
self._pip_version = None self._pip_version = None
self._site_packages = None self._site_packages = None
self._paths = None
@property @property
def path(self): # type: () -> Path def path(self): # type: () -> Path
...@@ -790,22 +798,7 @@ class Env(object): ...@@ -790,22 +798,7 @@ class Env(object):
@property @property
def site_packages(self): # type: () -> Path def site_packages(self): # type: () -> Path
if self._site_packages is None: if self._site_packages is None:
site_packages = [] self._site_packages = Path(self.paths["purelib"])
dist_packages = []
for entry in self.sys_path:
entry = Path(entry)
if entry.name == "site-packages":
site_packages.append(entry)
elif entry.name == "dist-packages":
dist_packages.append(entry)
if not site_packages and not dist_packages:
raise RuntimeError("Unable to find the site-packages directory")
if site_packages:
self._site_packages = site_packages[0]
else:
self._site_packages = dist_packages[0]
return self._site_packages return self._site_packages
...@@ -813,6 +806,13 @@ class Env(object): ...@@ -813,6 +806,13 @@ class Env(object):
def sys_path(self): # type: () -> List[str] def sys_path(self): # type: () -> List[str]
raise NotImplementedError() raise NotImplementedError()
@property
def paths(self): # type: () -> Dict[str, str]
if self._paths is None:
self._paths = self.get_paths()
return self._paths
@classmethod @classmethod
def get_base_prefix(cls): # type: () -> Path def get_base_prefix(cls): # type: () -> Path
if hasattr(sys, "real_prefix"): if hasattr(sys, "real_prefix"):
...@@ -841,6 +841,9 @@ class Env(object): ...@@ -841,6 +841,9 @@ class Env(object):
def get_pip_version(self): # type: () -> Version def get_pip_version(self): # type: () -> Version
raise NotImplementedError() raise NotImplementedError()
def get_paths(self): # type: () -> Dict[str, str]
raise NotImplementedError()
def is_valid_for_marker(self, marker): # type: (BaseMarker) -> bool def is_valid_for_marker(self, marker): # type: (BaseMarker) -> bool
return marker.validate(self.marker_env) return marker.validate(self.marker_env)
...@@ -961,6 +964,29 @@ class SystemEnv(Env): ...@@ -961,6 +964,29 @@ class SystemEnv(Env):
# has a pip and use that # has a pip and use that
return [sys.executable, "-m", "pip"] return [sys.executable, "-m", "pip"]
def get_paths(self): # type: () -> Dict[str, str]
# We can't use sysconfig.get_paths() because
# on some distributions it does not return the proper paths
# (those used by pip for instance). We go through distutils
# to get the proper ones.
from distutils.core import Distribution
from distutils.command.install import SCHEME_KEYS # noqa
d = Distribution()
d.parse_config_files()
obj = d.get_command_obj("install", create=True)
obj.finalize_options()
paths = sysconfig.get_paths().copy()
for key in SCHEME_KEYS:
if key == "headers":
# headers is not a path returned by sysconfig.get_paths()
continue
paths[key] = getattr(obj, "install_{}".format(key))
return paths
def get_marker_env(self): # type: () -> Dict[str, Any] def get_marker_env(self): # type: () -> Dict[str, Any]
if hasattr(sys, "implementation"): if hasattr(sys, "implementation"):
info = sys.implementation.version info = sys.implementation.version
...@@ -1071,6 +1097,11 @@ class VirtualEnv(Env): ...@@ -1071,6 +1097,11 @@ class VirtualEnv(Env):
return Version.parse(m.group(1)) return Version.parse(m.group(1))
def get_paths(self): # type: () -> Dict[str, str]
output = self.run("python", "-", input_=GET_PATHS)
return json.loads(output)
def is_venv(self): # type: () -> bool def is_venv(self): # type: () -> bool
return True return True
......
...@@ -9,11 +9,11 @@ from clikit.io import NullIO ...@@ -9,11 +9,11 @@ from clikit.io import NullIO
from poetry.core.semver import Version from poetry.core.semver import Version
from poetry.factory import Factory from poetry.factory import Factory
from poetry.utils._compat import WINDOWS
from poetry.utils._compat import Path from poetry.utils._compat import Path
from poetry.utils.env import EnvCommandError from poetry.utils.env import EnvCommandError
from poetry.utils.env import EnvManager from poetry.utils.env import EnvManager
from poetry.utils.env import NoCompatiblePythonVersionFound from poetry.utils.env import NoCompatiblePythonVersionFound
from poetry.utils.env import SystemEnv
from poetry.utils.env import VirtualEnv from poetry.utils.env import VirtualEnv
from poetry.utils.toml_file import TomlFile from poetry.utils.toml_file import TomlFile
...@@ -788,58 +788,21 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir( ...@@ -788,58 +788,21 @@ def test_activate_with_in_project_setting_does_not_fail_if_no_venvs_dir(
assert not envs_file.exists() assert not envs_file.exists()
def test_env_site_packages_should_find_the_site_packages_directory_if_standard(tmp_dir): def test_system_env_has_correct_paths():
if WINDOWS: env = SystemEnv(Path(sys.prefix))
site_packages = Path(tmp_dir).joinpath("Lib/site-packages")
else:
site_packages = Path(tmp_dir).joinpath(
"lib/python{}/site-packages".format(
".".join(str(v) for v in sys.version_info[:2])
)
)
site_packages.mkdir(parents=True)
env = MockVirtualEnv(Path(tmp_dir), Path(tmp_dir), sys_path=[str(site_packages)])
assert site_packages == env.site_packages
def test_env_site_packages_should_find_the_site_packages_directory_if_root(tmp_dir):
site_packages = Path(tmp_dir).joinpath("site-packages")
site_packages.mkdir(parents=True)
env = MockVirtualEnv(Path(tmp_dir), Path(tmp_dir), sys_path=[str(site_packages)])
assert site_packages == env.site_packages
paths = env.paths
def test_env_site_packages_should_find_the_dist_packages_directory_if_necessary( assert paths.get("purelib") is not None
tmp_dir, assert paths.get("platlib") is not None
): assert paths.get("scripts") is not None
site_packages = Path(tmp_dir).joinpath("dist-packages") assert env.site_packages == Path(paths["purelib"])
site_packages.mkdir(parents=True)
env = MockVirtualEnv(Path(tmp_dir), Path(tmp_dir), sys_path=[str(site_packages)])
assert site_packages == env.site_packages
def test_env_site_packages_should_prefer_site_packages_over_dist_packages(tmp_dir):
dist_packages = Path(tmp_dir).joinpath("dist-packages")
dist_packages.mkdir(parents=True)
site_packages = Path(tmp_dir).joinpath("site-packages")
site_packages.mkdir(parents=True)
env = MockVirtualEnv(
Path(tmp_dir), Path(tmp_dir), sys_path=[str(dist_packages), str(site_packages)]
)
assert site_packages == env.site_packages
def test_env_site_packages_should_raise_an_error_if_no_site_packages(tmp_dir): def test_venv_has_correct_paths(tmp_venv):
env = MockVirtualEnv(Path(tmp_dir), Path(tmp_dir), sys_path=[]) paths = tmp_venv.paths
with pytest.raises(RuntimeError): assert paths.get("purelib") is not None
env.site_packages assert paths.get("platlib") is not None
assert paths.get("scripts") is not None
assert tmp_venv.site_packages == Path(paths["purelib"])
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