https://github.com/python/cpython/commit/4a0d574273819b2b5006decb661da05b3baa8a4b
commit: 4a0d574273819b2b5006decb661da05b3baa8a4b
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2024-11-05T08:43:34+01:00
summary:

gh-120057: Add os.reload_environ() function (#126268)

Replace the os.environ.refresh() method with a new
os.reload_environ() function.

Co-authored-by: Bénédikt Tran <[email protected]>
Co-authored-by: Adam Turner <[email protected]>

files:
A Misc/NEWS.d/next/Library/2024-11-01-10-35-49.gh-issue-120057.YWy81Q.rst
M Doc/library/os.rst
M Doc/whatsnew/3.14.rst
M Lib/os.py
M Lib/test/test_os.py

diff --git a/Doc/library/os.rst b/Doc/library/os.rst
index f9cded40c2c755..c0354b2280c45c 100644
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -193,10 +193,6 @@ process and user.
    to the environment made after this time are not reflected in 
:data:`os.environ`,
    except for changes made by modifying :data:`os.environ` directly.
 
-   The :meth:`!os.environ.refresh` method updates :data:`os.environ` with
-   changes to the environment made by :func:`os.putenv`, by
-   :func:`os.unsetenv`, or made outside Python in the same process.
-
    This mapping may be used to modify the environment as well as query the
    environment.  :func:`putenv` will be called automatically when the mapping
    is modified.
@@ -226,12 +222,13 @@ process and user.
    :data:`os.environ`, and when one of the :meth:`pop` or :meth:`clear` 
methods is
    called.
 
+   .. seealso::
+
+      The :func:`os.reload_environ` function.
+
    .. versionchanged:: 3.9
       Updated to support :pep:`584`'s merge (``|``) and update (``|=``) 
operators.
 
-   .. versionchanged:: 3.14
-      Added the :meth:`!os.environ.refresh` method.
-
 
 .. data:: environb
 
@@ -249,6 +246,24 @@ process and user.
       Updated to support :pep:`584`'s merge (``|``) and update (``|=``) 
operators.
 
 
+.. function:: reload_environ()
+
+   The :data:`os.environ` and :data:`os.environb` mappings are a cache of
+   environment variables at the time that Python started.
+   As such, changes to the current process environment are not reflected
+   if made outside Python, or by :func:`os.putenv` or :func:`os.unsetenv`.
+   Use :func:`!os.reload_environ` to update :data:`os.environ` and 
:data:`os.environb`
+   with any such changes to the current process environment.
+
+   .. warning::
+      This function is not thread-safe. Calling it while the environment is
+      being modified in an other thread is an undefined behavior. Reading from
+      :data:`os.environ` or :data:`os.environb`, or calling :func:`os.getenv`
+      while reloading, may return an empty result.
+
+   .. versionadded:: next
+
+
 .. function:: chdir(path)
               fchdir(fd)
               getcwd()
@@ -568,7 +583,7 @@ process and user.
    of :data:`os.environ`. This also applies to :func:`getenv` and 
:func:`getenvb`, which
    respectively use :data:`os.environ` and :data:`os.environb` in their 
implementations.
 
-   See also the :data:`os.environ.refresh() <os.environ>` method.
+   See also the :func:`os.reload_environ` function.
 
    .. note::
 
@@ -818,7 +833,7 @@ process and user.
    don't update :data:`os.environ`, so it is actually preferable to delete 
items of
    :data:`os.environ`.
 
-   See also the :data:`os.environ.refresh() <os.environ>` method.
+   See also the :func:`os.reload_environ` function.
 
    .. audit-event:: os.unsetenv key os.unsetenv
 
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 80c1a93b95a6af..9300de440cdc30 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -365,9 +365,10 @@ operator
 os
 --
 
-* Add the :data:`os.environ.refresh() <os.environ>` method to update
-  :data:`os.environ` with changes to the environment made by :func:`os.putenv`,
-  by :func:`os.unsetenv`, or made outside Python in the same process.
+* Add the :func:`os.reload_environ` function to update :data:`os.environ` and
+  :data:`os.environb` with changes to the environment made by
+  :func:`os.putenv`, by :func:`os.unsetenv`, or made outside Python in the
+  same process.
   (Contributed by Victor Stinner in :gh:`120057`.)
 
 
diff --git a/Lib/os.py b/Lib/os.py
index aaa758d955fe4c..9c2258e6ccf5ba 100644
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -765,17 +765,6 @@ def __ror__(self, other):
         new.update(self)
         return new
 
-    if _exists("_create_environ"):
-        def refresh(self):
-            data = _create_environ()
-            if name == 'nt':
-                data = {self.encodekey(key): value
-                        for key, value in data.items()}
-
-            # modify in-place to keep os.environb in sync
-            self._data.clear()
-            self._data.update(data)
-
 def _create_environ_mapping():
     if name == 'nt':
         # Where Env Var Names Must Be UPPERCASE
@@ -810,6 +799,20 @@ def decode(value):
 del _create_environ_mapping
 
 
+if _exists("_create_environ"):
+    def reload_environ():
+        data = _create_environ()
+        if name == 'nt':
+            encodekey = environ.encodekey
+            data = {encodekey(key): value
+                    for key, value in data.items()}
+
+        # modify in-place to keep os.environb in sync
+        env_data = environ._data
+        env_data.clear()
+        env_data.update(data)
+
+
 def getenv(key, default=None):
     """Get an environment variable, return None if it doesn't exist.
     The optional second argument can specify an alternate default.
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 307f0f11ddc33f..9a4be78556c648 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -1298,8 +1298,8 @@ def test_ror_operator(self):
         self._test_underlying_process_env('_A_', '')
         self._test_underlying_process_env(overridden_key, original_value)
 
-    def test_refresh(self):
-        # Test os.environ.refresh()
+    def test_reload_environ(self):
+        # Test os.reload_environ()
         has_environb = hasattr(os, 'environb')
 
         # Test with putenv() which doesn't update os.environ
@@ -1309,7 +1309,7 @@ def test_refresh(self):
         if has_environb:
             self.assertEqual(os.environb[b'test_env'], b'python_value')
 
-        os.environ.refresh()
+        os.reload_environ()
         self.assertEqual(os.environ['test_env'], 'new_value')
         if has_environb:
             self.assertEqual(os.environb[b'test_env'], b'new_value')
@@ -1320,28 +1320,28 @@ def test_refresh(self):
         if has_environb:
             self.assertEqual(os.environb[b'test_env'], b'new_value')
 
-        os.environ.refresh()
+        os.reload_environ()
         self.assertNotIn('test_env', os.environ)
         if has_environb:
             self.assertNotIn(b'test_env', os.environb)
 
         if has_environb:
-            # test os.environb.refresh() with putenv()
+            # test reload_environ() on os.environb with putenv()
             os.environb[b'test_env'] = b'python_value2'
             os.putenv("test_env", "new_value2")
             self.assertEqual(os.environb[b'test_env'], b'python_value2')
             self.assertEqual(os.environ['test_env'], 'python_value2')
 
-            os.environb.refresh()
+            os.reload_environ()
             self.assertEqual(os.environb[b'test_env'], b'new_value2')
             self.assertEqual(os.environ['test_env'], 'new_value2')
 
-            # test os.environb.refresh() with unsetenv()
+            # test reload_environ() on os.environb with unsetenv()
             os.unsetenv('test_env')
             self.assertEqual(os.environb[b'test_env'], b'new_value2')
             self.assertEqual(os.environ['test_env'], 'new_value2')
 
-            os.environb.refresh()
+            os.reload_environ()
             self.assertNotIn(b'test_env', os.environb)
             self.assertNotIn('test_env', os.environ)
 
diff --git 
a/Misc/NEWS.d/next/Library/2024-11-01-10-35-49.gh-issue-120057.YWy81Q.rst 
b/Misc/NEWS.d/next/Library/2024-11-01-10-35-49.gh-issue-120057.YWy81Q.rst
new file mode 100644
index 00000000000000..ded60a3f57bca3
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-11-01-10-35-49.gh-issue-120057.YWy81Q.rst
@@ -0,0 +1,2 @@
+Replace the ``os.environ.refresh()`` method with a new
+:func:`os.reload_environ` function. Patch by Victor Stinner.

_______________________________________________
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