Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/setuptools/build_meta.py
7763 views
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
273