Sitelet https://envstack.dev/api/

Python API

The Python API mirrors the CLI closely: you can load raw stack files, resolve them into concrete values, apply them to os.environ, and optionally encrypt or serialize the result.

The examples below use the repository’s sample stacks under examples/ so the behavior is easier to reason about.

Loading an environment stack

Loading a stack returns an unresolved Env object. Variable references and modifiers are still present at this stage:

export ENVPATH=./examples/default
>>> import envstack
>>> env = envstack.load_environ("default")
>>> env["ENV"]
'prod'
>>> env["DEPLOY_ROOT"]
'${ROOT}/${ENV}'
>>> env["STACK"]
'default'

This is the programmatic equivalent of:

$ envstack default -u

Resolving a stack into concrete values

To evaluate variable references such as ${ROOT}/${ENV}, resolve the loaded environment:

>>> resolved = envstack.resolve_environ(env)
>>> resolved["ENV"]
'prod'
>>> resolved["ROOT"]
'/mnt/pipe'
>>> resolved["DEPLOY_ROOT"]
'/mnt/pipe/prod'

This matches the CLI’s resolved mode:

$ envstack default -r

For the full expansion grammar, including ${VAR:=default}, ${VAR:-default}, and ${VAR:?message}, see Variable expansion.

Loading inherited stacks

The dev example includes default, then overrides a few values:

>>> dev = envstack.resolve_environ(envstack.load_environ("dev"))
>>> dev["ENV"]
'dev'
>>> dev["LOG_LEVEL"]
'DEBUG'
>>> dev["DEPLOY_ROOT"]
'/mnt/pipe/dev'
>>> dev["PATH"].startswith("/mnt/pipe/dev/bin:/mnt/pipe/prod/bin:")
True

That pattern is often the most useful API workflow:

>>> resolved = envstack.resolve_environ(envstack.load_environ("dev"))

Initializing os.environ

If you want to apply a stack to the current Python process, use init():

>>> import os
>>> envstack.init("dev")
>>> os.getenv("ENV")
'dev'
>>> os.getenv("DEPLOY_ROOT")
'/mnt/pipe/dev'

init() updates os.environ and refreshes sys.path from the resolved PYTHONPATH. This makes it useful for bootstrap scripts and embedded tool launchers.

To restore the prior process environment:

>>> envstack.revert()
>>> os.getenv("ENV") is None
True

Building environments in Python

You can also author an environment directly:

>>> from envstack.env import Env, resolve_environ
>>> env = Env({"FOO": "bar", "BAR": "${FOO}"})
>>> resolve_environ(env)
{'FOO': 'bar', 'BAR': 'bar'}

This is useful when generating derived environments before writing them to disk:

>>> env.write("out.env")

Structured values

envstack supports lists and dictionaries in stack files. The data example shows how unresolved and resolved values differ:

>>> data_env = envstack.load_environ("data")
>>> data_env["DICT"]
{'a': 1, 'b': 2, 'c': '${INT}'}
>>> resolved = envstack.resolve_environ(data_env)
>>> resolved["DICT"]
{'a': '1', 'b': '2', 'c': '5'}
>>> resolved["CHAR_LIST"]
['a', 'b', 'c', 'world']

Encryption workflow

The examples/encryption/ stacks provide a concrete encryption example.

Point ENVPATH at both example roots:

>>> os.environ["ENVPATH"] = "examples/default:examples/encryption"

Load the keys stack first so the decryption keys are present in the process environment:

>>> keys = envstack.resolve_environ(envstack.load_environ("keys"))
>>> os.environ.update({k: str(v) for k, v in keys.items()})

Now encrypted values from secrets.env will resolve automatically:

>>> secrets = envstack.resolve_environ(envstack.load_environ("secrets"))
>>> secrets["KEY"]
'This is encrypted'
>>> secrets["SECRET"]
'my_super_secret_password'
>>> secrets["PASSWORD"]
'password'

You can also encrypt a plain environment in memory:

>>> from envstack.env import Env, encrypt_environ
>>> plain = Env({"SECRET": "super_secret", "PASSWORD": "my_password"})
>>> encrypted = encrypt_environ(plain)
>>> type(encrypted["SECRET"]).__name__
'EncryptedNode'

Common patterns

Load raw stack data:

>>> env = envstack.load_environ("default")

Load and resolve in one step:

>>> resolved = envstack.resolve_environ(envstack.load_environ("dev"))

Apply a stack to the current process:

>>> envstack.init("dev")

Restore the previous process environment:

>>> envstack.revert()

Configuration variables

The following environment variables affect runtime behavior:

Name Description
ALLOW_COMMANDS Allow embedded commands
COMMAND_TIMEOUT Embedded command timeout in seconds
DEFAULT_NAMESPACE Name of the default environment stack (default)
ENVPATH Colon-separated paths to search for environment files
IGNORE_MISSING Ignore missing stack files when resolving environments
INTERACTIVE Force shells to run in interactive mode
STACK Stores the name of the current environment stack