Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
keewenaw
GitHub Repository: keewenaw/ethereum-wallet-cracker
Path: blob/main/test/lib/python3.9/site-packages/setuptools/_distutils/sysconfig.py
4799 views
1
"""Provide access to Python's configuration information. The specific
2
configuration variables available depend heavily on the platform and
3
configuration. The values may be retrieved using
4
get_config_var(name), and the list of variables is available via
5
get_config_vars().keys(). Additional convenience functions are also
6
available.
7
8
Written by: Fred L. Drake, Jr.
9
Email: <[email protected]>
10
"""
11
12
import os
13
import re
14
import sys
15
import sysconfig
16
17
from .errors import DistutilsPlatformError
18
from . import py39compat
19
from ._functools import pass_none
20
21
IS_PYPY = '__pypy__' in sys.builtin_module_names
22
23
# These are needed in a couple of spots, so just compute them once.
24
PREFIX = os.path.normpath(sys.prefix)
25
EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
26
BASE_PREFIX = os.path.normpath(sys.base_prefix)
27
BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
28
29
# Path to the base directory of the project. On Windows the binary may
30
# live in project/PCbuild/win32 or project/PCbuild/amd64.
31
# set for cross builds
32
if "_PYTHON_PROJECT_BASE" in os.environ:
33
project_base = os.path.abspath(os.environ["_PYTHON_PROJECT_BASE"])
34
else:
35
if sys.executable:
36
project_base = os.path.dirname(os.path.abspath(sys.executable))
37
else:
38
# sys.executable can be empty if argv[0] has been changed and Python is
39
# unable to retrieve the real program name
40
project_base = os.getcwd()
41
42
43
# python_build: (Boolean) if true, we're either building Python or
44
# building an extension with an un-installed Python, so we use
45
# different (hard-wired) directories.
46
def _is_python_source_dir(d):
47
for fn in ("Setup", "Setup.local"):
48
if os.path.isfile(os.path.join(d, "Modules", fn)):
49
return True
50
return False
51
52
53
_sys_home = getattr(sys, '_home', None)
54
55
56
def _is_parent(dir_a, dir_b):
57
"""
58
Return True if a is a parent of b.
59
"""
60
return os.path.normcase(dir_a).startswith(os.path.normcase(dir_b))
61
62
63
if os.name == 'nt':
64
@pass_none
65
def _fix_pcbuild(d):
66
# In a venv, sys._home will be inside BASE_PREFIX rather than PREFIX.
67
prefixes = PREFIX, BASE_PREFIX
68
matched = (
69
prefix
70
for prefix in prefixes
71
if _is_parent(d, os.path.join(prefix, "PCbuild"))
72
)
73
return next(matched, d)
74
project_base = _fix_pcbuild(project_base)
75
_sys_home = _fix_pcbuild(_sys_home)
76
77
78
def _python_build():
79
if _sys_home:
80
return _is_python_source_dir(_sys_home)
81
return _is_python_source_dir(project_base)
82
83
84
python_build = _python_build()
85
86
87
# Calculate the build qualifier flags if they are defined. Adding the flags
88
# to the include and lib directories only makes sense for an installation, not
89
# an in-source build.
90
build_flags = ''
91
try:
92
if not python_build:
93
build_flags = sys.abiflags
94
except AttributeError:
95
# It's not a configure-based build, so the sys module doesn't have
96
# this attribute, which is fine.
97
pass
98
99
100
def get_python_version():
101
"""Return a string containing the major and minor Python version,
102
leaving off the patchlevel. Sample return values could be '1.5'
103
or '2.2'.
104
"""
105
return '%d.%d' % sys.version_info[:2]
106
107
108
def get_python_inc(plat_specific=0, prefix=None):
109
"""Return the directory containing installed Python header files.
110
111
If 'plat_specific' is false (the default), this is the path to the
112
non-platform-specific header files, i.e. Python.h and so on;
113
otherwise, this is the path to platform-specific header files
114
(namely pyconfig.h).
115
116
If 'prefix' is supplied, use it instead of sys.base_prefix or
117
sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
118
"""
119
if prefix is None:
120
prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
121
if os.name == "posix":
122
if IS_PYPY and sys.version_info < (3, 8):
123
return os.path.join(prefix, 'include')
124
if python_build:
125
# Assume the executable is in the build directory. The
126
# pyconfig.h file should be in the same directory. Since
127
# the build directory may not be the source directory, we
128
# must use "srcdir" from the makefile to find the "Include"
129
# directory.
130
if plat_specific:
131
return _sys_home or project_base
132
else:
133
incdir = os.path.join(get_config_var('srcdir'), 'Include')
134
return os.path.normpath(incdir)
135
implementation = 'pypy' if IS_PYPY else 'python'
136
python_dir = implementation + get_python_version() + build_flags
137
return os.path.join(prefix, "include", python_dir)
138
elif os.name == "nt":
139
if python_build:
140
# Include both the include and PC dir to ensure we can find
141
# pyconfig.h
142
return (os.path.join(prefix, "include") + os.path.pathsep +
143
os.path.join(prefix, "PC"))
144
return os.path.join(prefix, "include")
145
else:
146
raise DistutilsPlatformError(
147
"I don't know where Python installs its C header files "
148
"on platform '%s'" % os.name)
149
150
151
# allow this behavior to be monkey-patched. Ref pypa/distutils#2.
152
def _posix_lib(standard_lib, libpython, early_prefix, prefix):
153
if standard_lib:
154
return libpython
155
else:
156
return os.path.join(libpython, "site-packages")
157
158
159
def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
160
"""Return the directory containing the Python library (standard or
161
site additions).
162
163
If 'plat_specific' is true, return the directory containing
164
platform-specific modules, i.e. any module from a non-pure-Python
165
module distribution; otherwise, return the platform-shared library
166
directory. If 'standard_lib' is true, return the directory
167
containing standard Python library modules; otherwise, return the
168
directory for site-specific modules.
169
170
If 'prefix' is supplied, use it instead of sys.base_prefix or
171
sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
172
"""
173
174
if IS_PYPY and sys.version_info < (3, 8):
175
# PyPy-specific schema
176
if prefix is None:
177
prefix = PREFIX
178
if standard_lib:
179
return os.path.join(prefix, "lib-python", sys.version[0])
180
return os.path.join(prefix, 'site-packages')
181
182
early_prefix = prefix
183
184
if prefix is None:
185
if standard_lib:
186
prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
187
else:
188
prefix = plat_specific and EXEC_PREFIX or PREFIX
189
190
if os.name == "posix":
191
if plat_specific or standard_lib:
192
# Platform-specific modules (any module from a non-pure-Python
193
# module distribution) or standard Python library modules.
194
libdir = getattr(sys, "platlibdir", "lib")
195
else:
196
# Pure Python
197
libdir = "lib"
198
implementation = 'pypy' if IS_PYPY else 'python'
199
libpython = os.path.join(prefix, libdir,
200
implementation + get_python_version())
201
return _posix_lib(standard_lib, libpython, early_prefix, prefix)
202
elif os.name == "nt":
203
if standard_lib:
204
return os.path.join(prefix, "Lib")
205
else:
206
return os.path.join(prefix, "Lib", "site-packages")
207
else:
208
raise DistutilsPlatformError(
209
"I don't know where Python installs its library "
210
"on platform '%s'" % os.name)
211
212
213
def customize_compiler(compiler):
214
"""Do any platform-specific customization of a CCompiler instance.
215
216
Mainly needed on Unix, so we can plug in the information that
217
varies across Unices and is stored in Python's Makefile.
218
"""
219
if compiler.compiler_type == "unix":
220
if sys.platform == "darwin":
221
# Perform first-time customization of compiler-related
222
# config vars on OS X now that we know we need a compiler.
223
# This is primarily to support Pythons from binary
224
# installers. The kind and paths to build tools on
225
# the user system may vary significantly from the system
226
# that Python itself was built on. Also the user OS
227
# version and build tools may not support the same set
228
# of CPU architectures for universal builds.
229
global _config_vars
230
# Use get_config_var() to ensure _config_vars is initialized.
231
if not get_config_var('CUSTOMIZED_OSX_COMPILER'):
232
import _osx_support
233
_osx_support.customize_compiler(_config_vars)
234
_config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True'
235
236
(cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \
237
get_config_vars(
238
'CC', 'CXX', 'CFLAGS',
239
'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS')
240
241
if 'CC' in os.environ:
242
newcc = os.environ['CC']
243
if('LDSHARED' not in os.environ
244
and ldshared.startswith(cc)):
245
# If CC is overridden, use that as the default
246
# command for LDSHARED as well
247
ldshared = newcc + ldshared[len(cc):]
248
cc = newcc
249
if 'CXX' in os.environ:
250
cxx = os.environ['CXX']
251
if 'LDSHARED' in os.environ:
252
ldshared = os.environ['LDSHARED']
253
if 'CPP' in os.environ:
254
cpp = os.environ['CPP']
255
else:
256
cpp = cc + " -E" # not always
257
if 'LDFLAGS' in os.environ:
258
ldshared = ldshared + ' ' + os.environ['LDFLAGS']
259
if 'CFLAGS' in os.environ:
260
cflags = cflags + ' ' + os.environ['CFLAGS']
261
ldshared = ldshared + ' ' + os.environ['CFLAGS']
262
if 'CPPFLAGS' in os.environ:
263
cpp = cpp + ' ' + os.environ['CPPFLAGS']
264
cflags = cflags + ' ' + os.environ['CPPFLAGS']
265
ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
266
if 'AR' in os.environ:
267
ar = os.environ['AR']
268
if 'ARFLAGS' in os.environ:
269
archiver = ar + ' ' + os.environ['ARFLAGS']
270
else:
271
archiver = ar + ' ' + ar_flags
272
273
cc_cmd = cc + ' ' + cflags
274
compiler.set_executables(
275
preprocessor=cpp,
276
compiler=cc_cmd,
277
compiler_so=cc_cmd + ' ' + ccshared,
278
compiler_cxx=cxx,
279
linker_so=ldshared,
280
linker_exe=cc,
281
archiver=archiver)
282
283
if 'RANLIB' in os.environ and compiler.executables.get('ranlib', None):
284
compiler.set_executables(ranlib=os.environ['RANLIB'])
285
286
compiler.shared_lib_extension = shlib_suffix
287
288
289
def get_config_h_filename():
290
"""Return full pathname of installed pyconfig.h file."""
291
if python_build:
292
if os.name == "nt":
293
inc_dir = os.path.join(_sys_home or project_base, "PC")
294
else:
295
inc_dir = _sys_home or project_base
296
return os.path.join(inc_dir, 'pyconfig.h')
297
else:
298
return sysconfig.get_config_h_filename()
299
300
301
def get_makefile_filename():
302
"""Return full pathname of installed Makefile from the Python build."""
303
return sysconfig.get_makefile_filename()
304
305
306
def parse_config_h(fp, g=None):
307
"""Parse a config.h-style file.
308
309
A dictionary containing name/value pairs is returned. If an
310
optional dictionary is passed in as the second argument, it is
311
used instead of a new dictionary.
312
"""
313
return sysconfig.parse_config_h(fp, vars=g)
314
315
316
# Regexes needed for parsing Makefile (and similar syntaxes,
317
# like old-style Setup files).
318
_variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
319
_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
320
_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
321
322
323
def parse_makefile(fn, g=None):
324
"""Parse a Makefile-style file.
325
326
A dictionary containing name/value pairs is returned. If an
327
optional dictionary is passed in as the second argument, it is
328
used instead of a new dictionary.
329
"""
330
from distutils.text_file import TextFile
331
fp = TextFile(
332
fn, strip_comments=1, skip_blanks=1, join_lines=1,
333
errors="surrogateescape")
334
335
if g is None:
336
g = {}
337
done = {}
338
notdone = {}
339
340
while True:
341
line = fp.readline()
342
if line is None: # eof
343
break
344
m = _variable_rx.match(line)
345
if m:
346
n, v = m.group(1, 2)
347
v = v.strip()
348
# `$$' is a literal `$' in make
349
tmpv = v.replace('$$', '')
350
351
if "$" in tmpv:
352
notdone[n] = v
353
else:
354
try:
355
v = int(v)
356
except ValueError:
357
# insert literal `$'
358
done[n] = v.replace('$$', '$')
359
else:
360
done[n] = v
361
362
# Variables with a 'PY_' prefix in the makefile. These need to
363
# be made available without that prefix through sysconfig.
364
# Special care is needed to ensure that variable expansion works, even
365
# if the expansion uses the name without a prefix.
366
renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
367
368
# do variable interpolation here
369
while notdone:
370
for name in list(notdone):
371
value = notdone[name]
372
m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
373
if m:
374
n = m.group(1)
375
found = True
376
if n in done:
377
item = str(done[n])
378
elif n in notdone:
379
# get it on a subsequent round
380
found = False
381
elif n in os.environ:
382
# do it like make: fall back to environment
383
item = os.environ[n]
384
385
elif n in renamed_variables:
386
if name.startswith('PY_') and \
387
name[3:] in renamed_variables:
388
item = ""
389
390
elif 'PY_' + n in notdone:
391
found = False
392
393
else:
394
item = str(done['PY_' + n])
395
else:
396
done[n] = item = ""
397
if found:
398
after = value[m.end():]
399
value = value[:m.start()] + item + after
400
if "$" in after:
401
notdone[name] = value
402
else:
403
try:
404
value = int(value)
405
except ValueError:
406
done[name] = value.strip()
407
else:
408
done[name] = value
409
del notdone[name]
410
411
if name.startswith('PY_') \
412
and name[3:] in renamed_variables:
413
414
name = name[3:]
415
if name not in done:
416
done[name] = value
417
else:
418
# bogus variable reference; just drop it since we can't deal
419
del notdone[name]
420
421
fp.close()
422
423
# strip spurious spaces
424
for k, v in done.items():
425
if isinstance(v, str):
426
done[k] = v.strip()
427
428
# save the results in the global dictionary
429
g.update(done)
430
return g
431
432
433
def expand_makefile_vars(s, vars):
434
"""Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
435
'string' according to 'vars' (a dictionary mapping variable names to
436
values). Variables not present in 'vars' are silently expanded to the
437
empty string. The variable values in 'vars' should not contain further
438
variable expansions; if 'vars' is the output of 'parse_makefile()',
439
you're fine. Returns a variable-expanded version of 's'.
440
"""
441
442
# This algorithm does multiple expansion, so if vars['foo'] contains
443
# "${bar}", it will expand ${foo} to ${bar}, and then expand
444
# ${bar}... and so forth. This is fine as long as 'vars' comes from
445
# 'parse_makefile()', which takes care of such expansions eagerly,
446
# according to make's variable expansion semantics.
447
448
while True:
449
m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
450
if m:
451
(beg, end) = m.span()
452
s = s[0:beg] + vars.get(m.group(1)) + s[end:]
453
else:
454
break
455
return s
456
457
458
_config_vars = None
459
460
461
def get_config_vars(*args):
462
"""With no arguments, return a dictionary of all configuration
463
variables relevant for the current platform. Generally this includes
464
everything needed to build extensions and install both pure modules and
465
extensions. On Unix, this means every variable defined in Python's
466
installed Makefile; on Windows it's a much smaller set.
467
468
With arguments, return a list of values that result from looking up
469
each argument in the configuration variable dictionary.
470
"""
471
global _config_vars
472
if _config_vars is None:
473
_config_vars = sysconfig.get_config_vars().copy()
474
py39compat.add_ext_suffix(_config_vars)
475
476
if args:
477
vals = []
478
for name in args:
479
vals.append(_config_vars.get(name))
480
return vals
481
else:
482
return _config_vars
483
484
485
def get_config_var(name):
486
"""Return the value of a single variable using the dictionary
487
returned by 'get_config_vars()'. Equivalent to
488
get_config_vars().get(name)
489
"""
490
if name == 'SO':
491
import warnings
492
warnings.warn(
493
'SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
494
return get_config_vars().get(name)
495
496