22#
33# SPDX-License-Identifier: Apache-2.0
44
5+ import contextlib
56import os
67import platform
78import shutil
1314
1415import pytest
1516
16- from west import configuration as config
17-
1817GIT = shutil .which ('git' )
1918
2019# Git capabilities are discovered at runtime in
6261WINDOWS = (platform .system () == 'Windows' )
6362
6463#
65- # Test fixtures
64+ # Contextmanager
65+ #
66+
67+ @contextlib .contextmanager
68+ def update_env (env : dict , append = False , prepend = False , sep = os .pathsep ):
69+ """
70+ Temporarily update the process environment variables.
71+ This context manager updates `os.environ` with the key-value pairs
72+ provided in the `env` dictionary for the duration of the `with` block.
73+ Any existing environment variables are preserved and restored when
74+ the block exits.
75+ If the value is set to None, the environment variable is unset.
76+ The value can also be either appended (append=True) or prepended
77+ (prepend=True) to existing, using the given separator (sep).
78+ """
79+ env_bak = dict (os .environ )
80+ env_vars = {}
81+ for k , v in env .items ():
82+ current_v = os .getenv (k , None )
83+ # unset if value is None
84+ if v is None and k in os .environ :
85+ del os .environ [k ]
86+ # append value to existing value
87+ elif append and current_v is not None :
88+ env_vars [k ] = f'{ current_v } { sep } { v } '
89+ # prepend value to existing value
90+ elif prepend and current_v is not None :
91+ env_vars [k ] = f'{ v } { sep } { current_v } '
92+ # set to value
93+ else :
94+ env_vars [k ] = f'{ v } '
95+ os .environ .update (env_vars )
96+ try :
97+ yield
98+ finally :
99+ os .environ .clear ()
100+ os .environ .update (env_bak )
101+
102+
103+ @contextlib .contextmanager
104+ def chdir (path ):
105+ """
106+ Temporarily change the current working directory.
107+ This context manager changes the current working directory to `path`
108+ for the duration of the `with` block. After the block exits, the
109+ working directory is restored to its original value.
110+ """
111+ oldpwd = os .getcwd ()
112+ os .chdir (path )
113+ try :
114+ yield
115+ finally :
116+ os .chdir (oldpwd )
117+
118+
119+ #
120+ # Test fixtures (autouse=True)
66121#
67122
68123@pytest .fixture (scope = 'session' , autouse = True )
@@ -86,6 +141,36 @@ def _check_git_capabilities(tmpdir_factory):
86141 except subprocess .CalledProcessError :
87142 pass
88143
144+ @pytest .fixture (autouse = True )
145+ def independent_global_and_system_config (tmpdir_factory ):
146+ # Fixture to ensure that the user's actual global and system configuration
147+ # files are neither used nor touched during test.
148+ #
149+ # We also set ZEPHYR_BASE (to avoid complaints in subcommand
150+ # stderr), but to a spurious location (so that attempts to read
151+ # from inside of it are caught here).
152+ #
153+ tmpdir = Path (tmpdir_factory .mktemp ("test-configs" ))
154+
155+ # config paths
156+ system = tmpdir / 'config.system'
157+ glbl = tmpdir / 'config.global'
158+
159+ # run with environment variables set
160+ with update_env (
161+ {
162+ 'WEST_CONFIG_SYSTEM' : str (system ),
163+ 'WEST_CONFIG_GLOBAL' : str (glbl ),
164+ 'ZEPHYR_BASE' : str (tmpdir / 'no-zephyr-here' ),
165+ }
166+ ):
167+ yield
168+
169+
170+ #
171+ # Test fixtures
172+ #
173+
89174@pytest .fixture (scope = 'session' )
90175def _session_repos (tmp_path_factory ):
91176 '''Just a helper, do not use directly.'''
@@ -237,66 +322,20 @@ def west_init_tmpdir(repos_tmpdir):
237322@pytest .fixture
238323def config_tmpdir (tmpdir ):
239324 # Fixture for running from a temporary directory with
240- # environmental overrides in place so all configuration files
241- # live inside of it. This makes sure we don't touch
242- # the user's actual files.
243- #
244- # We also set ZEPHYR_BASE (to avoid complaints in subcommand
245- # stderr), but to a spurious location (so that attempts to read
246- # from inside of it are caught here).
325+ # environmental overrides in place so local configuration file
326+ # live inside of it. This ensures we don't touch the user's local config.
247327 #
248328 # Using this makes the tests run faster than if we used
249329 # west_init_tmpdir from conftest.py, and also ensures that the
250330 # configuration code doesn't depend on features like the existence
251331 # of a manifest file, helping separate concerns.
252- system = tmpdir / 'config.system'
253- glbl = tmpdir / 'config.global'
254- local = tmpdir / 'config.local'
255-
256- os .environ ['ZEPHYR_BASE' ] = str (tmpdir .join ('no-zephyr-here' ))
257- os .environ ['WEST_CONFIG_SYSTEM' ] = str (system )
258- os .environ ['WEST_CONFIG_GLOBAL' ] = str (glbl )
259- os .environ ['WEST_CONFIG_LOCAL' ] = str (local )
260332
261- # Make sure our environment variables (as well as other topdirs)
262- # are respected from tmpdir, and we aren't going to touch the
263- # user's real files.
264- start_dir = os .getcwd ()
265- tmpdir .chdir ()
333+ # determine a local config in tmp dir
334+ local_config = tmpdir / 'config.local'
266335
267- try :
268- assert config ._location (config .ConfigFile .SYSTEM ) == str (system )
269- assert config ._location (config .ConfigFile .GLOBAL ) == str (glbl )
270- td = tmpdir / 'test-topdir'
271- td .ensure (dir = True )
272- (td / '.west' ).ensure (dir = True )
273- (td / '.west' / 'config' ).ensure (file = True )
274- assert config ._location (config .ConfigFile .LOCAL ) == str (local )
275- assert (config ._location (config .ConfigFile .LOCAL ,
276- topdir = str (td )) ==
277- str (local ))
278- td .remove (rec = 1 )
279- assert not td .exists ()
280-
281- assert not local .exists ()
282-
283- # All clear: switch to the temporary directory and run the test.
336+ # run the test within tmpdir and with env variable set
337+ with chdir (tmpdir ), update_env ({'WEST_CONFIG_LOCAL' : local_config }):
284338 yield tmpdir
285- finally :
286- # Go back to where we started, for repeatability of results.
287- os .chdir (start_dir )
288-
289- # Clean up after ourselves so other test cases don't know
290- # about this tmpdir. It's OK if test cases deleted these
291- # settings already.
292- if 'ZEPHYR_BASE' in os .environ :
293- del os .environ ['ZEPHYR_BASE' ]
294- if 'WEST_CONFIG_SYSTEM' in os .environ :
295- del os .environ ['WEST_CONFIG_SYSTEM' ]
296- if 'WEST_CONFIG_GLOBAL' in os .environ :
297- del os .environ ['WEST_CONFIG_GLOBAL' ]
298- if 'WEST_CONFIG_LOCAL' in os .environ :
299- del os .environ ['WEST_CONFIG_LOCAL' ]
300339
301340#
302341# Helper functions
0 commit comments