We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Don't install setup_requires when run as a PEP 517 backend
PEP 517 separates the responsibilities around build requirements: the backend is responsible for saying what is required, and the frontend is responsible for ensuring they're available to the build.

In setuptools, build requirements are defined by `setup_requires`, and these get passed through to PEP 517's `get_requires_for_build_*` hooks. There is a monkeypatch to return them from these hooks and prevent setuptools trying to install them itself:

https://github.com/pypa/setuptools/blob/5e60dc50e540a942aeb558aabe7d92ab7eb13d4b/setuptools/build_meta.py#L56-L75

But something similar to that - preventing installation - should really be in place for all the PEP 517 hooks, because a PEP 517 backend isn't responsible for installing dependencies.

Why does this matter? Pip has the `--no-build-isolation` option, with which the caller can declare that they have taken care of build dependencies and pip should try to build the package in the current environment. This is useful for downstream packagers, and for experimenting with different versions of your build dependencies. But setuptools doesn't know about this, so it charges ahead and attempts to install things when that's not what you want.

The workaround I'm looking at is to only specify `setup_requires` if `'egg_info' in sys.argv`, as is the case when the `get_requires_for_build_*` hooks are called. But this is clearly not ideal.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `setuptools/build_meta.py`
Content:
```
1 """A PEP 517 interface to setuptools
2 
3 Previously, when a user or a command line tool (let's call it a "frontend")
4 needed to make a request of setuptools to take a certain action, for
5 example, generating a list of installation requirements, the frontend would
6 would call "setup.py egg_info" or "setup.py bdist_wheel" on the command line.
7 
8 PEP 517 defines a different method of interfacing with setuptools. Rather
9 than calling "setup.py" directly, the frontend should:
10 
11   1. Set the current directory to the directory with a setup.py file
12   2. Import this module into a safe python interpreter (one in which
13      setuptools can potentially set global variables or crash hard).
14   3. Call one of the functions defined in PEP 517.
15 
16 What each function does is defined in PEP 517. However, here is a "casual"
17 definition of the functions (this definition should not be relied on for
18 bug reports or API stability):
19 
20   - `build_wheel`: build a wheel in the folder and return the basename
21   - `get_requires_for_build_wheel`: get the `setup_requires` to build
22   - `prepare_metadata_for_build_wheel`: get the `install_requires`
23   - `build_sdist`: build an sdist in the folder and return the basename
24   - `get_requires_for_build_sdist`: get the `setup_requires` to build
25 
26 Again, this is not a formal definition! Just a "taste" of the module.
27 """
28 
29 import io
30 import os
31 import sys
32 import tokenize
33 import shutil
34 import contextlib
35 
36 import setuptools
37 import distutils
38 from setuptools.py31compat import TemporaryDirectory
39 
40 from pkg_resources import parse_requirements
41 
42 __all__ = ['get_requires_for_build_sdist',
43            'get_requires_for_build_wheel',
44            'prepare_metadata_for_build_wheel',
45            'build_wheel',
46            'build_sdist',
47            '__legacy__',
48            'SetupRequirementsError']
49 
50 
51 class SetupRequirementsError(BaseException):
52     def __init__(self, specifiers):
53         self.specifiers = specifiers
54 
55 
56 class Distribution(setuptools.dist.Distribution):
57     def fetch_build_eggs(self, specifiers):
58         specifier_list = list(map(str, parse_requirements(specifiers)))
59 
60         raise SetupRequirementsError(specifier_list)
61 
62     @classmethod
63     @contextlib.contextmanager
64     def patch(cls):
65         """
66         Replace
67         distutils.dist.Distribution with this class
68         for the duration of this context.
69         """
70         orig = distutils.core.Distribution
71         distutils.core.Distribution = cls
72         try:
73             yield
74         finally:
75             distutils.core.Distribution = orig
76 
77 
78 def _to_str(s):
79     """
80     Convert a filename to a string (on Python 2, explicitly
81     a byte string, not Unicode) as distutils checks for the
82     exact type str.
83     """
84     if sys.version_info[0] == 2 and not isinstance(s, str):
85         # Assume it's Unicode, as that's what the PEP says
86         # should be provided.
87         return s.encode(sys.getfilesystemencoding())
88     return s
89 
90 
91 def _get_immediate_subdirectories(a_dir):
92     return [name for name in os.listdir(a_dir)
93             if os.path.isdir(os.path.join(a_dir, name))]
94 
95 
96 def _file_with_extension(directory, extension):
97     matching = (
98         f for f in os.listdir(directory)
99         if f.endswith(extension)
100     )
101     file, = matching
102     return file
103 
104 
105 def _open_setup_script(setup_script):
106     if not os.path.exists(setup_script):
107         # Supply a default setup.py
108         return io.StringIO(u"from setuptools import setup; setup()")
109 
110     return getattr(tokenize, 'open', open)(setup_script)
111 
112 
113 class _BuildMetaBackend(object):
114 
115     def _fix_config(self, config_settings):
116         config_settings = config_settings or {}
117         config_settings.setdefault('--global-option', [])
118         return config_settings
119 
120     def _get_build_requires(self, config_settings, requirements):
121         config_settings = self._fix_config(config_settings)
122 
123         sys.argv = sys.argv[:1] + ['egg_info'] + \
124             config_settings["--global-option"]
125         try:
126             with Distribution.patch():
127                 self.run_setup()
128         except SetupRequirementsError as e:
129             requirements += e.specifiers
130 
131         return requirements
132 
133     def run_setup(self, setup_script='setup.py'):
134         # Note that we can reuse our build directory between calls
135         # Correctness comes first, then optimization later
136         __file__ = setup_script
137         __name__ = '__main__'
138 
139         with _open_setup_script(__file__) as f:
140             code = f.read().replace(r'\r\n', r'\n')
141 
142         exec(compile(code, __file__, 'exec'), locals())
143 
144     def get_requires_for_build_wheel(self, config_settings=None):
145         config_settings = self._fix_config(config_settings)
146         return self._get_build_requires(
147             config_settings, requirements=['wheel'])
148 
149     def get_requires_for_build_sdist(self, config_settings=None):
150         config_settings = self._fix_config(config_settings)
151         return self._get_build_requires(config_settings, requirements=[])
152 
153     def prepare_metadata_for_build_wheel(self, metadata_directory,
154                                          config_settings=None):
155         sys.argv = sys.argv[:1] + ['dist_info', '--egg-base',
156                                    _to_str(metadata_directory)]
157         self.run_setup()
158 
159         dist_info_directory = metadata_directory
160         while True:
161             dist_infos = [f for f in os.listdir(dist_info_directory)
162                           if f.endswith('.dist-info')]
163 
164             if (
165                 len(dist_infos) == 0 and
166                 len(_get_immediate_subdirectories(dist_info_directory)) == 1
167             ):
168 
169                 dist_info_directory = os.path.join(
170                     dist_info_directory, os.listdir(dist_info_directory)[0])
171                 continue
172 
173             assert len(dist_infos) == 1
174             break
175 
176         # PEP 517 requires that the .dist-info directory be placed in the
177         # metadata_directory. To comply, we MUST copy the directory to the root
178         if dist_info_directory != metadata_directory:
179             shutil.move(
180                 os.path.join(dist_info_directory, dist_infos[0]),
181                 metadata_directory)
182             shutil.rmtree(dist_info_directory, ignore_errors=True)
183 
184         return dist_infos[0]
185 
186     def _build_with_temp_dir(self, setup_command, result_extension,
187                              result_directory, config_settings):
188         config_settings = self._fix_config(config_settings)
189         result_directory = os.path.abspath(result_directory)
190 
191         # Build in a temporary directory, then copy to the target.
192         os.makedirs(result_directory, exist_ok=True)
193         with TemporaryDirectory(dir=result_directory) as tmp_dist_dir:
194             sys.argv = (sys.argv[:1] + setup_command +
195                         ['--dist-dir', tmp_dist_dir] +
196                         config_settings["--global-option"])
197             self.run_setup()
198 
199             result_basename = _file_with_extension(
200                 tmp_dist_dir, result_extension)
201             result_path = os.path.join(result_directory, result_basename)
202             if os.path.exists(result_path):
203                 # os.rename will fail overwriting on non-Unix.
204                 os.remove(result_path)
205             os.rename(os.path.join(tmp_dist_dir, result_basename), result_path)
206 
207         return result_basename
208 
209     def build_wheel(self, wheel_directory, config_settings=None,
210                     metadata_directory=None):
211         return self._build_with_temp_dir(['bdist_wheel'], '.whl',
212                                          wheel_directory, config_settings)
213 
214     def build_sdist(self, sdist_directory, config_settings=None):
215         return self._build_with_temp_dir(['sdist', '--formats', 'gztar'],
216                                          '.tar.gz', sdist_directory,
217                                          config_settings)
218 
219 
220 class _BuildMetaLegacyBackend(_BuildMetaBackend):
221     """Compatibility backend for setuptools
222 
223     This is a version of setuptools.build_meta that endeavors
224     to maintain backwards
225     compatibility with pre-PEP 517 modes of invocation. It
226     exists as a temporary
227     bridge between the old packaging mechanism and the new
228     packaging mechanism,
229     and will eventually be removed.
230     """
231     def run_setup(self, setup_script='setup.py'):
232         # In order to maintain compatibility with scripts assuming that
233         # the setup.py script is in a directory on the PYTHONPATH, inject
234         # '' into sys.path. (pypa/setuptools#1642)
235         sys_path = list(sys.path)           # Save the original path
236 
237         script_dir = os.path.dirname(os.path.abspath(setup_script))
238         if script_dir not in sys.path:
239             sys.path.insert(0, script_dir)
240 
241         # Some setup.py scripts (e.g. in pygame and numpy) use sys.argv[0] to
242         # get the directory of the source code. They expect it to refer to the
243         # setup.py script.
244         sys_argv_0 = sys.argv[0]
245         sys.argv[0] = setup_script
246 
247         try:
248             super(_BuildMetaLegacyBackend,
249                   self).run_setup(setup_script=setup_script)
250         finally:
251             # While PEP 517 frontends should be calling each hook in a fresh
252             # subprocess according to the standard (and thus it should not be
253             # strictly necessary to restore the old sys.path), we'll restore
254             # the original path so that the path manipulation does not persist
255             # within the hook after run_setup is called.
256             sys.path[:] = sys_path
257             sys.argv[0] = sys_argv_0
258 
259 
260 # The primary backend
261 _BACKEND = _BuildMetaBackend()
262 
263 get_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel
264 get_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist
265 prepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel
266 build_wheel = _BACKEND.build_wheel
267 build_sdist = _BACKEND.build_sdist
268 
269 
270 # The legacy backend
271 __legacy__ = _BuildMetaLegacyBackend()
272
```
--- 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/setuptools/build_meta.py b/setuptools/build_meta.py
--- a/setuptools/build_meta.py
+++ b/setuptools/build_meta.py
@@ -75,6 +75,22 @@
             distutils.core.Distribution = orig
 
 
+@contextlib.contextmanager
+def no_install_setup_requires():
+    """Temporarily disable installing setup_requires
+
+    Under PEP 517, the backend reports build dependencies to the frontend,
+    and the frontend is responsible for ensuring they're installed.
+    So setuptools (acting as a backend) should not try to install them.
+    """
+    orig = setuptools._install_setup_requires
+    setuptools._install_setup_requires = lambda attrs: None
+    try:
+        yield
+    finally:
+        setuptools._install_setup_requires = orig
+
+
 def _to_str(s):
     """
     Convert a filename to a string (on Python 2, explicitly
@@ -154,7 +170,8 @@
                                          config_settings=None):
         sys.argv = sys.argv[:1] + ['dist_info', '--egg-base',
                                    _to_str(metadata_directory)]
-        self.run_setup()
+        with no_install_setup_requires():
+            self.run_setup()
 
         dist_info_directory = metadata_directory
         while True:
@@ -194,7 +211,8 @@
             sys.argv = (sys.argv[:1] + setup_command +
                         ['--dist-dir', tmp_dist_dir] +
                         config_settings["--global-option"])
-            self.run_setup()
+            with no_install_setup_requires():
+                self.run_setup()
 
             result_basename = _file_with_extension(
                 tmp_dist_dir, result_extension)

{"golden_diff": "diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py\n--- a/setuptools/build_meta.py\n+++ b/setuptools/build_meta.py\n@@ -75,6 +75,22 @@\n             distutils.core.Distribution = orig\n \n \n+@contextlib.contextmanager\n+def no_install_setup_requires():\n+    \"\"\"Temporarily disable installing setup_requires\n+\n+    Under PEP 517, the backend reports build dependencies to the frontend,\n+    and the frontend is responsible for ensuring they're installed.\n+    So setuptools (acting as a backend) should not try to install them.\n+    \"\"\"\n+    orig = setuptools._install_setup_requires\n+    setuptools._install_setup_requires = lambda attrs: None\n+    try:\n+        yield\n+    finally:\n+        setuptools._install_setup_requires = orig\n+\n+\n def _to_str(s):\n     \"\"\"\n     Convert a filename to a string (on Python 2, explicitly\n@@ -154,7 +170,8 @@\n                                          config_settings=None):\n         sys.argv = sys.argv[:1] + ['dist_info', '--egg-base',\n                                    _to_str(metadata_directory)]\n-        self.run_setup()\n+        with no_install_setup_requires():\n+            self.run_setup()\n \n         dist_info_directory = metadata_directory\n         while True:\n@@ -194,7 +211,8 @@\n             sys.argv = (sys.argv[:1] + setup_command +\n                         ['--dist-dir', tmp_dist_dir] +\n                         config_settings[\"--global-option\"])\n-            self.run_setup()\n+            with no_install_setup_requires():\n+                self.run_setup()\n \n             result_basename = _file_with_extension(\n                 tmp_dist_dir, result_extension)\n", "issue": "Don't install setup_requires when run as a PEP 517 backend\nPEP 517 separates the responsibilities around build requirements: the backend is responsible for saying what is required, and the frontend is responsible for ensuring they're available to the build.\r\n\r\nIn setuptools, build requirements are defined by `setup_requires`, and these get passed through to PEP 517's `get_requires_for_build_*` hooks. There is a monkeypatch to return them from these hooks and prevent setuptools trying to install them itself:\r\n\r\nhttps://github.com/pypa/setuptools/blob/5e60dc50e540a942aeb558aabe7d92ab7eb13d4b/setuptools/build_meta.py#L56-L75\r\n\r\nBut something similar to that - preventing installation - should really be in place for all the PEP 517 hooks, because a PEP 517 backend isn't responsible for installing dependencies.\r\n\r\nWhy does this matter? Pip has the `--no-build-isolation` option, with which the caller can declare that they have taken care of build dependencies and pip should try to build the package in the current environment. This is useful for downstream packagers, and for experimenting with different versions of your build dependencies. But setuptools doesn't know about this, so it charges ahead and attempts to install things when that's not what you want.\r\n\r\nThe workaround I'm looking at is to only specify `setup_requires` if `'egg_info' in sys.argv`, as is the case when the `get_requires_for_build_*` hooks are called. But this is clearly not ideal.\n", "before_files": [{"content": "\"\"\"A PEP 517 interface to setuptools\n\nPreviously, when a user or a command line tool (let's call it a \"frontend\")\nneeded to make a request of setuptools to take a certain action, for\nexample, generating a list of installation requirements, the frontend would\nwould call \"setup.py egg_info\" or \"setup.py bdist_wheel\" on the command line.\n\nPEP 517 defines a different method of interfacing with setuptools. Rather\nthan calling \"setup.py\" directly, the frontend should:\n\n  1. Set the current directory to the directory with a setup.py file\n  2. Import this module into a safe python interpreter (one in which\n     setuptools can potentially set global variables or crash hard).\n  3. Call one of the functions defined in PEP 517.\n\nWhat each function does is defined in PEP 517. However, here is a \"casual\"\ndefinition of the functions (this definition should not be relied on for\nbug reports or API stability):\n\n  - `build_wheel`: build a wheel in the folder and return the basename\n  - `get_requires_for_build_wheel`: get the `setup_requires` to build\n  - `prepare_metadata_for_build_wheel`: get the `install_requires`\n  - `build_sdist`: build an sdist in the folder and return the basename\n  - `get_requires_for_build_sdist`: get the `setup_requires` to build\n\nAgain, this is not a formal definition! Just a \"taste\" of the module.\n\"\"\"\n\nimport io\nimport os\nimport sys\nimport tokenize\nimport shutil\nimport contextlib\n\nimport setuptools\nimport distutils\nfrom setuptools.py31compat import TemporaryDirectory\n\nfrom pkg_resources import parse_requirements\n\n__all__ = ['get_requires_for_build_sdist',\n           'get_requires_for_build_wheel',\n           'prepare_metadata_for_build_wheel',\n           'build_wheel',\n           'build_sdist',\n           '__legacy__',\n           'SetupRequirementsError']\n\n\nclass SetupRequirementsError(BaseException):\n    def __init__(self, specifiers):\n        self.specifiers = specifiers\n\n\nclass Distribution(setuptools.dist.Distribution):\n    def fetch_build_eggs(self, specifiers):\n        specifier_list = list(map(str, parse_requirements(specifiers)))\n\n        raise SetupRequirementsError(specifier_list)\n\n    @classmethod\n    @contextlib.contextmanager\n    def patch(cls):\n        \"\"\"\n        Replace\n        distutils.dist.Distribution with this class\n        for the duration of this context.\n        \"\"\"\n        orig = distutils.core.Distribution\n        distutils.core.Distribution = cls\n        try:\n            yield\n        finally:\n            distutils.core.Distribution = orig\n\n\ndef _to_str(s):\n    \"\"\"\n    Convert a filename to a string (on Python 2, explicitly\n    a byte string, not Unicode) as distutils checks for the\n    exact type str.\n    \"\"\"\n    if sys.version_info[0] == 2 and not isinstance(s, str):\n        # Assume it's Unicode, as that's what the PEP says\n        # should be provided.\n        return s.encode(sys.getfilesystemencoding())\n    return s\n\n\ndef _get_immediate_subdirectories(a_dir):\n    return [name for name in os.listdir(a_dir)\n            if os.path.isdir(os.path.join(a_dir, name))]\n\n\ndef _file_with_extension(directory, extension):\n    matching = (\n        f for f in os.listdir(directory)\n        if f.endswith(extension)\n    )\n    file, = matching\n    return file\n\n\ndef _open_setup_script(setup_script):\n    if not os.path.exists(setup_script):\n        # Supply a default setup.py\n        return io.StringIO(u\"from setuptools import setup; setup()\")\n\n    return getattr(tokenize, 'open', open)(setup_script)\n\n\nclass _BuildMetaBackend(object):\n\n    def _fix_config(self, config_settings):\n        config_settings = config_settings or {}\n        config_settings.setdefault('--global-option', [])\n        return config_settings\n\n    def _get_build_requires(self, config_settings, requirements):\n        config_settings = self._fix_config(config_settings)\n\n        sys.argv = sys.argv[:1] + ['egg_info'] + \\\n            config_settings[\"--global-option\"]\n        try:\n            with Distribution.patch():\n                self.run_setup()\n        except SetupRequirementsError as e:\n            requirements += e.specifiers\n\n        return requirements\n\n    def run_setup(self, setup_script='setup.py'):\n        # Note that we can reuse our build directory between calls\n        # Correctness comes first, then optimization later\n        __file__ = setup_script\n        __name__ = '__main__'\n\n        with _open_setup_script(__file__) as f:\n            code = f.read().replace(r'\\r\\n', r'\\n')\n\n        exec(compile(code, __file__, 'exec'), locals())\n\n    def get_requires_for_build_wheel(self, config_settings=None):\n        config_settings = self._fix_config(config_settings)\n        return self._get_build_requires(\n            config_settings, requirements=['wheel'])\n\n    def get_requires_for_build_sdist(self, config_settings=None):\n        config_settings = self._fix_config(config_settings)\n        return self._get_build_requires(config_settings, requirements=[])\n\n    def prepare_metadata_for_build_wheel(self, metadata_directory,\n                                         config_settings=None):\n        sys.argv = sys.argv[:1] + ['dist_info', '--egg-base',\n                                   _to_str(metadata_directory)]\n        self.run_setup()\n\n        dist_info_directory = metadata_directory\n        while True:\n            dist_infos = [f for f in os.listdir(dist_info_directory)\n                          if f.endswith('.dist-info')]\n\n            if (\n                len(dist_infos) == 0 and\n                len(_get_immediate_subdirectories(dist_info_directory)) == 1\n            ):\n\n                dist_info_directory = os.path.join(\n                    dist_info_directory, os.listdir(dist_info_directory)[0])\n                continue\n\n            assert len(dist_infos) == 1\n            break\n\n        # PEP 517 requires that the .dist-info directory be placed in the\n        # metadata_directory. To comply, we MUST copy the directory to the root\n        if dist_info_directory != metadata_directory:\n            shutil.move(\n                os.path.join(dist_info_directory, dist_infos[0]),\n                metadata_directory)\n            shutil.rmtree(dist_info_directory, ignore_errors=True)\n\n        return dist_infos[0]\n\n    def _build_with_temp_dir(self, setup_command, result_extension,\n                             result_directory, config_settings):\n        config_settings = self._fix_config(config_settings)\n        result_directory = os.path.abspath(result_directory)\n\n        # Build in a temporary directory, then copy to the target.\n        os.makedirs(result_directory, exist_ok=True)\n        with TemporaryDirectory(dir=result_directory) as tmp_dist_dir:\n            sys.argv = (sys.argv[:1] + setup_command +\n                        ['--dist-dir', tmp_dist_dir] +\n                        config_settings[\"--global-option\"])\n            self.run_setup()\n\n            result_basename = _file_with_extension(\n                tmp_dist_dir, result_extension)\n            result_path = os.path.join(result_directory, result_basename)\n            if os.path.exists(result_path):\n                # os.rename will fail overwriting on non-Unix.\n                os.remove(result_path)\n            os.rename(os.path.join(tmp_dist_dir, result_basename), result_path)\n\n        return result_basename\n\n    def build_wheel(self, wheel_directory, config_settings=None,\n                    metadata_directory=None):\n        return self._build_with_temp_dir(['bdist_wheel'], '.whl',\n                                         wheel_directory, config_settings)\n\n    def build_sdist(self, sdist_directory, config_settings=None):\n        return self._build_with_temp_dir(['sdist', '--formats', 'gztar'],\n                                         '.tar.gz', sdist_directory,\n                                         config_settings)\n\n\nclass _BuildMetaLegacyBackend(_BuildMetaBackend):\n    \"\"\"Compatibility backend for setuptools\n\n    This is a version of setuptools.build_meta that endeavors\n    to maintain backwards\n    compatibility with pre-PEP 517 modes of invocation. It\n    exists as a temporary\n    bridge between the old packaging mechanism and the new\n    packaging mechanism,\n    and will eventually be removed.\n    \"\"\"\n    def run_setup(self, setup_script='setup.py'):\n        # In order to maintain compatibility with scripts assuming that\n        # the setup.py script is in a directory on the PYTHONPATH, inject\n        # '' into sys.path. (pypa/setuptools#1642)\n        sys_path = list(sys.path)           # Save the original path\n\n        script_dir = os.path.dirname(os.path.abspath(setup_script))\n        if script_dir not in sys.path:\n            sys.path.insert(0, script_dir)\n\n        # Some setup.py scripts (e.g. in pygame and numpy) use sys.argv[0] to\n        # get the directory of the source code. They expect it to refer to the\n        # setup.py script.\n        sys_argv_0 = sys.argv[0]\n        sys.argv[0] = setup_script\n\n        try:\n            super(_BuildMetaLegacyBackend,\n                  self).run_setup(setup_script=setup_script)\n        finally:\n            # While PEP 517 frontends should be calling each hook in a fresh\n            # subprocess according to the standard (and thus it should not be\n            # strictly necessary to restore the old sys.path), we'll restore\n            # the original path so that the path manipulation does not persist\n            # within the hook after run_setup is called.\n            sys.path[:] = sys_path\n            sys.argv[0] = sys_argv_0\n\n\n# The primary backend\n_BACKEND = _BuildMetaBackend()\n\nget_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel\nget_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist\nprepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel\nbuild_wheel = _BACKEND.build_wheel\nbuild_sdist = _BACKEND.build_sdist\n\n\n# The legacy backend\n__legacy__ = _BuildMetaLegacyBackend()\n", "path": "setuptools/build_meta.py"}], "after_files": [{"content": "\"\"\"A PEP 517 interface to setuptools\n\nPreviously, when a user or a command line tool (let's call it a \"frontend\")\nneeded to make a request of setuptools to take a certain action, for\nexample, generating a list of installation requirements, the frontend would\nwould call \"setup.py egg_info\" or \"setup.py bdist_wheel\" on the command line.\n\nPEP 517 defines a different method of interfacing with setuptools. Rather\nthan calling \"setup.py\" directly, the frontend should:\n\n  1. Set the current directory to the directory with a setup.py file\n  2. Import this module into a safe python interpreter (one in which\n     setuptools can potentially set global variables or crash hard).\n  3. Call one of the functions defined in PEP 517.\n\nWhat each function does is defined in PEP 517. However, here is a \"casual\"\ndefinition of the functions (this definition should not be relied on for\nbug reports or API stability):\n\n  - `build_wheel`: build a wheel in the folder and return the basename\n  - `get_requires_for_build_wheel`: get the `setup_requires` to build\n  - `prepare_metadata_for_build_wheel`: get the `install_requires`\n  - `build_sdist`: build an sdist in the folder and return the basename\n  - `get_requires_for_build_sdist`: get the `setup_requires` to build\n\nAgain, this is not a formal definition! Just a \"taste\" of the module.\n\"\"\"\n\nimport io\nimport os\nimport sys\nimport tokenize\nimport shutil\nimport contextlib\n\nimport setuptools\nimport distutils\nfrom setuptools.py31compat import TemporaryDirectory\n\nfrom pkg_resources import parse_requirements\n\n__all__ = ['get_requires_for_build_sdist',\n           'get_requires_for_build_wheel',\n           'prepare_metadata_for_build_wheel',\n           'build_wheel',\n           'build_sdist',\n           '__legacy__',\n           'SetupRequirementsError']\n\n\nclass SetupRequirementsError(BaseException):\n    def __init__(self, specifiers):\n        self.specifiers = specifiers\n\n\nclass Distribution(setuptools.dist.Distribution):\n    def fetch_build_eggs(self, specifiers):\n        specifier_list = list(map(str, parse_requirements(specifiers)))\n\n        raise SetupRequirementsError(specifier_list)\n\n    @classmethod\n    @contextlib.contextmanager\n    def patch(cls):\n        \"\"\"\n        Replace\n        distutils.dist.Distribution with this class\n        for the duration of this context.\n        \"\"\"\n        orig = distutils.core.Distribution\n        distutils.core.Distribution = cls\n        try:\n            yield\n        finally:\n            distutils.core.Distribution = orig\n\n\n@contextlib.contextmanager\ndef no_install_setup_requires():\n    \"\"\"Temporarily disable installing setup_requires\n\n    Under PEP 517, the backend reports build dependencies to the frontend,\n    and the frontend is responsible for ensuring they're installed.\n    So setuptools (acting as a backend) should not try to install them.\n    \"\"\"\n    orig = setuptools._install_setup_requires\n    setuptools._install_setup_requires = lambda attrs: None\n    try:\n        yield\n    finally:\n        setuptools._install_setup_requires = orig\n\n\ndef _to_str(s):\n    \"\"\"\n    Convert a filename to a string (on Python 2, explicitly\n    a byte string, not Unicode) as distutils checks for the\n    exact type str.\n    \"\"\"\n    if sys.version_info[0] == 2 and not isinstance(s, str):\n        # Assume it's Unicode, as that's what the PEP says\n        # should be provided.\n        return s.encode(sys.getfilesystemencoding())\n    return s\n\n\ndef _get_immediate_subdirectories(a_dir):\n    return [name for name in os.listdir(a_dir)\n            if os.path.isdir(os.path.join(a_dir, name))]\n\n\ndef _file_with_extension(directory, extension):\n    matching = (\n        f for f in os.listdir(directory)\n        if f.endswith(extension)\n    )\n    file, = matching\n    return file\n\n\ndef _open_setup_script(setup_script):\n    if not os.path.exists(setup_script):\n        # Supply a default setup.py\n        return io.StringIO(u\"from setuptools import setup; setup()\")\n\n    return getattr(tokenize, 'open', open)(setup_script)\n\n\nclass _BuildMetaBackend(object):\n\n    def _fix_config(self, config_settings):\n        config_settings = config_settings or {}\n        config_settings.setdefault('--global-option', [])\n        return config_settings\n\n    def _get_build_requires(self, config_settings, requirements):\n        config_settings = self._fix_config(config_settings)\n\n        sys.argv = sys.argv[:1] + ['egg_info'] + \\\n            config_settings[\"--global-option\"]\n        try:\n            with Distribution.patch():\n                self.run_setup()\n        except SetupRequirementsError as e:\n            requirements += e.specifiers\n\n        return requirements\n\n    def run_setup(self, setup_script='setup.py'):\n        # Note that we can reuse our build directory between calls\n        # Correctness comes first, then optimization later\n        __file__ = setup_script\n        __name__ = '__main__'\n\n        with _open_setup_script(__file__) as f:\n            code = f.read().replace(r'\\r\\n', r'\\n')\n\n        exec(compile(code, __file__, 'exec'), locals())\n\n    def get_requires_for_build_wheel(self, config_settings=None):\n        config_settings = self._fix_config(config_settings)\n        return self._get_build_requires(\n            config_settings, requirements=['wheel'])\n\n    def get_requires_for_build_sdist(self, config_settings=None):\n        config_settings = self._fix_config(config_settings)\n        return self._get_build_requires(config_settings, requirements=[])\n\n    def prepare_metadata_for_build_wheel(self, metadata_directory,\n                                         config_settings=None):\n        sys.argv = sys.argv[:1] + ['dist_info', '--egg-base',\n                                   _to_str(metadata_directory)]\n        with no_install_setup_requires():\n            self.run_setup()\n\n        dist_info_directory = metadata_directory\n        while True:\n            dist_infos = [f for f in os.listdir(dist_info_directory)\n                          if f.endswith('.dist-info')]\n\n            if (\n                len(dist_infos) == 0 and\n                len(_get_immediate_subdirectories(dist_info_directory)) == 1\n            ):\n\n                dist_info_directory = os.path.join(\n                    dist_info_directory, os.listdir(dist_info_directory)[0])\n                continue\n\n            assert len(dist_infos) == 1\n            break\n\n        # PEP 517 requires that the .dist-info directory be placed in the\n        # metadata_directory. To comply, we MUST copy the directory to the root\n        if dist_info_directory != metadata_directory:\n            shutil.move(\n                os.path.join(dist_info_directory, dist_infos[0]),\n                metadata_directory)\n            shutil.rmtree(dist_info_directory, ignore_errors=True)\n\n        return dist_infos[0]\n\n    def _build_with_temp_dir(self, setup_command, result_extension,\n                             result_directory, config_settings):\n        config_settings = self._fix_config(config_settings)\n        result_directory = os.path.abspath(result_directory)\n\n        # Build in a temporary directory, then copy to the target.\n        os.makedirs(result_directory, exist_ok=True)\n        with TemporaryDirectory(dir=result_directory) as tmp_dist_dir:\n            sys.argv = (sys.argv[:1] + setup_command +\n                        ['--dist-dir', tmp_dist_dir] +\n                        config_settings[\"--global-option\"])\n            with no_install_setup_requires():\n                self.run_setup()\n\n            result_basename = _file_with_extension(\n                tmp_dist_dir, result_extension)\n            result_path = os.path.join(result_directory, result_basename)\n            if os.path.exists(result_path):\n                # os.rename will fail overwriting on non-Unix.\n                os.remove(result_path)\n            os.rename(os.path.join(tmp_dist_dir, result_basename), result_path)\n\n        return result_basename\n\n    def build_wheel(self, wheel_directory, config_settings=None,\n                    metadata_directory=None):\n        return self._build_with_temp_dir(['bdist_wheel'], '.whl',\n                                         wheel_directory, config_settings)\n\n    def build_sdist(self, sdist_directory, config_settings=None):\n        return self._build_with_temp_dir(['sdist', '--formats', 'gztar'],\n                                         '.tar.gz', sdist_directory,\n                                         config_settings)\n\n\nclass _BuildMetaLegacyBackend(_BuildMetaBackend):\n    \"\"\"Compatibility backend for setuptools\n\n    This is a version of setuptools.build_meta that endeavors\n    to maintain backwards\n    compatibility with pre-PEP 517 modes of invocation. It\n    exists as a temporary\n    bridge between the old packaging mechanism and the new\n    packaging mechanism,\n    and will eventually be removed.\n    \"\"\"\n    def run_setup(self, setup_script='setup.py'):\n        # In order to maintain compatibility with scripts assuming that\n        # the setup.py script is in a directory on the PYTHONPATH, inject\n        # '' into sys.path. (pypa/setuptools#1642)\n        sys_path = list(sys.path)           # Save the original path\n\n        script_dir = os.path.dirname(os.path.abspath(setup_script))\n        if script_dir not in sys.path:\n            sys.path.insert(0, script_dir)\n\n        # Some setup.py scripts (e.g. in pygame and numpy) use sys.argv[0] to\n        # get the directory of the source code. They expect it to refer to the\n        # setup.py script.\n        sys_argv_0 = sys.argv[0]\n        sys.argv[0] = setup_script\n\n        try:\n            super(_BuildMetaLegacyBackend,\n                  self).run_setup(setup_script=setup_script)\n        finally:\n            # While PEP 517 frontends should be calling each hook in a fresh\n            # subprocess according to the standard (and thus it should not be\n            # strictly necessary to restore the old sys.path), we'll restore\n            # the original path so that the path manipulation does not persist\n            # within the hook after run_setup is called.\n            sys.path[:] = sys_path\n            sys.argv[0] = sys_argv_0\n\n\n# The primary backend\n_BACKEND = _BuildMetaBackend()\n\nget_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel\nget_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist\nprepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel\nbuild_wheel = _BACKEND.build_wheel\nbuild_sdist = _BACKEND.build_sdist\n\n\n# The legacy backend\n__legacy__ = _BuildMetaLegacyBackend()\n", "path": "setuptools/build_meta.py"}]}