aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/sysconfig.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/sysconfig.py')
-rw-r--r--Lib/sysconfig.py50
1 files changed, 40 insertions, 10 deletions
diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py
index d056d2c3381..0e0decd4271 100644
--- a/Lib/sysconfig.py
+++ b/Lib/sysconfig.py
@@ -130,6 +130,12 @@ _BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
_CONFIG_VARS = None
_USER_BASE = None
+# Regexes needed for parsing Makefile (and similar syntaxes,
+# like old-style Setup files).
+_variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)"
+_findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
+_findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}"
+
def _safe_realpath(path):
try:
@@ -215,19 +221,14 @@ def _get_default_scheme():
-def _parse_makefile(filename, vars=None):
+def _parse_makefile(filename, vars=None, keep_unresolved=True):
"""Parse a Makefile-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.
"""
- # Regexes needed for parsing Makefile (and similar syntaxes,
- # like old-style Setup files).
import re
- _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
- _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
- _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
if vars is None:
vars = {}
@@ -241,7 +242,7 @@ def _parse_makefile(filename, vars=None):
for line in lines:
if line.startswith('#') or line.strip() == '':
continue
- m = _variable_rx.match(line)
+ m = re.match(_variable_rx, line)
if m:
n, v = m.group(1, 2)
v = v.strip()
@@ -274,8 +275,8 @@ def _parse_makefile(filename, vars=None):
while len(variables) > 0:
for name in tuple(variables):
value = notdone[name]
- m1 = _findvar1_rx.search(value)
- m2 = _findvar2_rx.search(value)
+ m1 = re.search(_findvar1_rx, value)
+ m2 = re.search(_findvar2_rx, value)
if m1 and m2:
m = m1 if m1.start() < m2.start() else m2
else:
@@ -330,9 +331,12 @@ def _parse_makefile(filename, vars=None):
done[name] = value
else:
+ # Adds unresolved variables to the done dict.
+ # This is disabled when called from distutils.sysconfig
+ if keep_unresolved:
+ done[name] = value
# bogus variable reference (e.g. "prefix=$/opt/python");
# just drop it since we can't deal
- done[name] = value
variables.remove(name)
# strip spurious spaces
@@ -712,6 +716,32 @@ def get_python_version():
return _PY_VERSION_SHORT
+def expand_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'.
+ """
+ import re
+
+ # 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.
+
+ while True:
+ m = re.search(_findvar1_rx, s) or re.search(_findvar2_rx, s)
+ if m:
+ (beg, end) = m.span()
+ s = s[0:beg] + vars.get(m.group(1)) + s[end:]
+ else:
+ break
+ return s
+
+
def _print_dict(title, data):
for index, (key, value) in enumerate(sorted(data.items())):
if index == 0: