- Notifications
You must be signed in to change notification settings - Fork 31.7k
/
Copy path__init__.py
722 lines (618 loc) · 26.3 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
"""Access to Python's configuration information."""
importos
importsys
importthreading
fromos.pathimportrealpath
__all__= [
'get_config_h_filename',
'get_config_var',
'get_config_vars',
'get_makefile_filename',
'get_path',
'get_path_names',
'get_paths',
'get_platform',
'get_python_version',
'get_scheme_names',
'parse_config_h',
]
# Keys for get_config_var() that are never converted to Python integers.
_ALWAYS_STR= {
'IPHONEOS_DEPLOYMENT_TARGET',
'MACOSX_DEPLOYMENT_TARGET',
}
_INSTALL_SCHEMES= {
'posix_prefix': {
'stdlib': '{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
'platstdlib': '{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
'purelib': '{base}/lib/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
'platlib': '{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
'include':
'{installed_base}/include/{implementation_lower}{py_version_short}{abiflags}',
'platinclude':
'{installed_platbase}/include/{implementation_lower}{py_version_short}{abiflags}',
'scripts': '{base}/bin',
'data': '{base}',
},
'posix_home': {
'stdlib': '{installed_base}/lib/{implementation_lower}',
'platstdlib': '{base}/lib/{implementation_lower}',
'purelib': '{base}/lib/{implementation_lower}',
'platlib': '{base}/lib/{implementation_lower}',
'include': '{installed_base}/include/{implementation_lower}',
'platinclude': '{installed_base}/include/{implementation_lower}',
'scripts': '{base}/bin',
'data': '{base}',
},
'nt': {
'stdlib': '{installed_base}/Lib',
'platstdlib': '{base}/Lib',
'purelib': '{base}/Lib/site-packages',
'platlib': '{base}/Lib/site-packages',
'include': '{installed_base}/Include',
'platinclude': '{installed_base}/Include',
'scripts': '{base}/Scripts',
'data': '{base}',
},
# Downstream distributors can overwrite the default install scheme.
# This is done to support downstream modifications where distributors change
# the installation layout (eg. different site-packages directory).
# So, distributors will change the default scheme to one that correctly
# represents their layout.
# This presents an issue for projects/people that need to bootstrap virtual
# environments, like virtualenv. As distributors might now be customizing
# the default install scheme, there is no guarantee that the information
# returned by sysconfig.get_default_scheme/get_paths is correct for
# a virtual environment, the only guarantee we have is that it is correct
# for the *current* environment. When bootstrapping a virtual environment,
# we need to know its layout, so that we can place the files in the
# correct locations.
# The "*_venv" install scheme is a scheme to bootstrap virtual environments,
# essentially identical to the default posix_prefix/nt schemes.
# Downstream distributors who patch posix_prefix/nt scheme are encouraged to
# leave the following schemes unchanged
'posix_venv': {
'stdlib': '{installed_base}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
'platstdlib': '{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
'purelib': '{base}/lib/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
'platlib': '{platbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
'include':
'{installed_base}/include/{implementation_lower}{py_version_short}{abiflags}',
'platinclude':
'{installed_platbase}/include/{implementation_lower}{py_version_short}{abiflags}',
'scripts': '{base}/bin',
'data': '{base}',
},
'nt_venv': {
'stdlib': '{installed_base}/Lib',
'platstdlib': '{base}/Lib',
'purelib': '{base}/Lib/site-packages',
'platlib': '{base}/Lib/site-packages',
'include': '{installed_base}/Include',
'platinclude': '{installed_base}/Include',
'scripts': '{base}/Scripts',
'data': '{base}',
},
}
# For the OS-native venv scheme, we essentially provide an alias:
ifos.name=='nt':
_INSTALL_SCHEMES['venv'] =_INSTALL_SCHEMES['nt_venv']
else:
_INSTALL_SCHEMES['venv'] =_INSTALL_SCHEMES['posix_venv']
def_get_implementation():
return'Python'
# NOTE: site.py has copy of this function.
# Sync it when modify this function.
def_getuserbase():
env_base=os.environ.get("PYTHONUSERBASE", None)
ifenv_base:
returnenv_base
# Emscripten, iOS, tvOS, VxWorks, WASI, and watchOS have no home directories
ifsys.platformin {"emscripten", "ios", "tvos", "vxworks", "wasi", "watchos"}:
returnNone
defjoinuser(*args):
returnos.path.expanduser(os.path.join(*args))
ifos.name=="nt":
base=os.environ.get("APPDATA") or"~"
returnjoinuser(base, _get_implementation())
ifsys.platform=="darwin"andsys._framework:
returnjoinuser("~", "Library", sys._framework,
f"{sys.version_info[0]}.{sys.version_info[1]}")
returnjoinuser("~", ".local")
_HAS_USER_BASE= (_getuserbase() isnotNone)
if_HAS_USER_BASE:
_INSTALL_SCHEMES|= {
# NOTE: When modifying "purelib" scheme, update site._get_path() too.
'nt_user': {
'stdlib': '{userbase}/{implementation}{py_version_nodot_plat}',
'platstdlib': '{userbase}/{implementation}{py_version_nodot_plat}',
'purelib': '{userbase}/{implementation}{py_version_nodot_plat}/site-packages',
'platlib': '{userbase}/{implementation}{py_version_nodot_plat}/site-packages',
'include': '{userbase}/{implementation}{py_version_nodot_plat}/Include',
'scripts': '{userbase}/{implementation}{py_version_nodot_plat}/Scripts',
'data': '{userbase}',
},
'posix_user': {
'stdlib': '{userbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
'platstdlib': '{userbase}/{platlibdir}/{implementation_lower}{py_version_short}{abi_thread}',
'purelib': '{userbase}/lib/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
'platlib': '{userbase}/lib/{implementation_lower}{py_version_short}{abi_thread}/site-packages',
'include': '{userbase}/include/{implementation_lower}{py_version_short}{abi_thread}',
'scripts': '{userbase}/bin',
'data': '{userbase}',
},
'osx_framework_user': {
'stdlib': '{userbase}/lib/{implementation_lower}',
'platstdlib': '{userbase}/lib/{implementation_lower}',
'purelib': '{userbase}/lib/{implementation_lower}/site-packages',
'platlib': '{userbase}/lib/{implementation_lower}/site-packages',
'include': '{userbase}/include/{implementation_lower}{py_version_short}',
'scripts': '{userbase}/bin',
'data': '{userbase}',
},
}
_SCHEME_KEYS= ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
'scripts', 'data')
_PY_VERSION=sys.version.split()[0]
_PY_VERSION_SHORT=f'{sys.version_info[0]}.{sys.version_info[1]}'
_PY_VERSION_SHORT_NO_DOT=f'{sys.version_info[0]}{sys.version_info[1]}'
_BASE_PREFIX=os.path.normpath(sys.base_prefix)
_BASE_EXEC_PREFIX=os.path.normpath(sys.base_exec_prefix)
# Mutex guarding initialization of _CONFIG_VARS.
_CONFIG_VARS_LOCK=threading.RLock()
_CONFIG_VARS=None
# True iff _CONFIG_VARS has been fully initialized.
_CONFIG_VARS_INITIALIZED=False
_USER_BASE=None
def_safe_realpath(path):
try:
returnrealpath(path)
exceptOSError:
returnpath
ifsys.executable:
_PROJECT_BASE=os.path.dirname(_safe_realpath(sys.executable))
else:
# sys.executable can be empty if argv[0] has been changed and Python is
# unable to retrieve the real program name
_PROJECT_BASE=_safe_realpath(os.getcwd())
# In a virtual environment, `sys._home` gives us the target directory
# `_PROJECT_BASE` for the executable that created it when the virtual
# python is an actual executable ('venv --copies' or Windows).
_sys_home=getattr(sys, '_home', None)
if_sys_home:
_PROJECT_BASE=_sys_home
ifos.name=='nt':
# In a source build, the executable is in a subdirectory of the root
# that we want (<root>\PCbuild\<platname>).
# `_BASE_PREFIX` is used as the base installation is where the source
# will be. The realpath is needed to prevent mount point confusion
# that can occur with just string comparisons.
if_safe_realpath(_PROJECT_BASE).startswith(
_safe_realpath(f'{_BASE_PREFIX}\\PCbuild')):
_PROJECT_BASE=_BASE_PREFIX
# set for cross builds
if"_PYTHON_PROJECT_BASE"inos.environ:
_PROJECT_BASE=_safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])
defis_python_build(check_home=None):
ifcheck_homeisnotNone:
importwarnings
warnings.warn(
(
'The check_home argument of sysconfig.is_python_build is '
'deprecated and its value is ignored. '
'It will be removed in Python 3.15.'
),
DeprecationWarning,
stacklevel=2,
)
forfnin ("Setup", "Setup.local"):
ifos.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
returnTrue
returnFalse
_PYTHON_BUILD=is_python_build()
if_PYTHON_BUILD:
forschemein ('posix_prefix', 'posix_home'):
# On POSIX-y platforms, Python will:
# - Build from .h files in 'headers' (which is only added to the
# scheme when building CPython)
# - Install .h files to 'include'
scheme=_INSTALL_SCHEMES[scheme]
scheme['headers'] =scheme['include']
scheme['include'] ='{srcdir}/Include'
scheme['platinclude'] ='{projectbase}/.'
delscheme
def_subst_vars(s, local_vars):
try:
returns.format(**local_vars)
exceptKeyErrorasvar:
try:
returns.format(**os.environ)
exceptKeyError:
raiseAttributeError(f'{var}') fromNone
def_extend_dict(target_dict, other_dict):
target_keys=target_dict.keys()
forkey, valueinother_dict.items():
ifkeyintarget_keys:
continue
target_dict[key] =value
def_expand_vars(scheme, vars):
res= {}
ifvarsisNone:
vars= {}
_extend_dict(vars, get_config_vars())
ifos.name=='nt':
# On Windows we want to substitute 'lib' for schemes rather
# than the native value (without modifying vars, in case it
# was passed in)
vars=vars| {'platlibdir': 'lib'}
forkey, valuein_INSTALL_SCHEMES[scheme].items():
ifos.namein ('posix', 'nt'):
value=os.path.expanduser(value)
res[key] =os.path.normpath(_subst_vars(value, vars))
returnres
def_get_preferred_schemes():
ifos.name=='nt':
return {
'prefix': 'nt',
'home': 'posix_home',
'user': 'nt_user',
}
ifsys.platform=='darwin'andsys._framework:
return {
'prefix': 'posix_prefix',
'home': 'posix_home',
'user': 'osx_framework_user',
}
return {
'prefix': 'posix_prefix',
'home': 'posix_home',
'user': 'posix_user',
}
defget_preferred_scheme(key):
ifkey=='prefix'andsys.prefix!=sys.base_prefix:
return'venv'
scheme=_get_preferred_schemes()[key]
ifschemenotin_INSTALL_SCHEMES:
raiseValueError(
f"{key!r} returned {scheme!r}, which is not a valid scheme "
f"on this platform"
)
returnscheme
defget_default_scheme():
returnget_preferred_scheme('prefix')
defget_makefile_filename():
"""Return the path of the Makefile."""
if_PYTHON_BUILD:
returnos.path.join(_PROJECT_BASE, "Makefile")
ifhasattr(sys, 'abiflags'):
config_dir_name=f'config-{_PY_VERSION_SHORT}{sys.abiflags}'
else:
config_dir_name='config'
ifhasattr(sys.implementation, '_multiarch'):
config_dir_name+=f'-{sys.implementation._multiarch}'
returnos.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
def_get_sysconfigdata_name():
multiarch=getattr(sys.implementation, '_multiarch', '')
returnos.environ.get(
'_PYTHON_SYSCONFIGDATA_NAME',
f'_sysconfigdata_{sys.abiflags}_{sys.platform}_{multiarch}',
)
def_init_posix(vars):
"""Initialize the module as appropriate for POSIX systems."""
# _sysconfigdata is generated at build time, see _generate_posix_vars()
name=_get_sysconfigdata_name()
# For cross builds, the path to the target's sysconfigdata must be specified
# so it can be imported. It cannot be in PYTHONPATH, as foreign modules in
# sys.path can cause crashes when loaded by the host interpreter.
# Rely on truthiness as a valueless env variable is still an empty string.
# See OS X note in _generate_posix_vars re _sysconfigdata.
if (path:=os.environ.get('_PYTHON_SYSCONFIGDATA_PATH')):
fromimportlib.machineryimportFileFinder, SourceFileLoader, SOURCE_SUFFIXES
fromimportlib.utilimportmodule_from_spec
spec=FileFinder(path, (SourceFileLoader, SOURCE_SUFFIXES)).find_spec(name)
_temp=module_from_spec(spec)
spec.loader.exec_module(_temp)
else:
_temp=__import__(name, globals(), locals(), ['build_time_vars'], 0)
build_time_vars=_temp.build_time_vars
vars.update(build_time_vars)
def_init_non_posix(vars):
"""Initialize the module as appropriate for NT"""
# set basic install directories
import_winapi
import_sysconfig
vars['LIBDEST'] =get_path('stdlib')
vars['BINLIBDEST'] =get_path('platstdlib')
vars['INCLUDEPY'] =get_path('include')
# Add EXT_SUFFIX, SOABI, and Py_GIL_DISABLED
vars.update(_sysconfig.config_vars())
vars['LIBDIR'] =_safe_realpath(os.path.join(get_config_var('installed_base'), 'libs'))
ifhasattr(sys, 'dllhandle'):
dllhandle=_winapi.GetModuleFileName(sys.dllhandle)
vars['LIBRARY'] =os.path.basename(_safe_realpath(dllhandle))
vars['LDLIBRARY'] =vars['LIBRARY']
vars['EXE'] ='.exe'
vars['VERSION'] =_PY_VERSION_SHORT_NO_DOT
vars['BINDIR'] =os.path.dirname(_safe_realpath(sys.executable))
vars['TZPATH'] =''
#
# public APIs
#
defparse_config_h(fp, vars=None):
"""Parse a config.h-style file.
A dictionary containing name/value pairs is returned. If an
optional dictionary is passed in as the second argument, it is
used instead of a new dictionary.
"""
ifvarsisNone:
vars= {}
importre
define_rx=re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
undef_rx=re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
whileTrue:
line=fp.readline()
ifnotline:
break
m=define_rx.match(line)
ifm:
n, v=m.group(1, 2)
try:
ifnin_ALWAYS_STR:
raiseValueError
v=int(v)
exceptValueError:
pass
vars[n] =v
else:
m=undef_rx.match(line)
ifm:
vars[m.group(1)] =0
returnvars
defget_config_h_filename():
"""Return the path of pyconfig.h."""
if_PYTHON_BUILD:
ifos.name=="nt":
inc_dir=os.path.dirname(sys._base_executable)
else:
inc_dir=_PROJECT_BASE
else:
inc_dir=get_path('platinclude')
returnos.path.join(inc_dir, 'pyconfig.h')
defget_scheme_names():
"""Return a tuple containing the schemes names."""
returntuple(sorted(_INSTALL_SCHEMES))
defget_path_names():
"""Return a tuple containing the paths names."""
return_SCHEME_KEYS
defget_paths(scheme=get_default_scheme(), vars=None, expand=True):
"""Return a mapping containing an install scheme.
``scheme`` is the install scheme name. If not provided, it will
return the default scheme for the current platform.
"""
ifexpand:
return_expand_vars(scheme, vars)
else:
return_INSTALL_SCHEMES[scheme]
defget_path(name, scheme=get_default_scheme(), vars=None, expand=True):
"""Return a path corresponding to the scheme.
``scheme`` is the install scheme name.
"""
returnget_paths(scheme, vars, expand)[name]
def_init_config_vars():
global_CONFIG_VARS
_CONFIG_VARS= {}
# Normalized versions of prefix and exec_prefix are handy to have;
# in fact, these are the standard versions used most places in the
# Distutils.
_PREFIX=os.path.normpath(sys.prefix)
_EXEC_PREFIX=os.path.normpath(sys.exec_prefix)
_CONFIG_VARS['prefix'] =_PREFIX# FIXME: This gets overwriten by _init_posix.
_CONFIG_VARS['exec_prefix'] =_EXEC_PREFIX# FIXME: This gets overwriten by _init_posix.
_CONFIG_VARS['py_version'] =_PY_VERSION
_CONFIG_VARS['py_version_short'] =_PY_VERSION_SHORT
_CONFIG_VARS['py_version_nodot'] =_PY_VERSION_SHORT_NO_DOT
_CONFIG_VARS['installed_base'] =_BASE_PREFIX
_CONFIG_VARS['base'] =_PREFIX
_CONFIG_VARS['installed_platbase'] =_BASE_EXEC_PREFIX
_CONFIG_VARS['platbase'] =_EXEC_PREFIX
_CONFIG_VARS['projectbase'] =_PROJECT_BASE
_CONFIG_VARS['platlibdir'] =sys.platlibdir
_CONFIG_VARS['implementation'] =_get_implementation()
_CONFIG_VARS['implementation_lower'] =_get_implementation().lower()
try:
_CONFIG_VARS['abiflags'] =sys.abiflags
exceptAttributeError:
# sys.abiflags may not be defined on all platforms.
_CONFIG_VARS['abiflags'] =''
try:
_CONFIG_VARS['py_version_nodot_plat'] =sys.winver.replace('.', '')
exceptAttributeError:
_CONFIG_VARS['py_version_nodot_plat'] =''
ifos.name=='nt':
_init_non_posix(_CONFIG_VARS)
_CONFIG_VARS['VPATH'] =sys._vpath
ifos.name=='posix':
_init_posix(_CONFIG_VARS)
if_HAS_USER_BASE:
# Setting 'userbase' is done below the call to the
# init function to enable using 'get_config_var' in
# the init-function.
_CONFIG_VARS['userbase'] =_getuserbase()
# e.g., 't' for free-threaded or '' for default build
_CONFIG_VARS['abi_thread'] ='t'if_CONFIG_VARS.get('Py_GIL_DISABLED') else''
# Always convert srcdir to an absolute path
srcdir=_CONFIG_VARS.get('srcdir', _PROJECT_BASE)
ifos.name=='posix':
if_PYTHON_BUILD:
# If srcdir is a relative path (typically '.' or '..')
# then it should be interpreted relative to the directory
# containing Makefile.
base=os.path.dirname(get_makefile_filename())
srcdir=os.path.join(base, srcdir)
else:
# srcdir is not meaningful since the installation is
# spread about the filesystem. We choose the
# directory containing the Makefile since we know it
# exists.
srcdir=os.path.dirname(get_makefile_filename())
_CONFIG_VARS['srcdir'] =_safe_realpath(srcdir)
# OS X platforms require special customization to handle
# multi-architecture, multi-os-version installers
ifsys.platform=='darwin':
import_osx_support
_osx_support.customize_config_vars(_CONFIG_VARS)
global_CONFIG_VARS_INITIALIZED
_CONFIG_VARS_INITIALIZED=True
defget_config_vars(*args):
"""With no arguments, return a dictionary of all configuration
variables relevant for the current platform.
On Unix, this means every variable defined in Python's installed Makefile;
On Windows it's a much smaller set.
With arguments, return a list of values that result from looking up
each argument in the configuration variable dictionary.
"""
global_CONFIG_VARS_INITIALIZED
# Avoid claiming the lock once initialization is complete.
ifnot_CONFIG_VARS_INITIALIZED:
with_CONFIG_VARS_LOCK:
# Test again with the lock held to avoid races. Note that
# we test _CONFIG_VARS here, not _CONFIG_VARS_INITIALIZED,
# to ensure that recursive calls to get_config_vars()
# don't re-enter init_config_vars().
if_CONFIG_VARSisNone:
_init_config_vars()
else:
# If the site module initialization happened after _CONFIG_VARS was
# initialized, a virtual environment might have been activated, resulting in
# variables like sys.prefix changing their value, so we need to re-init the
# config vars (see GH-126789).
if_CONFIG_VARS['base'] !=os.path.normpath(sys.prefix):
with_CONFIG_VARS_LOCK:
_CONFIG_VARS_INITIALIZED=False
_init_config_vars()
ifargs:
vals= []
fornameinargs:
vals.append(_CONFIG_VARS.get(name))
returnvals
else:
return_CONFIG_VARS
defget_config_var(name):
"""Return the value of a single variable using the dictionary returned by
'get_config_vars()'.
Equivalent to get_config_vars().get(name)
"""
returnget_config_vars().get(name)
defget_platform():
"""Return a string that identifies the current platform.
This is used mainly to distinguish platform-specific build directories and
platform-specific built distributions. Typically includes the OS name and
version and the architecture (as supplied by 'os.uname()'), although the
exact information included depends on the OS; on Linux, the kernel version
isn't particularly important.
Examples of returned values:
linux-i586
linux-alpha (?)
solaris-2.6-sun4u
Windows will return one of:
win-amd64 (64-bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
win-arm64 (64-bit Windows on ARM64 (aka AArch64)
win32 (all others - specifically, sys.platform is returned)
For other non-POSIX platforms, currently just returns 'sys.platform'.
"""
ifos.name=='nt':
if'amd64'insys.version.lower():
return'win-amd64'
if'(arm)'insys.version.lower():
return'win-arm32'
if'(arm64)'insys.version.lower():
return'win-arm64'
returnsys.platform
ifos.name!="posix"ornothasattr(os, 'uname'):
# XXX what about the architecture? NT is Intel or Alpha
returnsys.platform
# Set for cross builds explicitly
if"_PYTHON_HOST_PLATFORM"inos.environ:
returnos.environ["_PYTHON_HOST_PLATFORM"]
# Try to distinguish various flavours of Unix
osname, host, release, version, machine=os.uname()
# Convert the OS name to lowercase, remove '/' characters, and translate
# spaces (for "Power Macintosh")
osname=osname.lower().replace('/', '')
machine=machine.replace(' ', '_')
machine=machine.replace('/', '-')
ifosname[:5] =="linux":
ifsys.platform=="android":
osname="android"
release=get_config_var("ANDROID_API_LEVEL")
# Wheel tags use the ABI names from Android's own tools.
machine= {
"x86_64": "x86_64",
"i686": "x86",
"aarch64": "arm64_v8a",
"armv7l": "armeabi_v7a",
}[machine]
else:
# At least on Linux/Intel, 'machine' is the processor --
# i386, etc.
# XXX what about Alpha, SPARC, etc?
returnf"{osname}-{machine}"
elifosname[:5] =="sunos":
ifrelease[0] >="5": # SunOS 5 == Solaris 2
osname="solaris"
release=f"{int(release[0]) -3}.{release[2:]}"
# We can't use "platform.architecture()[0]" because a
# bootstrap problem. We use a dict to get an error
# if some suspicious happens.
bitness= {2147483647:"32bit", 9223372036854775807:"64bit"}
machine+=f".{bitness[sys.maxsize]}"
# fall through to standard osname-release-machine representation
elifosname[:3] =="aix":
from_aix_supportimportaix_platform
returnaix_platform()
elifosname[:6] =="cygwin":
osname="cygwin"
importre
rel_re=re.compile(r'[\d.]+')
m=rel_re.match(release)
ifm:
release=m.group()
elifosname[:6] =="darwin":
ifsys.platform=="ios":
release=get_config_vars().get("IPHONEOS_DEPLOYMENT_TARGET", "13.0")
osname=sys.platform
machine=sys.implementation._multiarch
else:
import_osx_support
osname, release, machine=_osx_support.get_platform_osx(
get_config_vars(),
osname, release, machine)
returnf"{osname}-{release}-{machine}"
defget_python_version():
return_PY_VERSION_SHORT
def_get_python_version_abi():
return_PY_VERSION_SHORT+get_config_var("abi_thread")
defexpand_makefile_vars(s, vars):
"""Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
'string' according to 'vars' (a dictionary mapping variable names to
values). Variables not present in 'vars' are silently expanded to the
empty string. The variable values in 'vars' should not contain further
variable expansions; if 'vars' is the output of 'parse_makefile()',
you're fine. Returns a variable-expanded version of 's'.
"""
importre
_findvar1_rx=r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
_findvar2_rx=r"\${([A-Za-z][A-Za-z0-9_]*)}"
# This algorithm does multiple expansion, so if vars['foo'] contains
# "${bar}", it will expand ${foo} to ${bar}, and then expand
# ${bar}... and so forth. This is fine as long as 'vars' comes from
# 'parse_makefile()', which takes care of such expansions eagerly,
# according to make's variable expansion semantics.
whileTrue:
m=re.search(_findvar1_rx, s) orre.search(_findvar2_rx, s)
ifm:
(beg, end) =m.span()
s=s[0:beg] +vars.get(m.group(1)) +s[end:]
else:
break
returns