Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fbfb02a

Browse files
committed
gh-120057: Add os.environ.refresh() method
1 parent 983efcf commit fbfb02a

7 files changed

Lines changed: 87 additions & 4 deletions

File tree

Doc/library/os.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ process and user.
193193
to the environment made after this time are not reflected in :data:`os.environ`,
194194
except for changes made by modifying :data:`os.environ` directly.
195195

196+
The :meth:`os.environ.refresh() <os.environ>` method updates
197+
:data:`os.environ` with changes to the environment made outside Python.
198+
196199
This mapping may be used to modify the environment as well as query the
197200
environment. :func:`putenv` will be called automatically when the mapping
198201
is modified.
@@ -222,6 +225,9 @@ process and user.
222225
:data:`os.environ`, and when one of the :meth:`pop` or :meth:`clear` methods is
223226
called.
224227

228+
.. versionchanged:: 3.14
229+
Added the :meth:`!os.environ.refresh()` method.
230+
225231
.. versionchanged:: 3.9
226232
Updated to support :pep:`584`'s merge (``|``) and update (``|=``) operators.
227233

Doc/whatsnew/3.14.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ ast
9292
Added :func:`ast.compare` for comparing two ASTs.
9393
(Contributed by Batuhan Taskaya and Jeremy Hylton in :issue:`15987`.)
9494

95+
os
96+
--
97+
98+
* Added the :meth:`os.environ.refresh() <os.environ>` method to update
99+
:data:`os.environ` with environment changes made outside Python.
100+
(Contributed by Victor Stinner in :gh:`120057`.)
95101

96102

97103
Optimizations

Lib/os.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ def _get_exports_list(module):
6464
from posix import _have_functions
6565
except ImportError:
6666
pass
67+
try:
68+
from posix import _create_environ
69+
except ImportError:
70+
pass
6771

6872
import posix
6973
__all__.extend(_get_exports_list(posix))
@@ -88,6 +92,10 @@ def _get_exports_list(module):
8892
from nt import _have_functions
8993
except ImportError:
9094
pass
95+
try:
96+
from nt import _create_environ
97+
except ImportError:
98+
pass
9199

92100
else:
93101
raise ImportError('no os specific module found')
@@ -773,7 +781,18 @@ def __ror__(self, other):
773781
new.update(self)
774782
return new
775783

776-
def _createenviron():
784+
if _exists("_create_environ"):
785+
def refresh(self):
786+
environ = _create_environ()
787+
if name == 'nt':
788+
data = {}
789+
for key, value in environ.items():
790+
data[encodekey(key)] = value
791+
else:
792+
data = environ
793+
self._data = data
794+
795+
def _create_environ_mapping():
777796
if name == 'nt':
778797
# Where Env Var Names Must Be UPPERCASE
779798
def check_str(value):
@@ -803,8 +822,8 @@ def decode(value):
803822
encode, decode)
804823

805824
# unicode environ
806-
environ = _createenviron()
807-
del _createenviron
825+
environ = _create_environ_mapping()
826+
del _create_environ_mapping
808827

809828

810829
def getenv(key, default=None):

Lib/test/test_os.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,22 @@ def test_ror_operator(self):
12981298
self._test_underlying_process_env('_A_', '')
12991299
self._test_underlying_process_env(overridden_key, original_value)
13001300

1301+
@unittest.skipUnless(hasattr(os.environ, 'refresh'),
1302+
'need os.environ.refresh()')
1303+
def test_refresh(self):
1304+
# Use putenv() which doesn't update os.environ
1305+
try:
1306+
from posix import putenv
1307+
except ImportError:
1308+
from nt import putenv
1309+
1310+
os.environ['test_env'] = 'python_value'
1311+
putenv("test_env", "new_value")
1312+
self.assertEqual(os.environ['test_env'], 'python_value')
1313+
1314+
os.environ.refresh()
1315+
self.assertEqual(os.environ['test_env'], 'new_value')
1316+
13011317

13021318
class WalkTests(unittest.TestCase):
13031319
"""Tests for os.walk()."""
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added the :meth:`os.environ.refresh() <os.environ>` method to update
2+
:data:`os.environ` with environment changes made outside Python. Patch by
3+
Victor Stinner.

Modules/clinic/posixmodule.c.h

Lines changed: 19 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/posixmodule.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16816,6 +16816,20 @@ os__is_inputhook_installed_impl(PyObject *module)
1681616816
return PyBool_FromLong(PyOS_InputHook != NULL);
1681716817
}
1681816818

16819+
/*[clinic input]
16820+
os._create_environ
16821+
16822+
Create the environment dictionary.
16823+
[clinic start generated code]*/
16824+
16825+
static PyObject *
16826+
os__create_environ_impl(PyObject *module)
16827+
/*[clinic end generated code: output=19d9039ab14f8ad4 input=a4c05686b34635e8]*/
16828+
{
16829+
return convertenviron();
16830+
}
16831+
16832+
1681916833
static PyMethodDef posix_methods[] = {
1682016834

1682116835
OS_STAT_METHODDEF
@@ -17030,6 +17044,7 @@ static PyMethodDef posix_methods[] = {
1703017044
OS__SUPPORTS_VIRTUAL_TERMINAL_METHODDEF
1703117045
OS__INPUTHOOK_METHODDEF
1703217046
OS__IS_INPUTHOOK_INSTALLED_METHODDEF
17047+
OS__CREATE_ENVIRON_METHODDEF
1703317048
{NULL, NULL} /* Sentinel */
1703417049
};
1703517050

0 commit comments

Comments
 (0)