We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`build_meta.build_sdist` should work if the destination directory already contains a tar.gz
The issue is similar to #1671, see #1745 for how the issue can be resolved.

--- 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 class SetupRequirementsError(BaseException):
51     def __init__(self, specifiers):
52         self.specifiers = specifiers
53 
54 
55 class Distribution(setuptools.dist.Distribution):
56     def fetch_build_eggs(self, specifiers):
57         specifier_list = list(map(str, parse_requirements(specifiers)))
58 
59         raise SetupRequirementsError(specifier_list)
60 
61     @classmethod
62     @contextlib.contextmanager
63     def patch(cls):
64         """
65         Replace
66         distutils.dist.Distribution with this class
67         for the duration of this context.
68         """
69         orig = distutils.core.Distribution
70         distutils.core.Distribution = cls
71         try:
72             yield
73         finally:
74             distutils.core.Distribution = orig
75 
76 
77 def _to_str(s):
78     """
79     Convert a filename to a string (on Python 2, explicitly
80     a byte string, not Unicode) as distutils checks for the
81     exact type str.
82     """
83     if sys.version_info[0] == 2 and not isinstance(s, str):
84         # Assume it's Unicode, as that's what the PEP says
85         # should be provided.
86         return s.encode(sys.getfilesystemencoding())
87     return s
88 
89 
90 def _get_immediate_subdirectories(a_dir):
91     return [name for name in os.listdir(a_dir)
92             if os.path.isdir(os.path.join(a_dir, name))]
93 
94 
95 def _file_with_extension(directory, extension):
96     matching = (
97         f for f in os.listdir(directory)
98         if f.endswith(extension)
99     )
100     file, = matching
101     return file
102 
103 
104 def _open_setup_script(setup_script):
105     if not os.path.exists(setup_script):
106         # Supply a default setup.py
107         return io.StringIO(u"from setuptools import setup; setup()")
108 
109     return getattr(tokenize, 'open', open)(setup_script)
110 
111 
112 class _BuildMetaBackend(object):
113 
114     def _fix_config(self, config_settings):
115         config_settings = config_settings or {}
116         config_settings.setdefault('--global-option', [])
117         return config_settings
118 
119     def _get_build_requires(self, config_settings, requirements):
120         config_settings = self._fix_config(config_settings)
121 
122         sys.argv = sys.argv[:1] + ['egg_info'] + \
123             config_settings["--global-option"]
124         try:
125             with Distribution.patch():
126                 self.run_setup()
127         except SetupRequirementsError as e:
128             requirements += e.specifiers
129 
130         return requirements
131 
132     def run_setup(self, setup_script='setup.py'):
133         # Note that we can reuse our build directory between calls
134         # Correctness comes first, then optimization later
135         __file__ = setup_script
136         __name__ = '__main__'
137 
138         with _open_setup_script(__file__) as f:
139             code = f.read().replace(r'\r\n', r'\n')
140 
141         exec(compile(code, __file__, 'exec'), locals())
142 
143     def get_requires_for_build_wheel(self, config_settings=None):
144         config_settings = self._fix_config(config_settings)
145         return self._get_build_requires(config_settings, requirements=['wheel'])
146 
147     def get_requires_for_build_sdist(self, config_settings=None):
148         config_settings = self._fix_config(config_settings)
149         return self._get_build_requires(config_settings, requirements=[])
150 
151     def prepare_metadata_for_build_wheel(self, metadata_directory,
152                                          config_settings=None):
153         sys.argv = sys.argv[:1] + ['dist_info', '--egg-base',
154                                    _to_str(metadata_directory)]
155         self.run_setup()
156 
157         dist_info_directory = metadata_directory
158         while True:
159             dist_infos = [f for f in os.listdir(dist_info_directory)
160                           if f.endswith('.dist-info')]
161 
162             if (len(dist_infos) == 0 and
163                 len(_get_immediate_subdirectories(dist_info_directory)) == 1):
164 
165                 dist_info_directory = os.path.join(
166                     dist_info_directory, os.listdir(dist_info_directory)[0])
167                 continue
168 
169             assert len(dist_infos) == 1
170             break
171 
172         # PEP 517 requires that the .dist-info directory be placed in the
173         # metadata_directory. To comply, we MUST copy the directory to the root
174         if dist_info_directory != metadata_directory:
175             shutil.move(
176                 os.path.join(dist_info_directory, dist_infos[0]),
177                 metadata_directory)
178             shutil.rmtree(dist_info_directory, ignore_errors=True)
179 
180         return dist_infos[0]
181 
182     def build_wheel(self, wheel_directory, config_settings=None,
183                     metadata_directory=None):
184         config_settings = self._fix_config(config_settings)
185         wheel_directory = os.path.abspath(wheel_directory)
186 
187         # Build the wheel in a temporary directory, then copy to the target
188         with TemporaryDirectory(dir=wheel_directory) as tmp_dist_dir:
189             sys.argv = (sys.argv[:1] +
190                         ['bdist_wheel', '--dist-dir', tmp_dist_dir] +
191                         config_settings["--global-option"])
192             self.run_setup()
193 
194             wheel_basename = _file_with_extension(tmp_dist_dir, '.whl')
195             wheel_path = os.path.join(wheel_directory, wheel_basename)
196             if os.path.exists(wheel_path):
197                 # os.rename will fail overwriting on non-unix env
198                 os.remove(wheel_path)
199             os.rename(os.path.join(tmp_dist_dir, wheel_basename), wheel_path)
200 
201         return wheel_basename
202 
203     def build_sdist(self, sdist_directory, config_settings=None):
204         config_settings = self._fix_config(config_settings)
205         sdist_directory = os.path.abspath(sdist_directory)
206         sys.argv = sys.argv[:1] + ['sdist', '--formats', 'gztar'] + \
207             config_settings["--global-option"] + \
208             ["--dist-dir", sdist_directory]
209         self.run_setup()
210 
211         return _file_with_extension(sdist_directory, '.tar.gz')
212 
213 
214 class _BuildMetaLegacyBackend(_BuildMetaBackend):
215     """Compatibility backend for setuptools
216 
217     This is a version of setuptools.build_meta that endeavors to maintain backwards
218     compatibility with pre-PEP 517 modes of invocation. It exists as a temporary
219     bridge between the old packaging mechanism and the new packaging mechanism,
220     and will eventually be removed.
221     """
222     def run_setup(self, setup_script='setup.py'):
223         # In order to maintain compatibility with scripts assuming that
224         # the setup.py script is in a directory on the PYTHONPATH, inject
225         # '' into sys.path. (pypa/setuptools#1642)
226         sys_path = list(sys.path)           # Save the original path
227 
228         script_dir = os.path.dirname(os.path.abspath(setup_script))
229         if script_dir not in sys.path:
230             sys.path.insert(0, script_dir)
231 
232         try:
233             super(_BuildMetaLegacyBackend,
234                   self).run_setup(setup_script=setup_script)
235         finally:
236             # While PEP 517 frontends should be calling each hook in a fresh
237             # subprocess according to the standard (and thus it should not be
238             # strictly necessary to restore the old sys.path), we'll restore
239             # the original path so that the path manipulation does not persist
240             # within the hook after run_setup is called.
241             sys.path[:] = sys_path
242 
243 # The primary backend
244 _BACKEND = _BuildMetaBackend()
245 
246 get_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel
247 get_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist
248 prepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel
249 build_wheel = _BACKEND.build_wheel
250 build_sdist = _BACKEND.build_sdist
251 
252 
253 # The legacy backend
254 __legacy__ = _BuildMetaLegacyBackend()
255
```
--- 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
@@ -38,6 +38,7 @@
 from setuptools.py31compat import TemporaryDirectory
 
 from pkg_resources import parse_requirements
+from pkg_resources.py31compat import makedirs
 
 __all__ = ['get_requires_for_build_sdist',
            'get_requires_for_build_wheel',
@@ -179,36 +180,38 @@
 
         return dist_infos[0]
 
-    def build_wheel(self, wheel_directory, config_settings=None,
-                    metadata_directory=None):
+    def _build_with_temp_dir(self, setup_command, result_extension,
+                             result_directory, config_settings):
         config_settings = self._fix_config(config_settings)
-        wheel_directory = os.path.abspath(wheel_directory)
+        result_directory = os.path.abspath(result_directory)
 
-        # Build the wheel in a temporary directory, then copy to the target
-        with TemporaryDirectory(dir=wheel_directory) as tmp_dist_dir:
-            sys.argv = (sys.argv[:1] +
-                        ['bdist_wheel', '--dist-dir', tmp_dist_dir] +
+        # Build in a temporary directory, then copy to the target.
+        makedirs(result_directory, exist_ok=True)
+        with TemporaryDirectory(dir=result_directory) as tmp_dist_dir:
+            sys.argv = (sys.argv[:1] + setup_command +
+                        ['--dist-dir', tmp_dist_dir] +
                         config_settings["--global-option"])
             self.run_setup()
 
-            wheel_basename = _file_with_extension(tmp_dist_dir, '.whl')
-            wheel_path = os.path.join(wheel_directory, wheel_basename)
-            if os.path.exists(wheel_path):
-                # os.rename will fail overwriting on non-unix env
-                os.remove(wheel_path)
-            os.rename(os.path.join(tmp_dist_dir, wheel_basename), wheel_path)
+            result_basename = _file_with_extension(tmp_dist_dir, result_extension)
+            result_path = os.path.join(result_directory, result_basename)
+            if os.path.exists(result_path):
+                # os.rename will fail overwriting on non-Unix.
+                os.remove(result_path)
+            os.rename(os.path.join(tmp_dist_dir, result_basename), result_path)
 
-        return wheel_basename
+        return result_basename
 
-    def build_sdist(self, sdist_directory, config_settings=None):
-        config_settings = self._fix_config(config_settings)
-        sdist_directory = os.path.abspath(sdist_directory)
-        sys.argv = sys.argv[:1] + ['sdist', '--formats', 'gztar'] + \
-            config_settings["--global-option"] + \
-            ["--dist-dir", sdist_directory]
-        self.run_setup()
 
-        return _file_with_extension(sdist_directory, '.tar.gz')
+    def build_wheel(self, wheel_directory, config_settings=None,
+                    metadata_directory=None):
+        return self._build_with_temp_dir(['bdist_wheel'], '.whl',
+                                         wheel_directory, config_settings)
+
+    def build_sdist(self, sdist_directory, config_settings=None):
+        return self._build_with_temp_dir(['sdist', '--formats', 'gztar'],
+                                         '.tar.gz', sdist_directory,
+                                         config_settings)
 
 
 class _BuildMetaLegacyBackend(_BuildMetaBackend):

{"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@@ -38,6 +38,7 @@\n from setuptools.py31compat import TemporaryDirectory\n \n from pkg_resources import parse_requirements\n+from pkg_resources.py31compat import makedirs\n \n __all__ = ['get_requires_for_build_sdist',\n            'get_requires_for_build_wheel',\n@@ -179,36 +180,38 @@\n \n         return dist_infos[0]\n \n-    def build_wheel(self, wheel_directory, config_settings=None,\n-                    metadata_directory=None):\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-        wheel_directory = os.path.abspath(wheel_directory)\n+        result_directory = os.path.abspath(result_directory)\n \n-        # Build the wheel in a temporary directory, then copy to the target\n-        with TemporaryDirectory(dir=wheel_directory) as tmp_dist_dir:\n-            sys.argv = (sys.argv[:1] +\n-                        ['bdist_wheel', '--dist-dir', tmp_dist_dir] +\n+        # Build in a temporary directory, then copy to the target.\n+        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-            wheel_basename = _file_with_extension(tmp_dist_dir, '.whl')\n-            wheel_path = os.path.join(wheel_directory, wheel_basename)\n-            if os.path.exists(wheel_path):\n-                # os.rename will fail overwriting on non-unix env\n-                os.remove(wheel_path)\n-            os.rename(os.path.join(tmp_dist_dir, wheel_basename), wheel_path)\n+            result_basename = _file_with_extension(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 wheel_basename\n+        return result_basename\n \n-    def build_sdist(self, sdist_directory, config_settings=None):\n-        config_settings = self._fix_config(config_settings)\n-        sdist_directory = os.path.abspath(sdist_directory)\n-        sys.argv = sys.argv[:1] + ['sdist', '--formats', 'gztar'] + \\\n-            config_settings[\"--global-option\"] + \\\n-            [\"--dist-dir\", sdist_directory]\n-        self.run_setup()\n \n-        return _file_with_extension(sdist_directory, '.tar.gz')\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 \n class _BuildMetaLegacyBackend(_BuildMetaBackend):\n", "issue": "`build_meta.build_sdist` should work if the destination directory already contains a tar.gz\nThe issue is similar to #1671, see #1745 for how the issue can be resolved.\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\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(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 (len(dist_infos) == 0 and\n                len(_get_immediate_subdirectories(dist_info_directory)) == 1):\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_wheel(self, wheel_directory, config_settings=None,\n                    metadata_directory=None):\n        config_settings = self._fix_config(config_settings)\n        wheel_directory = os.path.abspath(wheel_directory)\n\n        # Build the wheel in a temporary directory, then copy to the target\n        with TemporaryDirectory(dir=wheel_directory) as tmp_dist_dir:\n            sys.argv = (sys.argv[:1] +\n                        ['bdist_wheel', '--dist-dir', tmp_dist_dir] +\n                        config_settings[\"--global-option\"])\n            self.run_setup()\n\n            wheel_basename = _file_with_extension(tmp_dist_dir, '.whl')\n            wheel_path = os.path.join(wheel_directory, wheel_basename)\n            if os.path.exists(wheel_path):\n                # os.rename will fail overwriting on non-unix env\n                os.remove(wheel_path)\n            os.rename(os.path.join(tmp_dist_dir, wheel_basename), wheel_path)\n\n        return wheel_basename\n\n    def build_sdist(self, sdist_directory, config_settings=None):\n        config_settings = self._fix_config(config_settings)\n        sdist_directory = os.path.abspath(sdist_directory)\n        sys.argv = sys.argv[:1] + ['sdist', '--formats', 'gztar'] + \\\n            config_settings[\"--global-option\"] + \\\n            [\"--dist-dir\", sdist_directory]\n        self.run_setup()\n\n        return _file_with_extension(sdist_directory, '.tar.gz')\n\n\nclass _BuildMetaLegacyBackend(_BuildMetaBackend):\n    \"\"\"Compatibility backend for setuptools\n\n    This is a version of setuptools.build_meta that endeavors to maintain backwards\n    compatibility with pre-PEP 517 modes of invocation. It exists as a temporary\n    bridge between the old packaging mechanism and the new 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        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\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\nfrom pkg_resources.py31compat import makedirs\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\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(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 (len(dist_infos) == 0 and\n                len(_get_immediate_subdirectories(dist_info_directory)) == 1):\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        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(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\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 to maintain backwards\n    compatibility with pre-PEP 517 modes of invocation. It exists as a temporary\n    bridge between the old packaging mechanism and the new 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        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\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"}]}