gh-131277: allow EnvironmentVarGuard
to unset more than one environment variable at once (#131280)
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
parent
9558d22ac3
commit
3185e3115c
@ -1435,9 +1435,12 @@ The :mod:`test.support.os_helper` module provides support for os tests.
|
|||||||
``value``.
|
``value``.
|
||||||
|
|
||||||
|
|
||||||
.. method:: EnvironmentVarGuard.unset(envvar)
|
.. method:: EnvironmentVarGuard.unset(envvar, *others)
|
||||||
|
|
||||||
Temporarily unset the environment variable ``envvar``.
|
Temporarily unset one or more environment variables.
|
||||||
|
|
||||||
|
.. versionchanged:: next
|
||||||
|
More than one environment variable can be unset.
|
||||||
|
|
||||||
|
|
||||||
.. function:: can_symlink()
|
.. function:: can_symlink()
|
||||||
|
@ -2855,8 +2855,7 @@ def no_color():
|
|||||||
swap_attr(_colorize, "can_colorize", lambda file=None: False),
|
swap_attr(_colorize, "can_colorize", lambda file=None: False),
|
||||||
EnvironmentVarGuard() as env,
|
EnvironmentVarGuard() as env,
|
||||||
):
|
):
|
||||||
for var in {"FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS"}:
|
env.unset("FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS")
|
||||||
env.unset(var)
|
|
||||||
env.set("NO_COLOR", "1")
|
env.set("NO_COLOR", "1")
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
@ -720,9 +720,10 @@ else:
|
|||||||
|
|
||||||
|
|
||||||
class EnvironmentVarGuard(collections.abc.MutableMapping):
|
class EnvironmentVarGuard(collections.abc.MutableMapping):
|
||||||
|
"""Class to help protect the environment variable properly.
|
||||||
|
|
||||||
"""Class to help protect the environment variable properly. Can be used as
|
Can be used as a context manager.
|
||||||
a context manager."""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._environ = os.environ
|
self._environ = os.environ
|
||||||
@ -756,8 +757,10 @@ class EnvironmentVarGuard(collections.abc.MutableMapping):
|
|||||||
def set(self, envvar, value):
|
def set(self, envvar, value):
|
||||||
self[envvar] = value
|
self[envvar] = value
|
||||||
|
|
||||||
def unset(self, envvar):
|
def unset(self, envvar, /, *envvars):
|
||||||
del self[envvar]
|
"""Unset one or more environment variables."""
|
||||||
|
for ev in (envvar, *envvars):
|
||||||
|
del self[ev]
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
# We do what os.environ.copy() does.
|
# We do what os.environ.copy() does.
|
||||||
|
@ -10,8 +10,7 @@ from test.support.os_helper import EnvironmentVarGuard
|
|||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def clear_env():
|
def clear_env():
|
||||||
with EnvironmentVarGuard() as mock_env:
|
with EnvironmentVarGuard() as mock_env:
|
||||||
for var in "FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS", "TERM":
|
mock_env.unset("FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS", "TERM")
|
||||||
mock_env.unset(var)
|
|
||||||
yield mock_env
|
yield mock_env
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,12 +20,13 @@ class Test_OSXSupport(unittest.TestCase):
|
|||||||
self.prog_name = 'bogus_program_xxxx'
|
self.prog_name = 'bogus_program_xxxx'
|
||||||
self.temp_path_dir = os.path.abspath(os.getcwd())
|
self.temp_path_dir = os.path.abspath(os.getcwd())
|
||||||
self.env = self.enterContext(os_helper.EnvironmentVarGuard())
|
self.env = self.enterContext(os_helper.EnvironmentVarGuard())
|
||||||
for cv in ('CFLAGS', 'LDFLAGS', 'CPPFLAGS',
|
|
||||||
|
self.env.unset(
|
||||||
|
'CFLAGS', 'LDFLAGS', 'CPPFLAGS',
|
||||||
'BASECFLAGS', 'BLDSHARED', 'LDSHARED', 'CC',
|
'BASECFLAGS', 'BLDSHARED', 'LDSHARED', 'CC',
|
||||||
'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS',
|
'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS',
|
||||||
'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS'):
|
'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS'
|
||||||
if cv in self.env:
|
)
|
||||||
self.env.unset(cv)
|
|
||||||
|
|
||||||
def add_expected_saved_initial_values(self, config_vars, expected_vars):
|
def add_expected_saved_initial_values(self, config_vars, expected_vars):
|
||||||
# Ensure that the initial values for all modified config vars
|
# Ensure that the initial values for all modified config vars
|
||||||
|
@ -1568,8 +1568,7 @@ class BuiltinTest(ComplexesAreIdenticalMixin, unittest.TestCase):
|
|||||||
# try to get a user preferred encoding different than the current
|
# try to get a user preferred encoding different than the current
|
||||||
# locale encoding to check that open() uses the current locale
|
# locale encoding to check that open() uses the current locale
|
||||||
# encoding and not the user preferred encoding
|
# encoding and not the user preferred encoding
|
||||||
for key in ('LC_ALL', 'LANG', 'LC_CTYPE'):
|
env.unset('LC_ALL', 'LANG', 'LC_CTYPE')
|
||||||
env.unset(key)
|
|
||||||
|
|
||||||
self.write_testfile()
|
self.write_testfile()
|
||||||
current_locale_encoding = locale.getencoding()
|
current_locale_encoding = locale.getencoding()
|
||||||
|
@ -13,7 +13,6 @@ sentinel = object()
|
|||||||
class GetoptTests(unittest.TestCase):
|
class GetoptTests(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.env = self.enterContext(EnvironmentVarGuard())
|
self.env = self.enterContext(EnvironmentVarGuard())
|
||||||
if "POSIXLY_CORRECT" in self.env:
|
|
||||||
del self.env["POSIXLY_CORRECT"]
|
del self.env["POSIXLY_CORRECT"]
|
||||||
|
|
||||||
def assertError(self, *args, **kwargs):
|
def assertError(self, *args, **kwargs):
|
||||||
|
@ -2896,8 +2896,7 @@ class TextIOWrapperTest(unittest.TestCase):
|
|||||||
# try to get a user preferred encoding different than the current
|
# try to get a user preferred encoding different than the current
|
||||||
# locale encoding to check that TextIOWrapper() uses the current
|
# locale encoding to check that TextIOWrapper() uses the current
|
||||||
# locale encoding and not the user preferred encoding
|
# locale encoding and not the user preferred encoding
|
||||||
for key in ('LC_ALL', 'LANG', 'LC_CTYPE'):
|
env.unset('LC_ALL', 'LANG', 'LC_CTYPE')
|
||||||
env.unset(key)
|
|
||||||
|
|
||||||
current_locale_encoding = locale.getencoding()
|
current_locale_encoding = locale.getencoding()
|
||||||
b = self.BytesIO()
|
b = self.BytesIO()
|
||||||
|
@ -500,9 +500,7 @@ class TestMiscellaneous(unittest.TestCase):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
with os_helper.EnvironmentVarGuard() as env:
|
with os_helper.EnvironmentVarGuard() as env:
|
||||||
for key in ('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE'):
|
env.unset('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')
|
||||||
env.unset(key)
|
|
||||||
|
|
||||||
env.set('LC_CTYPE', 'UTF-8')
|
env.set('LC_CTYPE', 'UTF-8')
|
||||||
|
|
||||||
with check_warnings(('', DeprecationWarning)):
|
with check_warnings(('', DeprecationWarning)):
|
||||||
|
@ -3232,7 +3232,7 @@ class PathTest(PurePathTest):
|
|||||||
p7 = P(f'~{fakename}/Documents')
|
p7 = P(f'~{fakename}/Documents')
|
||||||
|
|
||||||
with os_helper.EnvironmentVarGuard() as env:
|
with os_helper.EnvironmentVarGuard() as env:
|
||||||
env.pop('HOME', None)
|
env.unset('HOME')
|
||||||
|
|
||||||
self.assertEqual(p1.expanduser(), P(userhome) / 'Documents')
|
self.assertEqual(p1.expanduser(), P(userhome) / 'Documents')
|
||||||
self.assertEqual(p2.expanduser(), P(userhome) / 'Documents')
|
self.assertEqual(p2.expanduser(), P(userhome) / 'Documents')
|
||||||
@ -3345,10 +3345,7 @@ class PathTest(PurePathTest):
|
|||||||
def test_expanduser_windows(self):
|
def test_expanduser_windows(self):
|
||||||
P = self.cls
|
P = self.cls
|
||||||
with os_helper.EnvironmentVarGuard() as env:
|
with os_helper.EnvironmentVarGuard() as env:
|
||||||
env.pop('HOME', None)
|
env.unset('HOME', 'USERPROFILE', 'HOMEPATH', 'HOMEDRIVE')
|
||||||
env.pop('USERPROFILE', None)
|
|
||||||
env.pop('HOMEPATH', None)
|
|
||||||
env.pop('HOMEDRIVE', None)
|
|
||||||
env['USERNAME'] = 'alice'
|
env['USERNAME'] = 'alice'
|
||||||
|
|
||||||
# test that the path returns unchanged
|
# test that the path returns unchanged
|
||||||
@ -3386,8 +3383,7 @@ class PathTest(PurePathTest):
|
|||||||
env['HOMEPATH'] = 'Users\\alice'
|
env['HOMEPATH'] = 'Users\\alice'
|
||||||
check()
|
check()
|
||||||
|
|
||||||
env.pop('HOMEDRIVE', None)
|
env.unset('HOMEDRIVE', 'HOMEPATH')
|
||||||
env.pop('HOMEPATH', None)
|
|
||||||
env['USERPROFILE'] = 'C:\\Users\\alice'
|
env['USERPROFILE'] = 'C:\\Users\\alice'
|
||||||
check()
|
check()
|
||||||
|
|
||||||
|
@ -368,7 +368,6 @@ class PlatformTest(unittest.TestCase):
|
|||||||
with support.swap_attr(platform, '_wmi_query', raises_oserror):
|
with support.swap_attr(platform, '_wmi_query', raises_oserror):
|
||||||
with os_helper.EnvironmentVarGuard() as environ:
|
with os_helper.EnvironmentVarGuard() as environ:
|
||||||
try:
|
try:
|
||||||
if 'PROCESSOR_ARCHITEW6432' in environ:
|
|
||||||
del environ['PROCESSOR_ARCHITEW6432']
|
del environ['PROCESSOR_ARCHITEW6432']
|
||||||
environ['PROCESSOR_ARCHITECTURE'] = 'foo'
|
environ['PROCESSOR_ARCHITECTURE'] = 'foo'
|
||||||
platform._uname_cache = None
|
platform._uname_cache = None
|
||||||
|
@ -422,7 +422,6 @@ class ParseArgsTestCase(unittest.TestCase):
|
|||||||
# which has an unclear API
|
# which has an unclear API
|
||||||
with os_helper.EnvironmentVarGuard() as env:
|
with os_helper.EnvironmentVarGuard() as env:
|
||||||
# Ignore SOURCE_DATE_EPOCH env var if it's set
|
# Ignore SOURCE_DATE_EPOCH env var if it's set
|
||||||
if 'SOURCE_DATE_EPOCH' in env:
|
|
||||||
del env['SOURCE_DATE_EPOCH']
|
del env['SOURCE_DATE_EPOCH']
|
||||||
|
|
||||||
regrtest = main.Regrtest(ns)
|
regrtest = main.Regrtest(ns)
|
||||||
|
@ -2458,7 +2458,7 @@ class TestWhich(BaseTest, unittest.TestCase):
|
|||||||
|
|
||||||
def test_environ_path_missing(self):
|
def test_environ_path_missing(self):
|
||||||
with os_helper.EnvironmentVarGuard() as env:
|
with os_helper.EnvironmentVarGuard() as env:
|
||||||
env.pop('PATH', None)
|
del env['PATH']
|
||||||
|
|
||||||
# without confstr
|
# without confstr
|
||||||
with unittest.mock.patch('os.confstr', side_effect=ValueError, \
|
with unittest.mock.patch('os.confstr', side_effect=ValueError, \
|
||||||
@ -2484,7 +2484,7 @@ class TestWhich(BaseTest, unittest.TestCase):
|
|||||||
|
|
||||||
def test_empty_path_no_PATH(self):
|
def test_empty_path_no_PATH(self):
|
||||||
with os_helper.EnvironmentVarGuard() as env:
|
with os_helper.EnvironmentVarGuard() as env:
|
||||||
env.pop('PATH', None)
|
del env['PATH']
|
||||||
rv = shutil.which(self.file)
|
rv = shutil.which(self.file)
|
||||||
self.assertIsNone(rv)
|
self.assertIsNone(rv)
|
||||||
|
|
||||||
@ -3446,8 +3446,7 @@ class TestGetTerminalSize(unittest.TestCase):
|
|||||||
expected = (int(size[1]), int(size[0])) # reversed order
|
expected = (int(size[1]), int(size[0])) # reversed order
|
||||||
|
|
||||||
with os_helper.EnvironmentVarGuard() as env:
|
with os_helper.EnvironmentVarGuard() as env:
|
||||||
del env['LINES']
|
env.unset('LINES', 'COLUMNS')
|
||||||
del env['COLUMNS']
|
|
||||||
actual = shutil.get_terminal_size()
|
actual = shutil.get_terminal_size()
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
@ -3455,8 +3454,7 @@ class TestGetTerminalSize(unittest.TestCase):
|
|||||||
@unittest.skipIf(support.is_wasi, "WASI has no /dev/null")
|
@unittest.skipIf(support.is_wasi, "WASI has no /dev/null")
|
||||||
def test_fallback(self):
|
def test_fallback(self):
|
||||||
with os_helper.EnvironmentVarGuard() as env:
|
with os_helper.EnvironmentVarGuard() as env:
|
||||||
del env['LINES']
|
env.unset('LINES', 'COLUMNS')
|
||||||
del env['COLUMNS']
|
|
||||||
|
|
||||||
# sys.__stdout__ has no fileno()
|
# sys.__stdout__ has no fileno()
|
||||||
with support.swap_attr(sys, '__stdout__', None):
|
with support.swap_attr(sys, '__stdout__', None):
|
||||||
|
@ -355,9 +355,7 @@ class HelperFunctionsTests(unittest.TestCase):
|
|||||||
|
|
||||||
with EnvironmentVarGuard() as environ, \
|
with EnvironmentVarGuard() as environ, \
|
||||||
mock.patch('os.path.expanduser', lambda path: path):
|
mock.patch('os.path.expanduser', lambda path: path):
|
||||||
|
environ.unset('PYTHONUSERBASE', 'APPDATA')
|
||||||
del environ['PYTHONUSERBASE']
|
|
||||||
del environ['APPDATA']
|
|
||||||
|
|
||||||
user_base = site.getuserbase()
|
user_base = site.getuserbase()
|
||||||
self.assertTrue(user_base.startswith('~' + os.sep),
|
self.assertTrue(user_base.startswith('~' + os.sep),
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
Allow to unset one or more environment variables at once via
|
||||||
|
:meth:`EnvironmentVarGuard.unset()
|
||||||
|
<test.support.os_helper.EnvironmentVarGuard.unset>`. Patch by Bénédikt Tran.
|
Loading…
x
Reference in New Issue
Block a user