Skip to content

Commit

Permalink
pythongh-120057: Add os.environ.refresh() method
Browse files Browse the repository at this point in the history
  • Loading branch information
vstinner committed Jun 4, 2024
1 parent 5a1205b commit 50447f4
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 1 deletion.
6 changes: 6 additions & 0 deletions Doc/library/os.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ 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() <os.environ>` method updates
:data:`os.environ` with changes to the environment made outside Python.

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.
Expand Down Expand Up @@ -222,6 +225,9 @@ process and user.
:data:`os.environ`, and when one of the :meth:`pop` or :meth:`clear` methods is
called.

.. versionchanged:: 3.14
Added the :meth:`!os.environ.refresh()` method.

.. versionchanged:: 3.9
Updated to support :pep:`584`'s merge (``|``) and update (``|=``) operators.

Expand Down
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ ast
Added :func:`ast.compare` for comparing two ASTs.
(Contributed by Batuhan Taskaya and Jeremy Hylton in :issue:`15987`.)

os
--

* Added the :meth:`os.environ.refresh() <os.environ>` method to update
:data:`os.environ` with environment changes made outside Python.
(Contributed by Victor Stinner in :gh:`120057`.)


Optimizations
Expand Down
19 changes: 19 additions & 0 deletions Lib/os.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ def _get_exports_list(module):
from posix import _have_functions
except ImportError:
pass
try:
from posix import _create_environ
except ImportError:
pass

import posix
__all__.extend(_get_exports_list(posix))
Expand All @@ -88,6 +92,10 @@ def _get_exports_list(module):
from nt import _have_functions
except ImportError:
pass
try:
from nt import _create_environ
except ImportError:
pass

else:
raise ImportError('no os specific module found')
Expand Down Expand Up @@ -773,6 +781,17 @@ def __ror__(self, other):
new.update(self)
return new

if _exists("_create_environ"):
def refresh(self):
environ = _create_environ()
if name == 'nt':
data = {}
for key, value in environ.items():
data[encodekey(key)] = value
else:
data = environ
self._data = data

def _createenviron():
if name == 'nt':
# Where Env Var Names Must Be UPPERCASE
Expand Down
17 changes: 17 additions & 0 deletions Lib/test/test_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,23 @@ def test_ror_operator(self):
self._test_underlying_process_env('_A_', '')
self._test_underlying_process_env(overridden_key, original_value)

@unittest.skipUnless(hasattr(os.environ, 'refresh'),
'need os.environ.refresh()')
def test_refresh(self):
# Use putenv() which doesn't update os.environ for the test
try:
from posix import putenv
except ImportError:
from nt import putenv

os.environ['test_env'] = 'python_value'

putenv("test_env", "new_value")
self.assertEqual(os.environ['test_env'], 'python_value')

os.environ.refresh()
self.assertEqual(os.environ['test_env'], 'new_value')


class WalkTests(unittest.TestCase):
"""Tests for os.walk()."""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added the :meth:`os.environ.refresh() <os.environ>` method to update
:data:`os.environ` with environment changes made outside Python. Patch by
Victor Stinner.
20 changes: 19 additions & 1 deletion Modules/clinic/posixmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -16727,6 +16727,20 @@ os__supports_virtual_terminal_impl(PyObject *module)
#endif


/*[clinic input]
os._create_environ
Create the environment dictionary.
[clinic start generated code]*/

static PyObject *
os__create_environ_impl(PyObject *module)
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
{
return convertenviron();
}


static PyMethodDef posix_methods[] = {

OS_STAT_METHODDEF
Expand Down Expand Up @@ -16939,6 +16953,7 @@ static PyMethodDef posix_methods[] = {
OS__PATH_LEXISTS_METHODDEF

OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
OS__CREATE_ENVIRON_METHODDEF
{NULL, NULL} /* Sentinel */
};

Expand Down

0 comments on commit 50447f4

Please sign in to comment.