os_helper.config_utils module

Configuration Utilities

A program often needs the same setting (a database URL, an API key) to come from different places depending on who is running it: a developer’s laptop reads a config file, a CI job reads a .env file checked into a scratch directory, a deployed server reads plain environment variables set by its host. Without a single rule for “where do I look, and in what order,” each caller ends up writing its own branching logic, and the branches drift.

get_config() fixes the order once: try a JSON/YAML file first, then .env files, then the process environment, and stop at the first source that supplies every key the caller asked for. Whichever source wins, the caller gets back one plain dictionary and never needs to know which tier resolved it.

Usage example

>>> import os_helper as osh
>>> osh.get_config(["db_url"], "myapp", env_files=[])
{'db_url': 'postgres://localhost/myapp'}

Author

Warith HARCHAOUI, https://linkedin.com/in/warith-harchaoui

os_helper.config_utils.get_config(keys, config_type, path=None, env_files=None, *, allow_ambient_env=True)[source]

Load configuration settings using a fixed fallback order.

Precedence (first match wins):

  1. path pointing to a JSON/YAML file (or, if a directory, the first .json, .yaml or .yml file in it that contains all keys);

  2. one or more .env files merged into os.environ;

  3. the current process environment (skipped when allow_ambient_env is False).

Parameters:
  • keys (List[str]) – Keys required to be present in the resolved configuration.

  • config_type (str) – Human-readable label used only in log messages.

  • path (Optional[str], optional) – Path to a configuration file or a directory containing one. If None or empty, this step is skipped.

  • env_files (Optional[List[str]], optional) – .env files to load into os.environ before reading variables. Defaults to [".env"].

  • allow_ambient_env (bool, optional) – When True (the default, and the only behavior before this parameter existed), step 3 reads the live process environment — which includes both the requested .env files and whatever the process happened to inherit at start-up. When False, step 3 is restricted to exactly the requested env_files’ own contents (read directly, never merged into or read back from os.environ): a key that resolves only because it happens to be set in the ambient environment is treated as unresolved. Used by the HTTP API (see os_helper.api), where “the caller can name any environment-variable key and get its live value back” is a credential-exposure shape, not a feature — a local CLI/library caller already has that access by definition, so this only ever needs to be False across a network boundary.

Returns:

Mapping with one entry per requested key.

Return type:

Dict[str, Union[str, int, float]]

Raises:

RuntimeError – If none of the sources provide all required keys.

Example

>>> config = get_config(["host", "port"], "database", path="config.yaml")
>>> config
{'host': 'localhost', 'port': 5432}