Module ds.env

Shell environment variables.

Global variables

var RE_ARGS

Regex for matching an argument to be interpolated.

var RE_EXPAND

Regex for finding variable expansions.

var RE_SPLIT

Regex for splitting commands.

var DEFAULT_WIDTH

Default width for warping commands.

Functions

def interpolate_args(cmd: str, args: List[str]) ‑> str

Return args interpolated into cmd.

def expand(value: str, store: Optional[Mapping[str, str]] = None) ‑> str

Expand variables of the form $var and ${var}.

Regular expansion works as expected:

>>> with TempEnv(a='hello', b='world'):
...     expand("$a ${b}")
'hello world'
>>> expand("nothing")
'nothing'

Unknown variables are left unchanged:

>>> with TempEnv(a='this'):
...     expand("$a is $b")
'this is $b'
def read_env(text: str) ‑> Dict[str, str]

Read an environment file.

>>> read_env('''# IGNORE=line
... export INCLUDE=value
... 'key name'="value with space"
... ''')
{'INCLUDE': 'value', 'key name': 'value with space'}
def wrap_cmd(cmd: str, width: int = 80) ‑> str

Return a nicely wrapped command.

Classes

class TempEnv (**initial: Optional[str])

Temporary environment variables.

Construct a temporary environment object.

Args

**initial : str
initial environment variables to set

Examples:

>>> with TempEnv(foo="bar") as env1:
...     env1["foo"] == "bar"
True
>>> with TempEnv(a="b", c="d", x=None) as env1:
...     with TempEnv(a=None, c="e", f="g") as env2:
...         env2["a"] is None and env2["c"] == "e"
True
Expand source code
class TempEnv:
    """Temporary environment variables."""

    def __init__(self, **initial: Optional[str]):
        """Construct a temporary environment object.

        Args:
            **initial (str): initial environment variables to set

        Examples:
        >>> with TempEnv(foo="bar") as env1:
        ...     env1["foo"] == "bar"
        True
        >>> with TempEnv(a="b", c="d", x=None) as env1:
        ...     with TempEnv(a=None, c="e", f="g") as env2:
        ...         env2["a"] is None and env2["c"] == "e"
        True
        """
        self.saved: Dict[str, Optional[str]] = {}
        for key, value in initial.items():
            if value is None:
                del self[key]
            else:
                self[key] = value

    def __enter__(self) -> TempEnv:
        """Return self when entering a context."""
        return self

    def __exit__(self, *_: Any) -> None:
        """Reset all keys back to their previous values/existence."""
        for key, old in self.saved.items():
            if old is None:
                if key in ENV:
                    del ENV[key]
            else:
                ENV[key] = old

    def __iter__(self) -> Iterator[str]:
        """Return the iterator for ENV.

        >>> list(TempEnv()) != []
        True
        """
        return ENV.__iter__()

    def __len__(self) -> int:
        """Return len(ENV).

        >>> len(TempEnv()) > 0
        True
        """
        return len(ENV)

    def __contains__(self, key: str) -> bool:
        """Return True if the key is in ENV.

        >>> with TempEnv(a="b") as env1:
        ...     "a" in env1
        True
        """
        return key in ENV

    def __getitem__(self, key: str) -> Optional[str]:
        """Return the current value of `key` or `None` if it isn't set."""
        return ENV.get(key, None)

    def __setitem__(self, key: str, value: str) -> None:
        """Set the value of an environment variable.

        >>> with TempEnv(a="b") as env1:
        ...     env1["a"] = "c"
        """
        if key not in self.saved:
            self.saved[key] = ENV.get(key)
        ENV[key] = str(value)

    def __delitem__(self, key: str) -> None:
        """Delete an environment variable.

        >>> with TempEnv(a=None) as env1:
        ...     del env1["a"]
        """
        if key not in self.saved:
            self.saved[key] = ENV.get(key)
        if key in ENV:
            del ENV[key]