mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Merge pull request #11466 from minrk/build_env_isolation
This commit is contained in:
commit
0a21080411
3 changed files with 38 additions and 4 deletions
1
news/6264.bugfix.rst
Normal file
1
news/6264.bugfix.rst
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix build environment isolation on some system Pythons.
|
|
@ -4,6 +4,7 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import site
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
@ -55,6 +56,26 @@ def get_runnable_pip() -> str:
|
||||||
return os.fsdecode(source / "__pip-runner__.py")
|
return os.fsdecode(source / "__pip-runner__.py")
|
||||||
|
|
||||||
|
|
||||||
|
def _get_system_sitepackages() -> Set[str]:
|
||||||
|
"""Get system site packages
|
||||||
|
|
||||||
|
Usually from site.getsitepackages,
|
||||||
|
but fallback on `get_purelib()/get_platlib()` if unavailable
|
||||||
|
(e.g. in a virtualenv created by virtualenv<20)
|
||||||
|
|
||||||
|
Returns normalized set of strings.
|
||||||
|
"""
|
||||||
|
if hasattr(site, "getsitepackages"):
|
||||||
|
system_sites = site.getsitepackages()
|
||||||
|
else:
|
||||||
|
# virtualenv < 20 overwrites site.py without getsitepackages
|
||||||
|
# fallback on get_purelib/get_platlib.
|
||||||
|
# this is known to miss things, but shouldn't in the cases
|
||||||
|
# where getsitepackages() has been removed (inside a virtualenv)
|
||||||
|
system_sites = [get_purelib(), get_platlib()]
|
||||||
|
return {os.path.normcase(path) for path in system_sites}
|
||||||
|
|
||||||
|
|
||||||
class BuildEnvironment:
|
class BuildEnvironment:
|
||||||
"""Creates and manages an isolated environment to install build deps"""
|
"""Creates and manages an isolated environment to install build deps"""
|
||||||
|
|
||||||
|
@ -75,9 +96,8 @@ class BuildEnvironment:
|
||||||
# Customize site to:
|
# Customize site to:
|
||||||
# - ensure .pth files are honored
|
# - ensure .pth files are honored
|
||||||
# - prevent access to system site packages
|
# - prevent access to system site packages
|
||||||
system_sites = {
|
system_sites = _get_system_sitepackages()
|
||||||
os.path.normcase(site) for site in (get_purelib(), get_platlib())
|
|
||||||
}
|
|
||||||
self._site_dir = os.path.join(temp_dir.path, "site")
|
self._site_dir = os.path.join(temp_dir.path, "site")
|
||||||
if not os.path.exists(self._site_dir):
|
if not os.path.exists(self._site_dir):
|
||||||
os.mkdir(self._site_dir)
|
os.mkdir(self._site_dir)
|
||||||
|
|
|
@ -4,7 +4,7 @@ from typing import Optional
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from pip._internal.build_env import BuildEnvironment
|
from pip._internal.build_env import BuildEnvironment, _get_system_sitepackages
|
||||||
from tests.lib import (
|
from tests.lib import (
|
||||||
PipTestEnvironment,
|
PipTestEnvironment,
|
||||||
TestPipResult,
|
TestPipResult,
|
||||||
|
@ -226,6 +226,10 @@ def test_build_env_isolation(script: PipTestEnvironment) -> None:
|
||||||
script.pip_install_local("-t", target, pkg_whl)
|
script.pip_install_local("-t", target, pkg_whl)
|
||||||
script.environ["PYTHONPATH"] = target
|
script.environ["PYTHONPATH"] = target
|
||||||
|
|
||||||
|
system_sites = _get_system_sitepackages()
|
||||||
|
# there should always be something to exclude
|
||||||
|
assert system_sites
|
||||||
|
|
||||||
run_with_build_env(
|
run_with_build_env(
|
||||||
script,
|
script,
|
||||||
"",
|
"",
|
||||||
|
@ -247,5 +251,14 @@ def test_build_env_isolation(script: PipTestEnvironment) -> None:
|
||||||
})), file=sys.stderr)
|
})), file=sys.stderr)
|
||||||
print('sys.path:\n ' + '\n '.join(sys.path), file=sys.stderr)
|
print('sys.path:\n ' + '\n '.join(sys.path), file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
"""
|
||||||
|
f"""
|
||||||
|
# second check: direct check of exclusion of system site packages
|
||||||
|
import os
|
||||||
|
|
||||||
|
normalized_path = [os.path.normcase(path) for path in sys.path]
|
||||||
|
for system_path in {system_sites!r}:
|
||||||
|
assert system_path not in normalized_path, \
|
||||||
|
f"{{system_path}} found in {{normalized_path}}"
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue