https://github.com/python/cpython/commit/70154855cf698560dd9a5e484a649839cd68dc7c
commit: 70154855cf698560dd9a5e484a649839cd68dc7c
branch: main
author: Filipe Laíns 🇵🇸 <[email protected]>
committer: FFY00 <[email protected]>
date: 2024-12-08T05:57:22Z
summary:

GH-126789: fix some sysconfig data on late site initializations (#127729)

files:
A Misc/NEWS.d/next/Library/2024-12-07-23-06-44.gh-issue-126789.4dqfV1.rst
M Lib/sysconfig/__init__.py
M Lib/test/test_sysconfig.py

diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index ad86609016e478..ed7b6a335d01d4 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -173,9 +173,7 @@ def joinuser(*args):
 _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]}'
-_PREFIX = os.path.normpath(sys.prefix)
 _BASE_PREFIX = os.path.normpath(sys.base_prefix)
-_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
 _BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
 # Mutex guarding initialization of _CONFIG_VARS.
 _CONFIG_VARS_LOCK = threading.RLock()
@@ -473,8 +471,8 @@ def _init_config_vars():
     global _CONFIG_VARS
     _CONFIG_VARS = {}
 
-    prefix = _PREFIX
-    exec_prefix = _EXEC_PREFIX
+    prefix = os.path.normpath(sys.prefix)
+    exec_prefix = os.path.normpath(sys.exec_prefix)
     base_prefix = _BASE_PREFIX
     base_exec_prefix = _BASE_EXEC_PREFIX
 
@@ -564,9 +562,19 @@ def get_config_vars(*args):
     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.
-    if not _CONFIG_VARS_INITIALIZED:
+    if _CONFIG_VARS_INITIALIZED:
+        # GH-126789: If sys.prefix or sys.exec_prefix were updated, invalidate 
the cache.
+        prefix = os.path.normpath(sys.prefix)
+        exec_prefix = os.path.normpath(sys.exec_prefix)
+        if _CONFIG_VARS['prefix'] != prefix or _CONFIG_VARS['exec_prefix'] != 
exec_prefix:
+            with _CONFIG_VARS_LOCK:
+                _CONFIG_VARS_INITIALIZED = False
+                _init_config_vars()
+    else:
+        # Initialize the config_vars cache.
         with _CONFIG_VARS_LOCK:
             # Test again with the lock held to avoid races. Note that
             # we test _CONFIG_VARS here, not _CONFIG_VARS_INITIALIZED,
diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
index 0df1a67ea2b720..ce504dc21af85f 100644
--- a/Lib/test/test_sysconfig.py
+++ b/Lib/test/test_sysconfig.py
@@ -53,6 +53,8 @@ def setUp(self):
         os.uname = self._get_uname
         # saving the environment
         self.name = os.name
+        self.prefix = sys.prefix
+        self.exec_prefix = sys.exec_prefix
         self.platform = sys.platform
         self.version = sys.version
         self._framework = sys._framework
@@ -77,6 +79,8 @@ def tearDown(self):
         else:
             del os.uname
         os.name = self.name
+        sys.prefix = self.prefix
+        sys.exec_prefix = self.exec_prefix
         sys.platform = self.platform
         sys.version = self.version
         sys._framework = self._framework
@@ -653,6 +657,27 @@ def test_sysconfigdata_json(self):
 
         self.assertEqual(system_config_vars, json_config_vars)
 
+    def test_sysconfig_config_vars_no_prefix_cache(self):
+        sys.prefix = 'prefix-AAA'
+        sys.exec_prefix = 'exec-prefix-AAA'
+
+        config_vars = sysconfig.get_config_vars()
+
+        self.assertEqual(config_vars['prefix'], sys.prefix)
+        self.assertEqual(config_vars['base'], sys.prefix)
+        self.assertEqual(config_vars['exec_prefix'], sys.exec_prefix)
+        self.assertEqual(config_vars['platbase'], sys.exec_prefix)
+
+        sys.prefix = 'prefix-BBB'
+        sys.exec_prefix = 'exec-prefix-BBB'
+
+        config_vars = sysconfig.get_config_vars()
+
+        self.assertEqual(config_vars['prefix'], sys.prefix)
+        self.assertEqual(config_vars['base'], sys.prefix)
+        self.assertEqual(config_vars['exec_prefix'], sys.exec_prefix)
+        self.assertEqual(config_vars['platbase'], sys.exec_prefix)
+
 
 class MakefileTests(unittest.TestCase):
 
diff --git 
a/Misc/NEWS.d/next/Library/2024-12-07-23-06-44.gh-issue-126789.4dqfV1.rst 
b/Misc/NEWS.d/next/Library/2024-12-07-23-06-44.gh-issue-126789.4dqfV1.rst
new file mode 100644
index 00000000000000..417e9ac986f27a
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-12-07-23-06-44.gh-issue-126789.4dqfV1.rst
@@ -0,0 +1,5 @@
+Fixed :func:`sysconfig.get_config_vars`, :func:`sysconfig.get_paths`, and
+siblings, returning outdated cached data if the value  of :data:`sys.prefix`
+or :data:`sys.exec_prefix` changes. Overwriting :data:`sys.prefix` or
+:data:`sys.exec_prefix` still is discouraged, as that might break other
+parts of the code.

_______________________________________________
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]

Reply via email to