GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • envstack
  • API
  • Design
  • Secrets
  • FAQ
  • GitHub

This view

  • Original page
  • New address

GeezerVison is showing envstack.dev — envstack

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

Select raw values without expanding their references:

envstack default -u PATH PYTHONPATH
envstack default -u PYTHONPATH -q

Both -u/--unresolved and -r/--resolve accept zero or more variable names. Without names they show all values; -q prints only the value of one selected variable. Unknown variable names are omitted.

Put stack names before these options: use envstack dev -u, not envstack -u dev. Arguments after -u now select variables, just as they do after -r.

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

See Runtime context for the complete control-variable table, when settings are read, and collision behavior. The default-stack environment setting is DEFAULT_NAMESPACE; ENVPATH uses the host platform’s path delimiter (: on POSIX and ; on Windows).

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.