Skip to content

Commit 4a53a39

Browse files
authored
GH-103480: make sysconfig a package (GH-110785)
1 parent d2a536b commit 4a53a39

File tree

4 files changed

+250
-229
lines changed

4 files changed

+250
-229
lines changed

Lib/sysconfig.py renamed to Lib/sysconfig/__init__.py

-227
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,6 @@ def joinuser(*args):
180180
_CONFIG_VARS_INITIALIZED = False
181181
_USER_BASE = None
182182

183-
# Regexes needed for parsing Makefile (and similar syntaxes,
184-
# like old-style Setup files).
185-
_variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)"
186-
_findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
187-
_findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}"
188-
189183

190184
def _safe_realpath(path):
191185
try:
@@ -317,134 +311,6 @@ def get_default_scheme():
317311
return get_preferred_scheme('prefix')
318312

319313

320-
def _parse_makefile(filename, vars=None, keep_unresolved=True):
321-
"""Parse a Makefile-style file.
322-
323-
A dictionary containing name/value pairs is returned. If an
324-
optional dictionary is passed in as the second argument, it is
325-
used instead of a new dictionary.
326-
"""
327-
import re
328-
329-
if vars is None:
330-
vars = {}
331-
done = {}
332-
notdone = {}
333-
334-
with open(filename, encoding=sys.getfilesystemencoding(),
335-
errors="surrogateescape") as f:
336-
lines = f.readlines()
337-
338-
for line in lines:
339-
if line.startswith('#') or line.strip() == '':
340-
continue
341-
m = re.match(_variable_rx, line)
342-
if m:
343-
n, v = m.group(1, 2)
344-
v = v.strip()
345-
# `$$' is a literal `$' in make
346-
tmpv = v.replace('$$', '')
347-
348-
if "$" in tmpv:
349-
notdone[n] = v
350-
else:
351-
try:
352-
if n in _ALWAYS_STR:
353-
raise ValueError
354-
355-
v = int(v)
356-
except ValueError:
357-
# insert literal `$'
358-
done[n] = v.replace('$$', '$')
359-
else:
360-
done[n] = v
361-
362-
# do variable interpolation here
363-
variables = list(notdone.keys())
364-
365-
# Variables with a 'PY_' prefix in the makefile. These need to
366-
# be made available without that prefix through sysconfig.
367-
# Special care is needed to ensure that variable expansion works, even
368-
# if the expansion uses the name without a prefix.
369-
renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
370-
371-
while len(variables) > 0:
372-
for name in tuple(variables):
373-
value = notdone[name]
374-
m1 = re.search(_findvar1_rx, value)
375-
m2 = re.search(_findvar2_rx, value)
376-
if m1 and m2:
377-
m = m1 if m1.start() < m2.start() else m2
378-
else:
379-
m = m1 if m1 else m2
380-
if m is not None:
381-
n = m.group(1)
382-
found = True
383-
if n in done:
384-
item = str(done[n])
385-
elif n in notdone:
386-
# get it on a subsequent round
387-
found = False
388-
elif n in os.environ:
389-
# do it like make: fall back to environment
390-
item = os.environ[n]
391-
392-
elif n in renamed_variables:
393-
if (name.startswith('PY_') and
394-
name[3:] in renamed_variables):
395-
item = ""
396-
397-
elif 'PY_' + n in notdone:
398-
found = False
399-
400-
else:
401-
item = str(done['PY_' + n])
402-
403-
else:
404-
done[n] = item = ""
405-
406-
if found:
407-
after = value[m.end():]
408-
value = value[:m.start()] + item + after
409-
if "$" in after:
410-
notdone[name] = value
411-
else:
412-
try:
413-
if name in _ALWAYS_STR:
414-
raise ValueError
415-
value = int(value)
416-
except ValueError:
417-
done[name] = value.strip()
418-
else:
419-
done[name] = value
420-
variables.remove(name)
421-
422-
if name.startswith('PY_') \
423-
and name[3:] in renamed_variables:
424-
425-
name = name[3:]
426-
if name not in done:
427-
done[name] = value
428-
429-
else:
430-
# Adds unresolved variables to the done dict.
431-
# This is disabled when called from distutils.sysconfig
432-
if keep_unresolved:
433-
done[name] = value
434-
# bogus variable reference (e.g. "prefix=$/opt/python");
435-
# just drop it since we can't deal
436-
variables.remove(name)
437-
438-
# strip spurious spaces
439-
for k, v in done.items():
440-
if isinstance(v, str):
441-
done[k] = v.strip()
442-
443-
# save the results in the global dictionary
444-
vars.update(done)
445-
return vars
446-
447-
448314
def get_makefile_filename():
449315
"""Return the path of the Makefile."""
450316
if _PYTHON_BUILD:
@@ -465,74 +331,6 @@ def _get_sysconfigdata_name():
465331
f'_sysconfigdata_{sys.abiflags}_{sys.platform}_{multiarch}',
466332
)
467333

468-
def _print_config_dict(d, stream):
469-
print ("{", file=stream)
470-
for k, v in sorted(d.items()):
471-
print(f" {k!r}: {v!r},", file=stream)
472-
print ("}", file=stream)
473-
474-
def _generate_posix_vars():
475-
"""Generate the Python module containing build-time variables."""
476-
vars = {}
477-
# load the installed Makefile:
478-
makefile = get_makefile_filename()
479-
try:
480-
_parse_makefile(makefile, vars)
481-
except OSError as e:
482-
msg = f"invalid Python installation: unable to open {makefile}"
483-
if hasattr(e, "strerror"):
484-
msg = f"{msg} ({e.strerror})"
485-
raise OSError(msg)
486-
# load the installed pyconfig.h:
487-
config_h = get_config_h_filename()
488-
try:
489-
with open(config_h, encoding="utf-8") as f:
490-
parse_config_h(f, vars)
491-
except OSError as e:
492-
msg = f"invalid Python installation: unable to open {config_h}"
493-
if hasattr(e, "strerror"):
494-
msg = f"{msg} ({e.strerror})"
495-
raise OSError(msg)
496-
# On AIX, there are wrong paths to the linker scripts in the Makefile
497-
# -- these paths are relative to the Python source, but when installed
498-
# the scripts are in another directory.
499-
if _PYTHON_BUILD:
500-
vars['BLDSHARED'] = vars['LDSHARED']
501-
502-
# There's a chicken-and-egg situation on OS X with regards to the
503-
# _sysconfigdata module after the changes introduced by #15298:
504-
# get_config_vars() is called by get_platform() as part of the
505-
# `make pybuilddir.txt` target -- which is a precursor to the
506-
# _sysconfigdata.py module being constructed. Unfortunately,
507-
# get_config_vars() eventually calls _init_posix(), which attempts
508-
# to import _sysconfigdata, which we won't have built yet. In order
509-
# for _init_posix() to work, if we're on Darwin, just mock up the
510-
# _sysconfigdata module manually and populate it with the build vars.
511-
# This is more than sufficient for ensuring the subsequent call to
512-
# get_platform() succeeds.
513-
name = _get_sysconfigdata_name()
514-
if 'darwin' in sys.platform:
515-
import types
516-
module = types.ModuleType(name)
517-
module.build_time_vars = vars
518-
sys.modules[name] = module
519-
520-
pybuilddir = f'build/lib.{get_platform()}-{_PY_VERSION_SHORT}'
521-
if hasattr(sys, "gettotalrefcount"):
522-
pybuilddir += '-pydebug'
523-
os.makedirs(pybuilddir, exist_ok=True)
524-
destfile = os.path.join(pybuilddir, name + '.py')
525-
526-
with open(destfile, 'w', encoding='utf8') as f:
527-
f.write('# system configuration generated and used by'
528-
' the sysconfig module\n')
529-
f.write('build_time_vars = ')
530-
_print_config_dict(vars, stream=f)
531-
532-
# Create file used for sys.path fixup -- see Modules/getpath.c
533-
with open('pybuilddir.txt', 'w', encoding='utf8') as f:
534-
f.write(pybuilddir)
535-
536334
def _init_posix(vars):
537335
"""Initialize the module as appropriate for POSIX systems."""
538336
# _sysconfigdata is generated at build time, see _generate_posix_vars()
@@ -857,28 +655,3 @@ def expand_makefile_vars(s, vars):
857655
else:
858656
break
859657
return s
860-
861-
862-
def _print_dict(title, data):
863-
for index, (key, value) in enumerate(sorted(data.items())):
864-
if index == 0:
865-
print(f'{title}: ')
866-
print(f'\t{key} = "{value}"')
867-
868-
869-
def _main():
870-
"""Display all information sysconfig detains."""
871-
if '--generate-posix-vars' in sys.argv:
872-
_generate_posix_vars()
873-
return
874-
print(f'Platform: "{get_platform()}"')
875-
print(f'Python version: "{get_python_version()}"')
876-
print(f'Current installation scheme: "{get_default_scheme()}"')
877-
print()
878-
_print_dict('Paths', get_paths())
879-
print()
880-
_print_dict('Variables', get_config_vars())
881-
882-
883-
if __name__ == '__main__':
884-
_main()

0 commit comments

Comments
 (0)