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
print(json.dumps(sys.path))
"""
GET_PATHS = """\
import json
import sysconfig
print(json.dumps(sysconfig.get_paths()))
"""
CREATE_VENV_COMMAND = """\
path = {!r}
......@@ -734,6 +741,7 @@ class Env(object):
self._marker_env = None
self._pip_version = None
self._site_packages = None
self._paths = None
@property
def path(self): # type: () -> Path
......@@ -790,22 +798,7 @@ class Env(object):
@property
def site_packages(self): # type: () -> Path
if self._site_packages is None:
site_packages = []
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]
self._site_packages = Path(self.paths["purelib"])
return self._site_packages
......@@ -813,6 +806,13 @@ class Env(object):
def sys_path(self): # type: () -> List[str]
raise NotImplementedError()
@property
def paths(self): # type: () -> Dict[str, str]
if self._paths is None:
self._paths = self.get_paths()
return self._paths
@classmethod
def get_base_prefix(cls): # type: () -> Path
if hasattr(sys, "real_prefix"):
......@@ -841,6 +841,9 @@ class Env(object):
def get_pip_version(self): # type: () -> Version
raise NotImplementedError()
def get_paths(self): # type: () -> Dict[str, str]
raise NotImplementedError()
def is_valid_for_marker(self, marker): # type: (BaseMarker) -> bool
return marker.validate(self.marker_env)
......@@ -961,6 +964,29 @@ class SystemEnv(Env):
# has a pip and use that
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]
if hasattr(sys, "implementation"):
info = sys.implementation.version
......@@ -1071,6 +1097,11 @@ class VirtualEnv(Env):
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
return True
......
......@@ -9,11 +9,11 @@ from clikit.io import NullIO
from poetry.core.semver import Version
from poetry.factory import Factory
from poetry.utils._compat import WINDOWS
from poetry.utils._compat import Path
from poetry.utils.env import EnvCommandError
from poetry.utils.env import EnvManager
from poetry.utils.env import NoCompatiblePythonVersionFound
from poetry.utils.env import SystemEnv
from poetry.utils.env import VirtualEnv
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(
assert not envs_file.exists()
def test_env_site_packages_should_find_the_site_packages_directory_if_standard(tmp_dir):
if WINDOWS:
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)])
def test_system_env_has_correct_paths():
env = SystemEnv(Path(sys.prefix))
assert site_packages == env.site_packages
def test_env_site_packages_should_find_the_dist_packages_directory_if_necessary(
tmp_dir,
):
site_packages = Path(tmp_dir).joinpath("dist-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
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)]
)
paths = env.paths
assert site_packages == env.site_packages
assert paths.get("purelib") is not None
assert paths.get("platlib") is not None
assert paths.get("scripts") is not None
assert env.site_packages == Path(paths["purelib"])
def test_env_site_packages_should_raise_an_error_if_no_site_packages(tmp_dir):
env = MockVirtualEnv(Path(tmp_dir), Path(tmp_dir), sys_path=[])
def test_venv_has_correct_paths(tmp_venv):
paths = tmp_venv.paths
with pytest.raises(RuntimeError):
env.site_packages
assert paths.get("purelib") is not None
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