Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Doc/library/test.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1435,9 +1435,12 @@ The :mod:`test.support.os_helper` module provides support for os tests.
``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()
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2855,8 +2855,7 @@ def no_color():
swap_attr(_colorize, "can_colorize", lambda file=None: False),
EnvironmentVarGuard() as env,
):
for var in {"FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS"}:
env.unset(var)
env.unset("FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS")
env.set("NO_COLOR", "1")
yield

Expand Down
11 changes: 7 additions & 4 deletions Lib/test/support/os_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -720,9 +720,10 @@ def temp_umask(umask):


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
a context manager."""
Can be used as a context manager.
"""

def __init__(self):
self._environ = os.environ
Expand Down Expand Up @@ -756,8 +757,10 @@ def __len__(self):
def set(self, envvar, value):
self[envvar] = value

def unset(self, envvar):
del self[envvar]
def unset(self, envvar, /, *envvars):
"""Unset one or more known environment variables."""
for ev in (envvar, *envvars):
del self[ev]

def copy(self):
# We do what os.environ.copy() does.
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test__colorize.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
@contextlib.contextmanager
def clear_env():
with EnvironmentVarGuard() as mock_env:
for var in "FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS", "TERM":
mock_env.unset(var)
mock_env.unset("FORCE_COLOR", "NO_COLOR", "PYTHON_COLORS", "TERM")
yield mock_env


Expand Down
13 changes: 7 additions & 6 deletions Lib/test/test__osx_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ def setUp(self):
self.prog_name = 'bogus_program_xxxx'
self.temp_path_dir = os.path.abspath(os.getcwd())
self.env = self.enterContext(os_helper.EnvironmentVarGuard())
for cv in ('CFLAGS', 'LDFLAGS', 'CPPFLAGS',
'BASECFLAGS', 'BLDSHARED', 'LDSHARED', 'CC',
'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS',
'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS'):
if cv in self.env:
self.env.unset(cv)

self.env.unset(
'CFLAGS', 'LDFLAGS', 'CPPFLAGS',
'BASECFLAGS', 'BLDSHARED', 'LDSHARED', 'CC',
'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS',
'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS'
)

def add_expected_saved_initial_values(self, config_vars, expected_vars):
# Ensure that the initial values for all modified config vars
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1568,8 +1568,7 @@ def test_open_default_encoding(self):
# try to get a user preferred encoding different than the current
# locale encoding to check that open() uses the current locale
# encoding and not the user preferred encoding
for key in ('LC_ALL', 'LANG', 'LC_CTYPE'):
env.unset(key)
env.unset('LC_ALL', 'LANG', 'LC_CTYPE')

self.write_testfile()
current_locale_encoding = locale.getencoding()
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_getopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
class GetoptTests(unittest.TestCase):
def setUp(self):
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):
self.assertRaises(getopt.GetoptError, *args, **kwargs)
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -2896,8 +2896,7 @@ def test_default_encoding(self):
# try to get a user preferred encoding different than the current
# locale encoding to check that TextIOWrapper() uses the current
# locale encoding and not the user preferred encoding
for key in ('LC_ALL', 'LANG', 'LC_CTYPE'):
env.unset(key)
env.unset('LC_ALL', 'LANG', 'LC_CTYPE')

current_locale_encoding = locale.getencoding()
b = self.BytesIO()
Expand Down
4 changes: 1 addition & 3 deletions Lib/test/test_locale.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,9 +500,7 @@ def test_defaults_UTF8(self):

try:
with os_helper.EnvironmentVarGuard() as env:
for key in ('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE'):
env.unset(key)

env.unset('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')
env.set('LC_CTYPE', 'UTF-8')

with check_warnings(('', DeprecationWarning)):
Expand Down
10 changes: 3 additions & 7 deletions Lib/test/test_pathlib/test_pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -3232,7 +3232,7 @@ def test_expanduser_posix(self):
p7 = P(f'~{fakename}/Documents')

with os_helper.EnvironmentVarGuard() as env:
env.pop('HOME', None)
env.unset('HOME')

self.assertEqual(p1.expanduser(), P(userhome) / 'Documents')
self.assertEqual(p2.expanduser(), P(userhome) / 'Documents')
Expand Down Expand Up @@ -3345,10 +3345,7 @@ def test_absolute_windows(self):
def test_expanduser_windows(self):
P = self.cls
with os_helper.EnvironmentVarGuard() as env:
env.pop('HOME', None)
env.pop('USERPROFILE', None)
env.pop('HOMEPATH', None)
env.pop('HOMEDRIVE', None)
env.unset('HOME', 'USERPROFILE', 'HOMEPATH', 'HOMEDRIVE')
env['USERNAME'] = 'alice'

# test that the path returns unchanged
Expand Down Expand Up @@ -3386,8 +3383,7 @@ def check():
env['HOMEPATH'] = 'Users\\alice'
check()

env.pop('HOMEDRIVE', None)
env.pop('HOMEPATH', None)
env.unset('HOMEDRIVE', 'HOMEPATH')
env['USERPROFILE'] = 'C:\\Users\\alice'
check()

Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,7 @@ def raises_oserror(*a):
with support.swap_attr(platform, '_wmi_query', raises_oserror):
with os_helper.EnvironmentVarGuard() as environ:
try:
if 'PROCESSOR_ARCHITEW6432' in environ:
del environ['PROCESSOR_ARCHITEW6432']
del environ['PROCESSOR_ARCHITEW6432']
environ['PROCESSOR_ARCHITECTURE'] = 'foo'
platform._uname_cache = None
system, node, release, version, machine, processor = platform.uname()
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_regrtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,7 @@ def create_regrtest(self, args):
# which has an unclear API
with os_helper.EnvironmentVarGuard() as env:
# 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)

Expand Down
10 changes: 4 additions & 6 deletions Lib/test/test_shutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -2458,7 +2458,7 @@ def test_environ_path_cwd(self):

def test_environ_path_missing(self):
with os_helper.EnvironmentVarGuard() as env:
env.pop('PATH', None)
del env['PATH']

# without confstr
with unittest.mock.patch('os.confstr', side_effect=ValueError, \
Expand All @@ -2484,7 +2484,7 @@ def test_empty_path(self):

def test_empty_path_no_PATH(self):
with os_helper.EnvironmentVarGuard() as env:
env.pop('PATH', None)
del env['PATH']
rv = shutil.which(self.file)
self.assertIsNone(rv)

Expand Down Expand Up @@ -3446,17 +3446,15 @@ def test_stty_match(self):
expected = (int(size[1]), int(size[0])) # reversed order

with os_helper.EnvironmentVarGuard() as env:
del env['LINES']
del env['COLUMNS']
env.unset('LINES', 'COLUMNS')
actual = shutil.get_terminal_size()

self.assertEqual(expected, actual)

@unittest.skipIf(support.is_wasi, "WASI has no /dev/null")
def test_fallback(self):
with os_helper.EnvironmentVarGuard() as env:
del env['LINES']
del env['COLUMNS']
env.unset('LINES', 'COLUMNS')

# sys.__stdout__ has no fileno()
with support.swap_attr(sys, '__stdout__', None):
Expand Down
4 changes: 1 addition & 3 deletions Lib/test/test_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,7 @@ def test_no_home_directory(self):

with EnvironmentVarGuard() as environ, \
mock.patch('os.path.expanduser', lambda path: path):

del environ['PYTHONUSERBASE']
del environ['APPDATA']
environ.unset('PYTHONUSERBASE', 'APPDATA')

user_base = site.getuserbase()
self.assertTrue(user_base.startswith('~' + os.sep),
Expand Down
Original file line number Diff line number Diff line change
@@ -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