We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
pip 21.1 install with --no-binary fails while 21.0.1 succeeds (pep517)
### Description

Installing the pip package `pex` with `--no-binary` fails after pip version changed from 21.0.1 to 21.1.  In the output log below, it seems like pep517 is involved.  Steps below are successful if pip==21.0.1 is used.

### Expected behavior

_No response_

### pip version

21.1

### Python version

3.6.4

### OS

RHEL7 x86_64

### How to Reproduce

python3 -m venv venv
. venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade setuptools
python3 -m pip install pex==2.1.30 --no-binary :all:

### Output

```sh-session
Cache entry deserialization failed, entry ignored
Collecting pip
  Using cached https://files.pythonhosted.org/packages/ac/cf/0cc542fc93de2f3b9b53cb979c7d1118cffb93204afb46299a9f858e113f/pip-21.1-py3-none-any.whl
Installing collected packages: pip
  Found existing installation: pip 9.0.1
    Uninstalling pip-9.0.1:
      Successfully uninstalled pip-9.0.1
Successfully installed pip-21.1

Requirement already satisfied: setuptools in ./venv/lib/python3.6/site-packages (28.8.0)
Collecting setuptools
  Using cached setuptools-56.0.0-py3-none-any.whl (784 kB)
Installing collected packages: setuptools
  Attempting uninstall: setuptools
    Found existing installation: setuptools 28.8.0
    Uninstalling setuptools-28.8.0:
      Successfully uninstalled setuptools-28.8.0
Successfully installed setuptools-56.0.0

Collecting pex==2.1.30
  Downloading pex-2.1.30.tar.gz (3.3 MB)
     |████████████████████████████████| 3.3 MB 3.0 MB/s 
  Installing build dependencies ... error
  ERROR: Command errored out with exit status 1:
   command: <path to venv>/venv/bin/python3 /tmp/pip-standalone-pip-5xbqguwg/__env_pip__.zip/pip install --ignore-installed --no-user --prefix /tmp/pip-build-env-3b3hrzfg/overlay --no-warn-script-location --no-binary :all: --only-binary :none: -i https://pypi.org/simple -- 'flit_core >=2,<3'
       cwd: None
  Complete output (67 lines):
  Collecting flit_core<3,>=2
    Using cached flit_core-2.3.0.tar.gz (22 kB)
    Getting requirements to build wheel: started
    Getting requirements to build wheel: finished with status 'error'
    ERROR: Command errored out with exit status 1:
     command: <path to venv>/venv/bin/python3 /tmp/pip-standalone-pip-5xbqguwg/__env_pip__.zip/pip/_vendor/pep517/in_process/_in_process.py get_requires_for_build_wheel /tmp/tmpogp2e7mb
         cwd: /tmp/pip-install-71xy4ixf/flit-core_156db09074064d12968592391ad52e71
    Complete output (1 lines):
    <path to venv>/venv/bin/python3: can't find '__main__' module in '/tmp/pip-standalone-pip-5xbqguwg/__env_pip__.zip/pip/_vendor/pep517/in_process/_in_process.py'

^repeated error while it tries earlier versions of flit_core
```


### Code of Conduct

- [X] I agree to follow the [PSF Code of Conduct](https://www.python.org/psf/conduct/).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/pip/_internal/build_env.py`
Content:
```
1 """Build Environment used for isolation during sdist building
2 """
3 
4 import contextlib
5 import logging
6 import os
7 import pathlib
8 import sys
9 import textwrap
10 import zipfile
11 from collections import OrderedDict
12 from sysconfig import get_paths
13 from types import TracebackType
14 from typing import TYPE_CHECKING, Iterable, Iterator, List, Optional, Set, Tuple, Type
15 
16 from pip._vendor.certifi import where
17 from pip._vendor.pkg_resources import Requirement, VersionConflict, WorkingSet
18 
19 from pip import __file__ as pip_location
20 from pip._internal.cli.spinners import open_spinner
21 from pip._internal.locations import get_platlib, get_prefixed_libs, get_purelib
22 from pip._internal.utils.subprocess import call_subprocess
23 from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds
24 
25 if TYPE_CHECKING:
26     from pip._internal.index.package_finder import PackageFinder
27 
28 logger = logging.getLogger(__name__)
29 
30 
31 class _Prefix:
32 
33     def __init__(self, path):
34         # type: (str) -> None
35         self.path = path
36         self.setup = False
37         self.bin_dir = get_paths(
38             'nt' if os.name == 'nt' else 'posix_prefix',
39             vars={'base': path, 'platbase': path}
40         )['scripts']
41         self.lib_dirs = get_prefixed_libs(path)
42 
43 
44 @contextlib.contextmanager
45 def _create_standalone_pip() -> Iterator[str]:
46     """Create a "standalone pip" zip file.
47 
48     The zip file's content is identical to the currently-running pip.
49     It will be used to install requirements into the build environment.
50     """
51     source = pathlib.Path(pip_location).resolve().parent
52 
53     # Return the current instance if it is already a zip file. This can happen
54     # if a PEP 517 requirement is an sdist itself.
55     if not source.is_dir() and source.parent.name == "__env_pip__.zip":
56         yield str(source)
57         return
58 
59     with TempDirectory(kind="standalone-pip") as tmp_dir:
60         pip_zip = os.path.join(tmp_dir.path, "__env_pip__.zip")
61         with zipfile.ZipFile(pip_zip, "w") as zf:
62             for child in source.rglob("*"):
63                 zf.write(child, child.relative_to(source.parent).as_posix())
64         yield os.path.join(pip_zip, "pip")
65 
66 
67 class BuildEnvironment:
68     """Creates and manages an isolated environment to install build deps
69     """
70 
71     def __init__(self):
72         # type: () -> None
73         temp_dir = TempDirectory(
74             kind=tempdir_kinds.BUILD_ENV, globally_managed=True
75         )
76 
77         self._prefixes = OrderedDict(
78             (name, _Prefix(os.path.join(temp_dir.path, name)))
79             for name in ('normal', 'overlay')
80         )
81 
82         self._bin_dirs = []  # type: List[str]
83         self._lib_dirs = []  # type: List[str]
84         for prefix in reversed(list(self._prefixes.values())):
85             self._bin_dirs.append(prefix.bin_dir)
86             self._lib_dirs.extend(prefix.lib_dirs)
87 
88         # Customize site to:
89         # - ensure .pth files are honored
90         # - prevent access to system site packages
91         system_sites = {
92             os.path.normcase(site) for site in (get_purelib(), get_platlib())
93         }
94         self._site_dir = os.path.join(temp_dir.path, 'site')
95         if not os.path.exists(self._site_dir):
96             os.mkdir(self._site_dir)
97         with open(os.path.join(self._site_dir, 'sitecustomize.py'), 'w') as fp:
98             fp.write(textwrap.dedent(
99                 '''
100                 import os, site, sys
101 
102                 # First, drop system-sites related paths.
103                 original_sys_path = sys.path[:]
104                 known_paths = set()
105                 for path in {system_sites!r}:
106                     site.addsitedir(path, known_paths=known_paths)
107                 system_paths = set(
108                     os.path.normcase(path)
109                     for path in sys.path[len(original_sys_path):]
110                 )
111                 original_sys_path = [
112                     path for path in original_sys_path
113                     if os.path.normcase(path) not in system_paths
114                 ]
115                 sys.path = original_sys_path
116 
117                 # Second, add lib directories.
118                 # ensuring .pth file are processed.
119                 for path in {lib_dirs!r}:
120                     assert not path in sys.path
121                     site.addsitedir(path)
122                 '''
123             ).format(system_sites=system_sites, lib_dirs=self._lib_dirs))
124 
125     def __enter__(self):
126         # type: () -> None
127         self._save_env = {
128             name: os.environ.get(name, None)
129             for name in ('PATH', 'PYTHONNOUSERSITE', 'PYTHONPATH')
130         }
131 
132         path = self._bin_dirs[:]
133         old_path = self._save_env['PATH']
134         if old_path:
135             path.extend(old_path.split(os.pathsep))
136 
137         pythonpath = [self._site_dir]
138 
139         os.environ.update({
140             'PATH': os.pathsep.join(path),
141             'PYTHONNOUSERSITE': '1',
142             'PYTHONPATH': os.pathsep.join(pythonpath),
143         })
144 
145     def __exit__(
146         self,
147         exc_type,  # type: Optional[Type[BaseException]]
148         exc_val,  # type: Optional[BaseException]
149         exc_tb  # type: Optional[TracebackType]
150     ):
151         # type: (...) -> None
152         for varname, old_value in self._save_env.items():
153             if old_value is None:
154                 os.environ.pop(varname, None)
155             else:
156                 os.environ[varname] = old_value
157 
158     def check_requirements(self, reqs):
159         # type: (Iterable[str]) -> Tuple[Set[Tuple[str, str]], Set[str]]
160         """Return 2 sets:
161             - conflicting requirements: set of (installed, wanted) reqs tuples
162             - missing requirements: set of reqs
163         """
164         missing = set()
165         conflicting = set()
166         if reqs:
167             ws = WorkingSet(self._lib_dirs)
168             for req in reqs:
169                 try:
170                     if ws.find(Requirement.parse(req)) is None:
171                         missing.add(req)
172                 except VersionConflict as e:
173                     conflicting.add((str(e.args[0].as_requirement()),
174                                      str(e.args[1])))
175         return conflicting, missing
176 
177     def install_requirements(
178         self,
179         finder,  # type: PackageFinder
180         requirements,  # type: Iterable[str]
181         prefix_as_string,  # type: str
182         message  # type: str
183     ):
184         # type: (...) -> None
185         prefix = self._prefixes[prefix_as_string]
186         assert not prefix.setup
187         prefix.setup = True
188         if not requirements:
189             return
190         with _create_standalone_pip() as standalone_pip:
191             self._install_requirements(
192                 standalone_pip,
193                 finder,
194                 requirements,
195                 prefix,
196                 message,
197             )
198 
199     @staticmethod
200     def _install_requirements(
201         standalone_pip: str,
202         finder: "PackageFinder",
203         requirements: Iterable[str],
204         prefix: _Prefix,
205         message: str,
206     ) -> None:
207         args = [
208             sys.executable, standalone_pip, 'install',
209             '--ignore-installed', '--no-user', '--prefix', prefix.path,
210             '--no-warn-script-location',
211         ]  # type: List[str]
212         if logger.getEffectiveLevel() <= logging.DEBUG:
213             args.append('-v')
214         for format_control in ('no_binary', 'only_binary'):
215             formats = getattr(finder.format_control, format_control)
216             args.extend(('--' + format_control.replace('_', '-'),
217                          ','.join(sorted(formats or {':none:'}))))
218 
219         index_urls = finder.index_urls
220         if index_urls:
221             args.extend(['-i', index_urls[0]])
222             for extra_index in index_urls[1:]:
223                 args.extend(['--extra-index-url', extra_index])
224         else:
225             args.append('--no-index')
226         for link in finder.find_links:
227             args.extend(['--find-links', link])
228 
229         for host in finder.trusted_hosts:
230             args.extend(['--trusted-host', host])
231         if finder.allow_all_prereleases:
232             args.append('--pre')
233         if finder.prefer_binary:
234             args.append('--prefer-binary')
235         args.append('--')
236         args.extend(requirements)
237         extra_environ = {"_PIP_STANDALONE_CERT": where()}
238         with open_spinner(message) as spinner:
239             call_subprocess(args, spinner=spinner, extra_environ=extra_environ)
240 
241 
242 class NoOpBuildEnvironment(BuildEnvironment):
243     """A no-op drop-in replacement for BuildEnvironment
244     """
245 
246     def __init__(self):
247         # type: () -> None
248         pass
249 
250     def __enter__(self):
251         # type: () -> None
252         pass
253 
254     def __exit__(
255         self,
256         exc_type,  # type: Optional[Type[BaseException]]
257         exc_val,  # type: Optional[BaseException]
258         exc_tb  # type: Optional[TracebackType]
259     ):
260         # type: (...) -> None
261         pass
262 
263     def cleanup(self):
264         # type: () -> None
265         pass
266 
267     def install_requirements(
268         self,
269         finder,  # type: PackageFinder
270         requirements,  # type: Iterable[str]
271         prefix_as_string,  # type: str
272         message  # type: str
273     ):
274         # type: (...) -> None
275         raise NotImplementedError()
276
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/pip/_internal/build_env.py b/src/pip/_internal/build_env.py
--- a/src/pip/_internal/build_env.py
+++ b/src/pip/_internal/build_env.py
@@ -187,9 +187,17 @@
         prefix.setup = True
         if not requirements:
             return
-        with _create_standalone_pip() as standalone_pip:
+        with contextlib.ExitStack() as ctx:
+            # TODO: Remove this block when dropping 3.6 support. Python 3.6
+            # lacks importlib.resources and pep517 has issues loading files in
+            # a zip, so we fallback to the "old" method by adding the current
+            # pip directory to the child process's sys.path.
+            if sys.version_info < (3, 7):
+                pip_runnable = os.path.dirname(pip_location)
+            else:
+                pip_runnable = ctx.enter_context(_create_standalone_pip())
             self._install_requirements(
-                standalone_pip,
+                pip_runnable,
                 finder,
                 requirements,
                 prefix,
@@ -198,14 +206,14 @@
 
     @staticmethod
     def _install_requirements(
-        standalone_pip: str,
+        pip_runnable: str,
         finder: "PackageFinder",
         requirements: Iterable[str],
         prefix: _Prefix,
         message: str,
     ) -> None:
         args = [
-            sys.executable, standalone_pip, 'install',
+            sys.executable, pip_runnable, 'install',
             '--ignore-installed', '--no-user', '--prefix', prefix.path,
             '--no-warn-script-location',
         ]  # type: List[str]

{"golden_diff": "diff --git a/src/pip/_internal/build_env.py b/src/pip/_internal/build_env.py\n--- a/src/pip/_internal/build_env.py\n+++ b/src/pip/_internal/build_env.py\n@@ -187,9 +187,17 @@\n         prefix.setup = True\n         if not requirements:\n             return\n-        with _create_standalone_pip() as standalone_pip:\n+        with contextlib.ExitStack() as ctx:\n+            # TODO: Remove this block when dropping 3.6 support. Python 3.6\n+            # lacks importlib.resources and pep517 has issues loading files in\n+            # a zip, so we fallback to the \"old\" method by adding the current\n+            # pip directory to the child process's sys.path.\n+            if sys.version_info < (3, 7):\n+                pip_runnable = os.path.dirname(pip_location)\n+            else:\n+                pip_runnable = ctx.enter_context(_create_standalone_pip())\n             self._install_requirements(\n-                standalone_pip,\n+                pip_runnable,\n                 finder,\n                 requirements,\n                 prefix,\n@@ -198,14 +206,14 @@\n \n     @staticmethod\n     def _install_requirements(\n-        standalone_pip: str,\n+        pip_runnable: str,\n         finder: \"PackageFinder\",\n         requirements: Iterable[str],\n         prefix: _Prefix,\n         message: str,\n     ) -> None:\n         args = [\n-            sys.executable, standalone_pip, 'install',\n+            sys.executable, pip_runnable, 'install',\n             '--ignore-installed', '--no-user', '--prefix', prefix.path,\n             '--no-warn-script-location',\n         ]  # type: List[str]\n", "issue": "pip 21.1 install with --no-binary fails while 21.0.1 succeeds (pep517)\n### Description\n\nInstalling the pip package `pex` with `--no-binary` fails after pip version changed from 21.0.1 to 21.1.  In the output log below, it seems like pep517 is involved.  Steps below are successful if pip==21.0.1 is used.\n\n### Expected behavior\n\n_No response_\n\n### pip version\n\n21.1\n\n### Python version\n\n3.6.4\n\n### OS\n\nRHEL7 x86_64\n\n### How to Reproduce\n\npython3 -m venv venv\r\n. venv/bin/activate\r\npython3 -m pip install --upgrade pip\r\npython3 -m pip install --upgrade setuptools\r\npython3 -m pip install pex==2.1.30 --no-binary :all:\n\n### Output\n\n```sh-session\nCache entry deserialization failed, entry ignored\r\nCollecting pip\r\n  Using cached https://files.pythonhosted.org/packages/ac/cf/0cc542fc93de2f3b9b53cb979c7d1118cffb93204afb46299a9f858e113f/pip-21.1-py3-none-any.whl\r\nInstalling collected packages: pip\r\n  Found existing installation: pip 9.0.1\r\n    Uninstalling pip-9.0.1:\r\n      Successfully uninstalled pip-9.0.1\r\nSuccessfully installed pip-21.1\r\n\r\nRequirement already satisfied: setuptools in ./venv/lib/python3.6/site-packages (28.8.0)\r\nCollecting setuptools\r\n  Using cached setuptools-56.0.0-py3-none-any.whl (784 kB)\r\nInstalling collected packages: setuptools\r\n  Attempting uninstall: setuptools\r\n    Found existing installation: setuptools 28.8.0\r\n    Uninstalling setuptools-28.8.0:\r\n      Successfully uninstalled setuptools-28.8.0\r\nSuccessfully installed setuptools-56.0.0\r\n\r\nCollecting pex==2.1.30\r\n  Downloading pex-2.1.30.tar.gz (3.3 MB)\r\n     |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 3.3 MB 3.0 MB/s \r\n  Installing build dependencies ... error\r\n  ERROR: Command errored out with exit status 1:\r\n   command: <path to venv>/venv/bin/python3 /tmp/pip-standalone-pip-5xbqguwg/__env_pip__.zip/pip install --ignore-installed --no-user --prefix /tmp/pip-build-env-3b3hrzfg/overlay --no-warn-script-location --no-binary :all: --only-binary :none: -i https://pypi.org/simple -- 'flit_core >=2,<3'\r\n       cwd: None\r\n  Complete output (67 lines):\r\n  Collecting flit_core<3,>=2\r\n    Using cached flit_core-2.3.0.tar.gz (22 kB)\r\n    Getting requirements to build wheel: started\r\n    Getting requirements to build wheel: finished with status 'error'\r\n    ERROR: Command errored out with exit status 1:\r\n     command: <path to venv>/venv/bin/python3 /tmp/pip-standalone-pip-5xbqguwg/__env_pip__.zip/pip/_vendor/pep517/in_process/_in_process.py get_requires_for_build_wheel /tmp/tmpogp2e7mb\r\n         cwd: /tmp/pip-install-71xy4ixf/flit-core_156db09074064d12968592391ad52e71\r\n    Complete output (1 lines):\r\n    <path to venv>/venv/bin/python3: can't find '__main__' module in '/tmp/pip-standalone-pip-5xbqguwg/__env_pip__.zip/pip/_vendor/pep517/in_process/_in_process.py'\r\n\r\n^repeated error while it tries earlier versions of flit_core\n```\n\n\n### Code of Conduct\n\n- [X] I agree to follow the [PSF Code of Conduct](https://www.python.org/psf/conduct/).\n", "before_files": [{"content": "\"\"\"Build Environment used for isolation during sdist building\n\"\"\"\n\nimport contextlib\nimport logging\nimport os\nimport pathlib\nimport sys\nimport textwrap\nimport zipfile\nfrom collections import OrderedDict\nfrom sysconfig import get_paths\nfrom types import TracebackType\nfrom typing import TYPE_CHECKING, Iterable, Iterator, List, Optional, Set, Tuple, Type\n\nfrom pip._vendor.certifi import where\nfrom pip._vendor.pkg_resources import Requirement, VersionConflict, WorkingSet\n\nfrom pip import __file__ as pip_location\nfrom pip._internal.cli.spinners import open_spinner\nfrom pip._internal.locations import get_platlib, get_prefixed_libs, get_purelib\nfrom pip._internal.utils.subprocess import call_subprocess\nfrom pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds\n\nif TYPE_CHECKING:\n    from pip._internal.index.package_finder import PackageFinder\n\nlogger = logging.getLogger(__name__)\n\n\nclass _Prefix:\n\n    def __init__(self, path):\n        # type: (str) -> None\n        self.path = path\n        self.setup = False\n        self.bin_dir = get_paths(\n            'nt' if os.name == 'nt' else 'posix_prefix',\n            vars={'base': path, 'platbase': path}\n        )['scripts']\n        self.lib_dirs = get_prefixed_libs(path)\n\n\n@contextlib.contextmanager\ndef _create_standalone_pip() -> Iterator[str]:\n    \"\"\"Create a \"standalone pip\" zip file.\n\n    The zip file's content is identical to the currently-running pip.\n    It will be used to install requirements into the build environment.\n    \"\"\"\n    source = pathlib.Path(pip_location).resolve().parent\n\n    # Return the current instance if it is already a zip file. This can happen\n    # if a PEP 517 requirement is an sdist itself.\n    if not source.is_dir() and source.parent.name == \"__env_pip__.zip\":\n        yield str(source)\n        return\n\n    with TempDirectory(kind=\"standalone-pip\") as tmp_dir:\n        pip_zip = os.path.join(tmp_dir.path, \"__env_pip__.zip\")\n        with zipfile.ZipFile(pip_zip, \"w\") as zf:\n            for child in source.rglob(\"*\"):\n                zf.write(child, child.relative_to(source.parent).as_posix())\n        yield os.path.join(pip_zip, \"pip\")\n\n\nclass BuildEnvironment:\n    \"\"\"Creates and manages an isolated environment to install build deps\n    \"\"\"\n\n    def __init__(self):\n        # type: () -> None\n        temp_dir = TempDirectory(\n            kind=tempdir_kinds.BUILD_ENV, globally_managed=True\n        )\n\n        self._prefixes = OrderedDict(\n            (name, _Prefix(os.path.join(temp_dir.path, name)))\n            for name in ('normal', 'overlay')\n        )\n\n        self._bin_dirs = []  # type: List[str]\n        self._lib_dirs = []  # type: List[str]\n        for prefix in reversed(list(self._prefixes.values())):\n            self._bin_dirs.append(prefix.bin_dir)\n            self._lib_dirs.extend(prefix.lib_dirs)\n\n        # Customize site to:\n        # - ensure .pth files are honored\n        # - prevent access to system site packages\n        system_sites = {\n            os.path.normcase(site) for site in (get_purelib(), get_platlib())\n        }\n        self._site_dir = os.path.join(temp_dir.path, 'site')\n        if not os.path.exists(self._site_dir):\n            os.mkdir(self._site_dir)\n        with open(os.path.join(self._site_dir, 'sitecustomize.py'), 'w') as fp:\n            fp.write(textwrap.dedent(\n                '''\n                import os, site, sys\n\n                # First, drop system-sites related paths.\n                original_sys_path = sys.path[:]\n                known_paths = set()\n                for path in {system_sites!r}:\n                    site.addsitedir(path, known_paths=known_paths)\n                system_paths = set(\n                    os.path.normcase(path)\n                    for path in sys.path[len(original_sys_path):]\n                )\n                original_sys_path = [\n                    path for path in original_sys_path\n                    if os.path.normcase(path) not in system_paths\n                ]\n                sys.path = original_sys_path\n\n                # Second, add lib directories.\n                # ensuring .pth file are processed.\n                for path in {lib_dirs!r}:\n                    assert not path in sys.path\n                    site.addsitedir(path)\n                '''\n            ).format(system_sites=system_sites, lib_dirs=self._lib_dirs))\n\n    def __enter__(self):\n        # type: () -> None\n        self._save_env = {\n            name: os.environ.get(name, None)\n            for name in ('PATH', 'PYTHONNOUSERSITE', 'PYTHONPATH')\n        }\n\n        path = self._bin_dirs[:]\n        old_path = self._save_env['PATH']\n        if old_path:\n            path.extend(old_path.split(os.pathsep))\n\n        pythonpath = [self._site_dir]\n\n        os.environ.update({\n            'PATH': os.pathsep.join(path),\n            'PYTHONNOUSERSITE': '1',\n            'PYTHONPATH': os.pathsep.join(pythonpath),\n        })\n\n    def __exit__(\n        self,\n        exc_type,  # type: Optional[Type[BaseException]]\n        exc_val,  # type: Optional[BaseException]\n        exc_tb  # type: Optional[TracebackType]\n    ):\n        # type: (...) -> None\n        for varname, old_value in self._save_env.items():\n            if old_value is None:\n                os.environ.pop(varname, None)\n            else:\n                os.environ[varname] = old_value\n\n    def check_requirements(self, reqs):\n        # type: (Iterable[str]) -> Tuple[Set[Tuple[str, str]], Set[str]]\n        \"\"\"Return 2 sets:\n            - conflicting requirements: set of (installed, wanted) reqs tuples\n            - missing requirements: set of reqs\n        \"\"\"\n        missing = set()\n        conflicting = set()\n        if reqs:\n            ws = WorkingSet(self._lib_dirs)\n            for req in reqs:\n                try:\n                    if ws.find(Requirement.parse(req)) is None:\n                        missing.add(req)\n                except VersionConflict as e:\n                    conflicting.add((str(e.args[0].as_requirement()),\n                                     str(e.args[1])))\n        return conflicting, missing\n\n    def install_requirements(\n        self,\n        finder,  # type: PackageFinder\n        requirements,  # type: Iterable[str]\n        prefix_as_string,  # type: str\n        message  # type: str\n    ):\n        # type: (...) -> None\n        prefix = self._prefixes[prefix_as_string]\n        assert not prefix.setup\n        prefix.setup = True\n        if not requirements:\n            return\n        with _create_standalone_pip() as standalone_pip:\n            self._install_requirements(\n                standalone_pip,\n                finder,\n                requirements,\n                prefix,\n                message,\n            )\n\n    @staticmethod\n    def _install_requirements(\n        standalone_pip: str,\n        finder: \"PackageFinder\",\n        requirements: Iterable[str],\n        prefix: _Prefix,\n        message: str,\n    ) -> None:\n        args = [\n            sys.executable, standalone_pip, 'install',\n            '--ignore-installed', '--no-user', '--prefix', prefix.path,\n            '--no-warn-script-location',\n        ]  # type: List[str]\n        if logger.getEffectiveLevel() <= logging.DEBUG:\n            args.append('-v')\n        for format_control in ('no_binary', 'only_binary'):\n            formats = getattr(finder.format_control, format_control)\n            args.extend(('--' + format_control.replace('_', '-'),\n                         ','.join(sorted(formats or {':none:'}))))\n\n        index_urls = finder.index_urls\n        if index_urls:\n            args.extend(['-i', index_urls[0]])\n            for extra_index in index_urls[1:]:\n                args.extend(['--extra-index-url', extra_index])\n        else:\n            args.append('--no-index')\n        for link in finder.find_links:\n            args.extend(['--find-links', link])\n\n        for host in finder.trusted_hosts:\n            args.extend(['--trusted-host', host])\n        if finder.allow_all_prereleases:\n            args.append('--pre')\n        if finder.prefer_binary:\n            args.append('--prefer-binary')\n        args.append('--')\n        args.extend(requirements)\n        extra_environ = {\"_PIP_STANDALONE_CERT\": where()}\n        with open_spinner(message) as spinner:\n            call_subprocess(args, spinner=spinner, extra_environ=extra_environ)\n\n\nclass NoOpBuildEnvironment(BuildEnvironment):\n    \"\"\"A no-op drop-in replacement for BuildEnvironment\n    \"\"\"\n\n    def __init__(self):\n        # type: () -> None\n        pass\n\n    def __enter__(self):\n        # type: () -> None\n        pass\n\n    def __exit__(\n        self,\n        exc_type,  # type: Optional[Type[BaseException]]\n        exc_val,  # type: Optional[BaseException]\n        exc_tb  # type: Optional[TracebackType]\n    ):\n        # type: (...) -> None\n        pass\n\n    def cleanup(self):\n        # type: () -> None\n        pass\n\n    def install_requirements(\n        self,\n        finder,  # type: PackageFinder\n        requirements,  # type: Iterable[str]\n        prefix_as_string,  # type: str\n        message  # type: str\n    ):\n        # type: (...) -> None\n        raise NotImplementedError()\n", "path": "src/pip/_internal/build_env.py"}], "after_files": [{"content": "\"\"\"Build Environment used for isolation during sdist building\n\"\"\"\n\nimport contextlib\nimport logging\nimport os\nimport pathlib\nimport sys\nimport textwrap\nimport zipfile\nfrom collections import OrderedDict\nfrom sysconfig import get_paths\nfrom types import TracebackType\nfrom typing import TYPE_CHECKING, Iterable, Iterator, List, Optional, Set, Tuple, Type\n\nfrom pip._vendor.certifi import where\nfrom pip._vendor.pkg_resources import Requirement, VersionConflict, WorkingSet\n\nfrom pip import __file__ as pip_location\nfrom pip._internal.cli.spinners import open_spinner\nfrom pip._internal.locations import get_platlib, get_prefixed_libs, get_purelib\nfrom pip._internal.utils.subprocess import call_subprocess\nfrom pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds\n\nif TYPE_CHECKING:\n    from pip._internal.index.package_finder import PackageFinder\n\nlogger = logging.getLogger(__name__)\n\n\nclass _Prefix:\n\n    def __init__(self, path):\n        # type: (str) -> None\n        self.path = path\n        self.setup = False\n        self.bin_dir = get_paths(\n            'nt' if os.name == 'nt' else 'posix_prefix',\n            vars={'base': path, 'platbase': path}\n        )['scripts']\n        self.lib_dirs = get_prefixed_libs(path)\n\n\n@contextlib.contextmanager\ndef _create_standalone_pip() -> Iterator[str]:\n    \"\"\"Create a \"standalone pip\" zip file.\n\n    The zip file's content is identical to the currently-running pip.\n    It will be used to install requirements into the build environment.\n    \"\"\"\n    source = pathlib.Path(pip_location).resolve().parent\n\n    # Return the current instance if it is already a zip file. This can happen\n    # if a PEP 517 requirement is an sdist itself.\n    if not source.is_dir() and source.parent.name == \"__env_pip__.zip\":\n        yield str(source)\n        return\n\n    with TempDirectory(kind=\"standalone-pip\") as tmp_dir:\n        pip_zip = os.path.join(tmp_dir.path, \"__env_pip__.zip\")\n        with zipfile.ZipFile(pip_zip, \"w\") as zf:\n            for child in source.rglob(\"*\"):\n                zf.write(child, child.relative_to(source.parent).as_posix())\n        yield os.path.join(pip_zip, \"pip\")\n\n\nclass BuildEnvironment:\n    \"\"\"Creates and manages an isolated environment to install build deps\n    \"\"\"\n\n    def __init__(self):\n        # type: () -> None\n        temp_dir = TempDirectory(\n            kind=tempdir_kinds.BUILD_ENV, globally_managed=True\n        )\n\n        self._prefixes = OrderedDict(\n            (name, _Prefix(os.path.join(temp_dir.path, name)))\n            for name in ('normal', 'overlay')\n        )\n\n        self._bin_dirs = []  # type: List[str]\n        self._lib_dirs = []  # type: List[str]\n        for prefix in reversed(list(self._prefixes.values())):\n            self._bin_dirs.append(prefix.bin_dir)\n            self._lib_dirs.extend(prefix.lib_dirs)\n\n        # Customize site to:\n        # - ensure .pth files are honored\n        # - prevent access to system site packages\n        system_sites = {\n            os.path.normcase(site) for site in (get_purelib(), get_platlib())\n        }\n        self._site_dir = os.path.join(temp_dir.path, 'site')\n        if not os.path.exists(self._site_dir):\n            os.mkdir(self._site_dir)\n        with open(os.path.join(self._site_dir, 'sitecustomize.py'), 'w') as fp:\n            fp.write(textwrap.dedent(\n                '''\n                import os, site, sys\n\n                # First, drop system-sites related paths.\n                original_sys_path = sys.path[:]\n                known_paths = set()\n                for path in {system_sites!r}:\n                    site.addsitedir(path, known_paths=known_paths)\n                system_paths = set(\n                    os.path.normcase(path)\n                    for path in sys.path[len(original_sys_path):]\n                )\n                original_sys_path = [\n                    path for path in original_sys_path\n                    if os.path.normcase(path) not in system_paths\n                ]\n                sys.path = original_sys_path\n\n                # Second, add lib directories.\n                # ensuring .pth file are processed.\n                for path in {lib_dirs!r}:\n                    assert not path in sys.path\n                    site.addsitedir(path)\n                '''\n            ).format(system_sites=system_sites, lib_dirs=self._lib_dirs))\n\n    def __enter__(self):\n        # type: () -> None\n        self._save_env = {\n            name: os.environ.get(name, None)\n            for name in ('PATH', 'PYTHONNOUSERSITE', 'PYTHONPATH')\n        }\n\n        path = self._bin_dirs[:]\n        old_path = self._save_env['PATH']\n        if old_path:\n            path.extend(old_path.split(os.pathsep))\n\n        pythonpath = [self._site_dir]\n\n        os.environ.update({\n            'PATH': os.pathsep.join(path),\n            'PYTHONNOUSERSITE': '1',\n            'PYTHONPATH': os.pathsep.join(pythonpath),\n        })\n\n    def __exit__(\n        self,\n        exc_type,  # type: Optional[Type[BaseException]]\n        exc_val,  # type: Optional[BaseException]\n        exc_tb  # type: Optional[TracebackType]\n    ):\n        # type: (...) -> None\n        for varname, old_value in self._save_env.items():\n            if old_value is None:\n                os.environ.pop(varname, None)\n            else:\n                os.environ[varname] = old_value\n\n    def check_requirements(self, reqs):\n        # type: (Iterable[str]) -> Tuple[Set[Tuple[str, str]], Set[str]]\n        \"\"\"Return 2 sets:\n            - conflicting requirements: set of (installed, wanted) reqs tuples\n            - missing requirements: set of reqs\n        \"\"\"\n        missing = set()\n        conflicting = set()\n        if reqs:\n            ws = WorkingSet(self._lib_dirs)\n            for req in reqs:\n                try:\n                    if ws.find(Requirement.parse(req)) is None:\n                        missing.add(req)\n                except VersionConflict as e:\n                    conflicting.add((str(e.args[0].as_requirement()),\n                                     str(e.args[1])))\n        return conflicting, missing\n\n    def install_requirements(\n        self,\n        finder,  # type: PackageFinder\n        requirements,  # type: Iterable[str]\n        prefix_as_string,  # type: str\n        message  # type: str\n    ):\n        # type: (...) -> None\n        prefix = self._prefixes[prefix_as_string]\n        assert not prefix.setup\n        prefix.setup = True\n        if not requirements:\n            return\n        with contextlib.ExitStack() as ctx:\n            # TODO: Remove this block when dropping 3.6 support. Python 3.6\n            # lacks importlib.resources and pep517 has issues loading files in\n            # a zip, so we fallback to the \"old\" method by adding the current\n            # pip directory to the child process's sys.path.\n            if sys.version_info < (3, 7):\n                pip_runnable = os.path.dirname(pip_location)\n            else:\n                pip_runnable = ctx.enter_context(_create_standalone_pip())\n            self._install_requirements(\n                pip_runnable,\n                finder,\n                requirements,\n                prefix,\n                message,\n            )\n\n    @staticmethod\n    def _install_requirements(\n        pip_runnable: str,\n        finder: \"PackageFinder\",\n        requirements: Iterable[str],\n        prefix: _Prefix,\n        message: str,\n    ) -> None:\n        args = [\n            sys.executable, pip_runnable, 'install',\n            '--ignore-installed', '--no-user', '--prefix', prefix.path,\n            '--no-warn-script-location',\n        ]  # type: List[str]\n        if logger.getEffectiveLevel() <= logging.DEBUG:\n            args.append('-v')\n        for format_control in ('no_binary', 'only_binary'):\n            formats = getattr(finder.format_control, format_control)\n            args.extend(('--' + format_control.replace('_', '-'),\n                         ','.join(sorted(formats or {':none:'}))))\n\n        index_urls = finder.index_urls\n        if index_urls:\n            args.extend(['-i', index_urls[0]])\n            for extra_index in index_urls[1:]:\n                args.extend(['--extra-index-url', extra_index])\n        else:\n            args.append('--no-index')\n        for link in finder.find_links:\n            args.extend(['--find-links', link])\n\n        for host in finder.trusted_hosts:\n            args.extend(['--trusted-host', host])\n        if finder.allow_all_prereleases:\n            args.append('--pre')\n        if finder.prefer_binary:\n            args.append('--prefer-binary')\n        args.append('--')\n        args.extend(requirements)\n        extra_environ = {\"_PIP_STANDALONE_CERT\": where()}\n        with open_spinner(message) as spinner:\n            call_subprocess(args, spinner=spinner, extra_environ=extra_environ)\n\n\nclass NoOpBuildEnvironment(BuildEnvironment):\n    \"\"\"A no-op drop-in replacement for BuildEnvironment\n    \"\"\"\n\n    def __init__(self):\n        # type: () -> None\n        pass\n\n    def __enter__(self):\n        # type: () -> None\n        pass\n\n    def __exit__(\n        self,\n        exc_type,  # type: Optional[Type[BaseException]]\n        exc_val,  # type: Optional[BaseException]\n        exc_tb  # type: Optional[TracebackType]\n    ):\n        # type: (...) -> None\n        pass\n\n    def cleanup(self):\n        # type: () -> None\n        pass\n\n    def install_requirements(\n        self,\n        finder,  # type: PackageFinder\n        requirements,  # type: Iterable[str]\n        prefix_as_string,  # type: str\n        message  # type: str\n    ):\n        # type: (...) -> None\n        raise NotImplementedError()\n", "path": "src/pip/_internal/build_env.py"}]}