https://github.com/python/cpython/commit/c931d75831e4176b4876875c01e4b989c8915275
commit: c931d75831e4176b4876875c01e4b989c8915275
branch: main
author: Filipe Laíns 🇵🇸 <[email protected]>
committer: FFY00 <[email protected]>
date: 2025-01-29T22:47:20Z
summary:
GH-127178: improve compatibility in `_sysconfig_vars_(...).json` (#128558)
files:
M Lib/sysconfig/__init__.py
M Lib/sysconfig/__main__.py
M Lib/test/test_sysconfig.py
diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index 3c3c9796ec3307..69f72452c4069a 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -116,8 +116,10 @@ def _getuserbase():
if env_base:
return env_base
- # Emscripten, iOS, tvOS, VxWorks, WASI, and watchOS have no home
directories
- if sys.platform in {"emscripten", "ios", "tvos", "vxworks", "wasi",
"watchos"}:
+ # Emscripten, iOS, tvOS, VxWorks, WASI, and watchOS have no home
directories.
+ # Use _PYTHON_HOST_PLATFORM to get the correct platform when
cross-compiling.
+ system_name = os.environ.get('_PYTHON_HOST_PLATFORM',
sys.platform).split('-')[0]
+ if system_name in {"emscripten", "ios", "tvos", "vxworks", "wasi",
"watchos"}:
return None
def joinuser(*args):
@@ -342,6 +344,18 @@ def get_makefile_filename():
return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
+def _import_from_directory(path, name):
+ if name not in sys.modules:
+ import importlib.machinery
+ import importlib.util
+
+ spec = importlib.machinery.PathFinder.find_spec(name, [path])
+ module = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(module)
+ sys.modules[name] = module
+ return sys.modules[name]
+
+
def _get_sysconfigdata_name():
multiarch = getattr(sys.implementation, '_multiarch', '')
return os.environ.get(
@@ -349,27 +363,34 @@ def _get_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()
+
+def _get_sysconfigdata():
+ import importlib
+
name = _get_sysconfigdata_name()
+ path = os.environ.get('_PYTHON_SYSCONFIGDATA_PATH')
+ module = _import_from_directory(path, name) if path else
importlib.import_module(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')):
- from importlib.machinery import FileFinder, SourceFileLoader,
SOURCE_SUFFIXES
- from importlib.util import module_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
+ return module.build_time_vars
+
+
+def _installation_is_relocated():
+ """Is the Python installation running from a different prefix than what
was targetted when building?"""
+ if os.name != 'posix':
+ raise NotImplementedError('sysconfig._installation_is_relocated() is
currently only supported on POSIX')
+
+ data = _get_sysconfigdata()
+ return (
+ data['prefix'] != getattr(sys, 'base_prefix', '')
+ or data['exec_prefix'] != getattr(sys, 'base_exec_prefix', '')
+ )
+
+
+def _init_posix(vars):
+ """Initialize the module as appropriate for POSIX systems."""
# GH-126920: Make sure we don't overwrite any of the keys already set
- vars.update(build_time_vars | vars)
+ vars.update(_get_sysconfigdata() | vars)
+
def _init_non_posix(vars):
"""Initialize the module as appropriate for NT"""
diff --git a/Lib/sysconfig/__main__.py b/Lib/sysconfig/__main__.py
index 10728c709e1811..bc2197cfe79402 100644
--- a/Lib/sysconfig/__main__.py
+++ b/Lib/sysconfig/__main__.py
@@ -232,10 +232,14 @@ def _generate_posix_vars():
print(f'Written {destfile}')
+ install_vars = get_config_vars()
+ # Fix config vars to match the values after install (of the default
environment)
+ install_vars['projectbase'] = install_vars['BINDIR']
+ install_vars['srcdir'] = install_vars['LIBPL']
# Write a JSON file with the output of sysconfig.get_config_vars
jsonfile = os.path.join(pybuilddir, _get_json_data_name())
with open(jsonfile, 'w') as f:
- json.dump(get_config_vars(), f, indent=2)
+ json.dump(install_vars, f, indent=2)
print(f'Written {jsonfile}')
diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
index 1002d90074599a..3950d8888d4c8c 100644
--- a/Lib/test/test_sysconfig.py
+++ b/Lib/test/test_sysconfig.py
@@ -650,8 +650,21 @@ def test_sysconfigdata_json(self):
system_config_vars = get_config_vars()
- # Ignore keys in the check
- for key in ('projectbase', 'srcdir'):
+ ignore_keys = set()
+ # Keys dependent on Python being run outside the build directrory
+ if sysconfig.is_python_build():
+ ignore_keys |= {'srcdir'}
+ # Keys dependent on the executable location
+ if os.path.dirname(sys.executable) != system_config_vars['BINDIR']:
+ ignore_keys |= {'projectbase'}
+ # Keys dependent on the environment (different inside virtual
environments)
+ if sys.prefix != sys.base_prefix:
+ ignore_keys |= {'prefix', 'exec_prefix', 'base', 'platbase'}
+ # Keys dependent on Python being run from the prefix targetted when
building (different on relocatable installs)
+ if sysconfig._installation_is_relocated():
+ ignore_keys |= {'prefix', 'exec_prefix', 'base', 'platbase',
'installed_base', 'installed_platbase'}
+
+ for key in ignore_keys:
json_config_vars.pop(key)
system_config_vars.pop(key)
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]