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 defaults into kwargs and return kwargs.

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 the with statement, 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 dest is allowed to be created. Default: False, the dest must exist already (will fail() if it does not). If True, mkdir_p() will be called with dest.

merge_kwargs(defaults, kwargs)[source]

Merge defaults into kwargs and return kwargs.

Intended usage is for setting defaults to **kwargs when 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 defaults parameter only get included of not present in the kwargs argument. 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
Parameters
  • defaults (dict) – The dictionary of defaults to add to kwargs if not present.

  • kwargs (dict) – The dictionary to merge defaults into.

Returns

The kwargs dictionary, possibly with values from defaults injected.

Return type

dict

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 / with block’s scope ends.

  1. 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.
    
  2. 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 a str.

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 / with block’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 supports os.unsetenv(). See the end of the description of os.environ for 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 a str.

Tests

Tests for the ci_exec.utils module.

test_cd(capsys)[source]

Validate cd behaves as expected.

test_merge_kwargs()[source]

Validate merge_kwargs() merges as expected.

test_set_env()[source]

Validate set_env sets environment variables.

test_unset_env()[source]

Validate unset_env unsets environment variables.