Coverage for .nox/test-3-9/lib/python3.9/site-packages/nskit/common/contextmanagers/env.py: 91%
35 statements
« prev ^ index » next coverage.py v7.4.2, created at 2024-02-25 17:38 +0000
« prev ^ index » next coverage.py v7.4.2, created at 2024-02-25 17:38 +0000
1"""Context manager for running in a specific directory."""
2from contextlib import ContextDecorator
3import os
4from typing import Dict, List, Optional
6from nskit._logging import logger_factory
9class Env(ContextDecorator):
10 """Context manager for managing environment variables.
12 The optional arguments can provide either an exhaustive set of environment values, values to override or values to remove.
13 """
15 def __init__(
16 self,
17 environ: Optional[Dict[str, str]] = None,
18 override: Optional[Dict[str, str]] = None,
19 remove: Optional[List[str]] = None
20 ):
21 """Initialise the context manager.
23 The parameters are applied in the following order (so can be combined): 1st - environ, 2nd - override, 3rd - remove
25 Keyword Args:
26 environ (Optional[Dict[str, str]]): an exhaustive set of environment values to set (replaces overall os.environ contents)
27 override (Optional[Dict[str, str]]): a set of environment values to either override or set (replaces values in existing os.environ)
28 remove (Optional[List[str]]): a set of environment values to remove (removes values if found in os.environ )
29 """
30 if environ is not None and not isinstance(environ, dict):
31 raise TypeError('environ should be a dict')
32 if override is not None and not isinstance(override, dict):
33 raise TypeError('override should be a dict')
34 if remove is not None and not isinstance(remove, (list, tuple, set)):
35 raise TypeError('remove should be a (list, tuple, set)')
36 self._environ = environ
37 self._override = override
38 self._remove = remove
39 self._original = None
41 def __enter__(self):
42 """Change to the target environment variables."""
43 # Handling circular imports with LoggingConfig
44 logger = logger_factory.get_logger(__name__)
45 if self._environ or self._override or self._remove:
46 self._original = os.environ.copy()
47 if self._environ is not None:
48 # Here we pop all keys from it and then update
49 os.environ.clear()
50 os.environ.update(self._environ)
51 if self._override:
52 os.environ.update(self._override)
53 if self._remove:
54 for key in list(self._remove):
55 os.environ.pop(key, None)
56 logger.info('Changing env variables')
57 logger.debug(f'New env variables: {os.environ}')
58 else:
59 logger.info('No arguments set (environ, override, remove)')
61 def __exit__(self, *args, **kwargs): # noqa: U100
62 """Reset to the original environment variables."""
63 if self._original:
64 os.environ.clear()
65 os.environ.update(self._original.copy())