ci_exec.utils¶
Assorted utility functions.
This module aims to house any utility functions that may facilitate easier consumption
of the ci_exec package.
cd(dest, *[, create])Context manager / decorator that can be used to change directories.
merge_kwargs(defaults, kwargs)Merge
defaultsintokwargsand returnkwargs.
set_env(**kwargs)Context manager / decorator that can be used to set environment variables.
unset_env(*args)Context manager / decorator that can be used to unset environment variables.
- class cd(dest, *, create=False)[source]¶
Context manager / decorator that can be used to change directories.
This context manager will change directories to
dest, and after its scope expires (outside of thewithstatement, or after the decorated function) it will change directories back to the original current working directory.As a context manager:
from ci_exec import cd, which if __name__ == "__main__": # Get the build tools setup. cmake = which("cmake") ninja = which("ninja") # Suppose current directory here is "/source" with cd("build", create=True): # Current directory is now "/source/build" cmake("..", "-G", "Ninja", "-DCMAKE_BUILD_TYPE=Release") ninja() # Any code out-dented (not under the `with`): current directory is "/source"
As a decorator:
from ci_exec import cd, which @cd("build", create=True) def build(): # Inside the function: current directory is "/source/build" cmake = which("cmake") ninja = which("ninja") cmake("..", "-G", "Ninja", "-DCMAKE_BUILD_TYPE=Release") ninja() if __name__ == "__main__": # Suppose current directory here is "/source" build() # Function executes in "/source/build" # After the function current directory is "/source"
- Parameters
dest (pathlib.Path or str) – The destination to change directories to.
create (bool) – Whether or not the
destis allowed to be created. Default:False, thedestmust exist already (willfail()if it does not). IfTrue,mkdir_p()will be called withdest.
- merge_kwargs(defaults, kwargs)[source]¶
Merge
defaultsintokwargsand returnkwargs.Intended usage is for setting defaults to
**kwargswhen the caller did not provide a given argument, but making sure not to overwrite the caller’s explicit argument when specified.For example:
>>> merge_kwargs({"a": 1, "b": 2}, {}) {'a': 1, 'b': 2} >>> merge_kwargs({"a": 1, "b": 2}, {"a": 3}) {'a': 3, 'b': 2}
Entries in the
defaultsparameter only get included of not present in thekwargsargument. This is to facilitate something like this:from ci_exec import merge_kwargs # The function we want to customize the defaults for. def func(alpha=1, beta=2): return alpha + beta # Example: default to alpha=2, leave beta alone. def custom(**kwargs): return func(**merge_kwargs({"alpha": 2}, kwargs)) # custom() == 4 # custom(alpha=0) == 2 # custom(beta=0) == 2 # custom(alpha=0, beta=0) == 0
- class set_env(**kwargs)[source]¶
Context manager / decorator that can be used to set environment variables.
Usage example:
from ci_exec import set_env @set_env(CC="clang", CXX="clang++") def build_clang(): # CC="clang" and CXX="clang++" inside function. # ... or ... with set_env(CC="clang", CXX="clang++"): # CC="clang" and CXX="clang++" in `with` block
Prior environment variable state will be recorded and later restored when a decorated function /
withblock’s scope ends.An environment variable was already set. Its value is saved before overwriting, and then later restored:
# Example: CC=gcc was already set. with set_env(CC="clang"): # Inside block: CC="clang" # Out-dented: CC=gcc again.
An environment variable was not already set. Its value is unset again:
# Example: CC was _not_ set in environment. with set_env(CC="clang"): # Inside block: CC="clang" # Out-dented: CC _not_ set in environment.
Note
See note in unset_env for more information on removing environment variables.
- Parameters
**kwargs – Keyword argument parameter pack. Keys are the environment variable to set, and values are the desired value of the environment variable. All keys and all values must be strings.
- Raises
ValueError – If no arguments are provided (
len(kwargs) == 0), or if any keys / values are not astr.
- class unset_env(*args)[source]¶
Context manager / decorator that can be used to unset environment variables.
Usage example:
from ci_exec import unset_env @unset_env("CC", "CXX") def build(): # Neither CC nor CXX are set in the environment during this function call. # ... or ... with unset_env("CC", "CXX"): # Neither CC nor CXX are set in the environment inside this block.
Prior environment variable state will be recorded and later restored when a decorated function /
withblock’s scope ends. So if an environment variable was already set, its value is saved before deletion, and then later restored:# Example: CC=gcc was already set. with unset_env("CC"): # Inside block: CC not set in environment. # Out-dented: CC=gcc again.
Note
Removing the environment variable is done via
del os.environ[env_var]. This may or may not affect child processes in the manner you expect, depending on whether your platform supportsos.unsetenv(). See the end of the description ofos.environfor more information.- Parameters
*args – Argument parameter pack. Each argument is an environment variable to unset. Each argument must be a string. If a specified argument is not currently set in the environment, it will effectively be skipped.
- Raises
ValueError – If no arguments are provided (
len(args) == 0), or if any arguments are not astr.
Tests¶
Tests for the ci_exec.utils module.
- test_merge_kwargs()[source]¶
Validate
merge_kwargs()merges as expected.