Skip to content

syshttp.env

syshttp.env

Where syshttp's settings come from: a list of prefixes, one environment mapping.

Every setting is a variable with a full name -- syshttp's own carry SYSHTTP_ (SYSHTTP_PROXY, SYSHTTP_HOME, SYSHTTP_HOOKS_<KEY>), conventional ones keep theirs (HTTPS_PROXY, NO_PROXY, CA_BUNDLE) -- read as <PREFIX><NAME> for each prefix in turn, the first one set winning. The prefixes come from SYSHTTP_PREFIX, a :-separated list taken literally (AGENTS_ reads AGENTS_HTTPS_PROXY); blank or unset is one empty prefix, the names as written. A tool embedding syshttp therefore opts out of the defaults with SYSHTTP_PREFIX=MYTOOL_ or layers its own over them with MYTOOL_: (the empty entry last).

An :class:HTTPEnv holds one such view. Two of them with different prefixes or mappings never see each other's settings, which is how one process serves several configurations; every function that reads a setting takes one as env= and builds a default HTTPEnv() when given none. Nothing is read at import: a variable set later takes effect on the next call.

A CGI program gets every request header as an HTTP_* variable, so a client could choose HTTP_PROXY and its kin: under CGI, set a prefix list without the empty entry.

HTTPEnv(prefixes=None, environ=None)

A view of the environment through a list of prefixes.

prefixes -- None (read SYSHTTP_PREFIX at each lookup; blank or unset is ("",)), a :-separated string, or an iterable of prefixes; each is used literally and upper-cased, "" meaning the names as written, and an empty iterable reading nothing. environ -- the mapping to read, default os.environ as it is at each lookup. A malformed prefix is a ValueError: from the constructor for an argument, from the first lookup for SYSHTTP_PREFIX (a ConfigurationError).

Source code in src/syshttp/env.py
76
77
78
79
80
81
82
def __init__(
    self, prefixes: Union[str, Iterable[str], None] = None, environ: Optional[Mapping[str, str]] = None
) -> None:
    if isinstance(prefixes, str):
        prefixes = prefixes.split(":")
    self._prefixes = None if prefixes is None else _prefix_list(prefixes, "prefixes")
    self._environ = environ

environ property

The mapping settings are read from.

prefixes property

The prefixes in force, in lookup order: the argument, else SYSHTTP_PREFIX, else ("",).

family(stem)

(rest, value, variable) for every variable named <PREFIX><stem><rest> with a non-empty rest and a value that is not blank (stripped), the first prefix winning for a rest (compared upper-cased); in prefix order, then name order.

Source code in src/syshttp/env.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
def family(self, stem: str) -> Iterator[Tuple[str, str, str]]:
    """``(rest, value, variable)`` for every variable named
    ``<PREFIX><stem><rest>`` with a non-empty ``rest`` and a value that is
    not blank (stripped), the first prefix winning for a ``rest`` (compared
    upper-cased); in prefix order, then name order."""
    env = self.environ
    seen = set()
    for prefix in self.prefixes:
        head = prefix + stem
        for variable in sorted(env):
            if not variable.startswith(head) or len(variable) == len(head):
                continue
            rest = variable[len(head) :]
            value = (env[variable] or "").strip()
            if value and rest.upper() not in seen:
                seen.add(rest.upper())
                yield rest, value, variable

find(*names)

(variable, value) for the first of names set, not blank, under the first prefix that has one (every name is tried under a prefix before the next prefix); the value stripped. None when none is.

Source code in src/syshttp/env.py
104
105
106
107
108
109
110
111
112
113
114
115
116
def find(self, *names: str) -> Optional[Tuple[str, str]]:
    """``(variable, value)`` for the first of ``names`` set, not blank,
    under the first prefix that has one (every name is tried under a
    prefix before the next prefix); the value stripped. ``None`` when
    none is."""
    env = self.environ
    for prefix in self.prefixes:
        for name in names:
            variable = prefix + name
            value = (env.get(variable) or "").strip()
            if value:
                return variable, value
    return None

get(*names)

The value :meth:find finds, or None.

Source code in src/syshttp/env.py
118
119
120
121
def get(self, *names: str) -> Optional[str]:
    """The value :meth:`find` finds, or ``None``."""
    found = self.find(*names)
    return found[1] if found else None

name(name)

The variable for name under the first prefix: what a message names when nothing is set, and what a child process is given.

Source code in src/syshttp/env.py
 98
 99
100
101
102
def name(self, name: str) -> str:
    """The variable for ``name`` under the first prefix: what a message
    names when nothing is set, and what a child process is given."""
    prefixes = self.prefixes
    return (prefixes[0] if prefixes else "") + name