mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	[3.13] gh-131277: allow EnvironmentVarGuard to unset more than one environment variable at once (GH-131280) (#131409)
(cherry picked from commit 3185e3115c)
---------
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
			
			
This commit is contained in:
		
							parent
							
								
									25ae2045a8
								
							
						
					
					
						commit
						85c20374c0
					
				
					 10 changed files with 27 additions and 36 deletions
				
			
		| 
						 | 
				
			
			@ -2707,8 +2707,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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -693,9 +693,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
 | 
			
		||||
| 
						 | 
				
			
			@ -729,8 +730,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 environment variables."""
 | 
			
		||||
        for ev in (envvar, *envvars):
 | 
			
		||||
            del self[ev]
 | 
			
		||||
 | 
			
		||||
    def copy(self):
 | 
			
		||||
        # We do what os.environ.copy() does.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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',
 | 
			
		||||
 | 
			
		||||
        self.env.unset(
 | 
			
		||||
            '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)
 | 
			
		||||
            '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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,6 @@
 | 
			
		|||
class GetoptTests(unittest.TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.env = self.enterContext(EnvironmentVarGuard())
 | 
			
		||||
        if "POSIXLY_CORRECT" in self.env:
 | 
			
		||||
        del self.env["POSIXLY_CORRECT"]
 | 
			
		||||
 | 
			
		||||
    def assertError(self, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1391,7 +1391,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')
 | 
			
		||||
| 
						 | 
				
			
			@ -1504,10 +1504,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
 | 
			
		||||
| 
						 | 
				
			
			@ -1545,8 +1542,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()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -336,7 +336,6 @@ 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']
 | 
			
		||||
                    environ['PROCESSOR_ARCHITECTURE'] = 'foo'
 | 
			
		||||
                    platform._uname_cache = None
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -419,7 +419,6 @@ 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']
 | 
			
		||||
 | 
			
		||||
            regrtest = main.Regrtest(ns)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2465,7 +2465,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, \
 | 
			
		||||
| 
						 | 
				
			
			@ -2491,7 +2491,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)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3424,8 +3424,7 @@ 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)
 | 
			
		||||
| 
						 | 
				
			
			@ -3433,8 +3432,7 @@ def test_stty_match(self):
 | 
			
		|||
    @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):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue