From 9a62bcde36aaa4863576ac9adaf418d96e0598d9 Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Sun, 5 Jan 2025 17:28:40 +0100 Subject: [PATCH] fix(env): ensure all system site paths are used With this change, when using newer Python versions (>=3.12), Poetry correctly detects and considers read-only system site packages when an environment is loaded. Resolves: #9878 --- src/poetry/utils/env/base_env.py | 13 ++++++++----- src/poetry/utils/env/script_strings.py | 5 +++++ tests/utils/env/test_env.py | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/poetry/utils/env/base_env.py b/src/poetry/utils/env/base_env.py index f57fb9cc2ae..3c0da4ffa20 100644 --- a/src/poetry/utils/env/base_env.py +++ b/src/poetry/utils/env/base_env.py @@ -175,13 +175,10 @@ def os(self) -> str: @property def site_packages(self) -> SitePackages: if self._site_packages is None: - # we disable write checks if no user site exist - fallbacks = [self.usersite] if self.usersite else [] self._site_packages = SitePackages( self.purelib, self.platlib, - fallbacks, - skip_write_checks=not fallbacks, + self.fallbacks, ) return self._site_packages @@ -214,8 +211,14 @@ def platlib(self) -> Path: return self._platlib + @cached_property + def fallbacks(self) -> list[Path]: + paths = [Path(path) for path in self.paths.get("fallbacks", [])] + paths += [self.usersite] if self.usersite else [] + return paths + def _get_lib_dirs(self) -> list[Path]: - return [self.purelib, self.platlib] + return [self.purelib, self.platlib, *self.fallbacks] def is_path_relative_to_lib(self, path: Path) -> bool: for lib_path in self._get_lib_dirs(): diff --git a/src/poetry/utils/env/script_strings.py b/src/poetry/utils/env/script_strings.py index f95663fbc94..a2935b566e9 100644 --- a/src/poetry/utils/env/script_strings.py +++ b/src/poetry/utils/env/script_strings.py @@ -97,6 +97,11 @@ def _version_nodot(version): paths = sysconfig.get_paths().copy() +paths["fallbacks"] = [ + p for p in site.getsitepackages() + if p and p not in {paths.get("purelib"), paths.get("platlib")} +] + if site.check_enableusersite(): paths["usersite"] = site.getusersitepackages() paths["userbase"] = site.getuserbase() diff --git a/tests/utils/env/test_env.py b/tests/utils/env/test_env.py index b3f63a7339d..97eda471416 100644 --- a/tests/utils/env/test_env.py +++ b/tests/utils/env/test_env.py @@ -309,7 +309,7 @@ def test_env_system_packages_are_relative_to_lib( # These are the virtual environments' base env packages, # in this case the system site packages. - for dist in metadata.distributions(path=[str(env.parent_env.site_packages.path)]): + for dist in env.parent_env.site_packages.distributions(): assert ( env.is_path_relative_to_lib( Path(str(dist._path)) # type: ignore[attr-defined]