Skip to content

Commit f53ccfb

Browse files
committed
Run pip in isolated env by building zip
1 parent 3ab760a commit f53ccfb

File tree

2 files changed

+69
-33
lines changed

2 files changed

+69
-33
lines changed

news/8214.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Prevent packages already-installed alongside with pip to be injected into an
2+
isolated build environment during build-time dependency population.

src/pip/_internal/build_env.py

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
"""Build Environment used for isolation during sdist building
22
"""
33

4+
import contextlib
45
import logging
56
import os
7+
import pathlib
68
import sys
79
import textwrap
10+
import zipfile
811
from collections import OrderedDict
912
from sysconfig import get_paths
1013
from types import TracebackType
11-
from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type
14+
from typing import TYPE_CHECKING, Iterable, Iterator, List, Optional, Set, Tuple, Type
1215

1316
from pip._vendor.pkg_resources import Requirement, VersionConflict, WorkingSet
1417

@@ -37,6 +40,61 @@ def __init__(self, path):
3740
self.lib_dirs = get_prefixed_libs(path)
3841

3942

43+
@contextlib.contextmanager
44+
def _create_standalone_pip() -> Iterator[str]:
45+
"""Create a zip file containing specified pip installation."""
46+
source = pathlib.Path(pip_location).resolve().parent
47+
with TempDirectory() as tmp_dir:
48+
pip_zip = os.path.join(tmp_dir.path, "pip.zip")
49+
with zipfile.ZipFile(pip_zip, "w") as zf:
50+
for child in source.rglob("*"):
51+
arcname = child.relative_to(source.parent)
52+
zf.write(child, arcname.as_posix())
53+
yield os.path.join(pip_zip, "pip")
54+
55+
56+
def _install_requirements(
57+
standalone_pip: str,
58+
finder: "PackageFinder",
59+
requirements: Iterable[str],
60+
prefix: _Prefix,
61+
message: str,
62+
) -> None:
63+
args = [
64+
sys.executable, standalone_pip, 'install',
65+
'--ignore-installed', '--no-user', '--prefix', prefix.path,
66+
'--no-warn-script-location',
67+
] # type: List[str]
68+
if logger.getEffectiveLevel() <= logging.DEBUG:
69+
args.append('-v')
70+
for format_control in ('no_binary', 'only_binary'):
71+
formats = getattr(finder.format_control, format_control)
72+
args += [
73+
'--' + format_control.replace('_', '-'),
74+
','.join(sorted(formats or {':none:'}))
75+
]
76+
index_urls = finder.index_urls
77+
if index_urls:
78+
args.extend(['-i', index_urls[0]])
79+
for extra_index in index_urls[1:]:
80+
args.extend(['--extra-index-url', extra_index])
81+
else:
82+
args.append('--no-index')
83+
for link in finder.find_links:
84+
args.extend(['--find-links', link])
85+
86+
for host in finder.trusted_hosts:
87+
args.extend(['--trusted-host', host])
88+
if finder.allow_all_prereleases:
89+
args.append('--pre')
90+
if finder.prefer_binary:
91+
args.append('--prefer-binary')
92+
args.append('--')
93+
args.extend(requirements)
94+
with open_spinner(message) as spinner:
95+
call_subprocess(args, spinner=spinner)
96+
97+
4098
class BuildEnvironment:
4199
"""Creates and manages an isolated environment to install build deps
42100
"""
@@ -160,38 +218,14 @@ def install_requirements(
160218
prefix.setup = True
161219
if not requirements:
162220
return
163-
args = [
164-
sys.executable, os.path.dirname(pip_location), 'install',
165-
'--ignore-installed', '--no-user', '--prefix', prefix.path,
166-
'--no-warn-script-location',
167-
] # type: List[str]
168-
if logger.getEffectiveLevel() <= logging.DEBUG:
169-
args.append('-v')
170-
for format_control in ('no_binary', 'only_binary'):
171-
formats = getattr(finder.format_control, format_control)
172-
args.extend(('--' + format_control.replace('_', '-'),
173-
','.join(sorted(formats or {':none:'}))))
174-
175-
index_urls = finder.index_urls
176-
if index_urls:
177-
args.extend(['-i', index_urls[0]])
178-
for extra_index in index_urls[1:]:
179-
args.extend(['--extra-index-url', extra_index])
180-
else:
181-
args.append('--no-index')
182-
for link in finder.find_links:
183-
args.extend(['--find-links', link])
184-
185-
for host in finder.trusted_hosts:
186-
args.extend(['--trusted-host', host])
187-
if finder.allow_all_prereleases:
188-
args.append('--pre')
189-
if finder.prefer_binary:
190-
args.append('--prefer-binary')
191-
args.append('--')
192-
args.extend(requirements)
193-
with open_spinner(message) as spinner:
194-
call_subprocess(args, spinner=spinner)
221+
with _create_standalone_pip() as standalone_pip:
222+
_install_requirements(
223+
standalone_pip,
224+
finder,
225+
requirements,
226+
prefix,
227+
message,
228+
)
195229

196230

197231
class NoOpBuildEnvironment(BuildEnvironment):

0 commit comments

Comments
 (0)