Environment: Ergonomic, Concise Shell Variable Interface#

my.apis.Environment.env#

Global instance of this class for convenient access.

class my.apis.Environment.Environment#

An ergonomic interface for reading environment variables.

As opposed to the builtin interface, this singleton class provides intelligent type coercion, automatic dotenv loading, performant caching, and most importantly, a much clearer and more ergonomic syntax.

from my.apis import env

# export SOME_TEXT="production"
print(f'{env.SOME_TEXT=!r}')  # -> 'production'
print(f'{env.MISSING_VAR=!r}')  # -> ''

# export SOME_PATH="~/Downloads"
# export NESTED_PATH="$SOME_PATH/child"
print(f'{env.paths.SOME_PATH=!r}')  # -> PosixPath('/home/username/Downloads')
print(f'{env.paths.NESTED_PATH=!r}')  # -> PosixPath('/home/username/Downloads/child')

# export SOME_FLAG="32"
# export OTHER_FLAG="yes"
# export FALSE_FLAG="yes, some non-truthy string"
print(env.flags.SOME_FLAG)  # -> 32
print(bool(env.flags.OTHER_FLAG))  # -> True
print(bool(env.flags.FALSE_FLAG))  # -> False
print(bool(env.flags.MISSING_FLAG))  # -> False

Beyond basic string access via attribute or item notation, the class provides specialized accessors for common use cases:

1. The paths property turns vars into filesystem paths with variable expansion, user home directory expansion, and automatic path resolution.

2. The flags property interprets environment variables as int flags, recognizing common truthy values like true, yes, and ON as 1 for use w/ booleans.

Note

All environment variable names must be uppercase to be recognized by the interface.

I Getters#

Environment.get(key: str, default: str = '') → str#

Get an environment variable as a string, with optional default.

Equivalent to attribute (env.MY_VAR) or item (env['MY_VAR']) access, which return the empty string for unset variables.

Parameters:
  • key – Environment variable name.

  • default – Value to return when the variable is unset.

Returns:

The variable’s value, with any $VAR/${VAR} references interpolated.

Examples

Read a variable with attribute access or an explicit fallback:

>>> from my.apis import env
>>> env.set('DEMO_GREETING', 'hello world')
>>> env.DEMO_GREETING
'hello world'
>>> env.get('DEMO_MISSING', 'fallback')
'fallback'
>>> env['DEMO_MISSING']
''

II Setters#

Environment.set(key: str, value: str) → None#

Set an environment variable, clearing caches if value changes.

Equivalent to attribute (env.MY_VAR = ...) or item (env['MY_VAR'] = ...) assignment.

Parameters:
  • key – Variable name (must be uppercase with underscores).

  • value – Variable value.

Raises:

AssertionError – If key doesn’t match naming convention.

Examples

Assign via the method or plain attribute syntax:

>>> from my.apis import env
>>> env.set('DEMO_TOPIC', 'docs')
>>> env.DEMO_TOPIC = 'sphinx docs'
>>> env.DEMO_TOPIC
'sphinx docs'

III Paths#

property Environment.paths: _PathEnv#

A cached property allowing for ergonomic dot-notation access to coerced path vars.

Examples

Read an interpolated variable directly as a Path:

>>> from my.apis import env
>>> env.set('DEMO_BASE', '/srv/app')
>>> env.set('DEMO_LOGS', '$DEMO_BASE/logs')
>>> env.paths.DEMO_LOGS
PosixPath('/srv/app/logs')
Environment.path(key: str, default: str | Path = '', mkdir: bool = False) → Path#

Get environment variable as an expanded, resolved path.

Performs variable substitution for ${VAR} or $VAR patterns, then expands user home directory and resolves to absolute path.

Parameters:
  • key – Environment variable name.

  • default – Default path if variable not set.

  • mkdir – Whether to create directory if it doesn’t exist.

Returns:

Resolved absolute path, or NOWHERE when both the variable and the default are empty. NOWHERE is a non-traversable sentinel: it compares equal only to itself, reports exists() as False, and yields nothing from iterdir() / rglob() / glob() so that unset path variables cannot be walked by accident.

Examples

Resolve a set variable, and fall back to the sentinel for an unset one:

>>> from my.apis import env
>>> env.set('DEMO_LOGS', '/srv/app/logs')
>>> env.path('DEMO_LOGS')
PosixPath('/srv/app/logs')
>>> env.path('DEMO_UNSET')
NOWHERE

IV Flags#

property Environment.flags: _FlagEnv#

A cached property allowing for ergonomic dot-notation access to coerced flag vars.

Examples

Read truthy strings and integers as int flags:

>>> from my.apis import env
>>> env.set('DEMO_VERBOSE', 'yes')
>>> env.set('DEMO_WORKERS', '4')
>>> env.flags.DEMO_VERBOSE
1
>>> env.flags.DEMO_WORKERS
4
>>> bool(env.flags.DEMO_UNSET)
False
Environment.flag(key: str, default: int = 0) → int#

Get an environment variable as an integer flag, falling back when unset or unrecognized.

Recognizes (case-insensitively): t|true|y|yes|enable|enabled|on as 1, plus any string of digits (optionally negative) as its integer value.

Parameters:
  • key – Environment variable name (must be uppercase).

  • default – Default value if not set or unrecognized.

Returns:

Any integer.

Raises:

AssertionError – If key is empty or not uppercase.

Examples

Unrecognized values yield the default:

>>> from my.apis import env
>>> env.set('DEMO_OFF', 'nope')
>>> env.flag('DEMO_OFF')
0
>>> env.flag('DEMO_OFF', default=-1)
-1

V Utilities#

property Environment.is_dev: bool#

Check if environment is in development mode, based on the $MY_MODE var.

Any value starting with dev counts, as does leaving $MY_MODE unset entirely. Cached on first access per instance.

Examples

A fresh instance reflects the current $MY_MODE:

>>> from my.apis import Environment
>>> demo = Environment()
>>> demo.set('MY_MODE', 'development')
>>> demo.is_dev
True
static Environment.is_valid_name(key: str) → bool#

Check if string is a valid environment variable name.

Parameters:

key – String to validate.

Returns:

True if key contains only uppercase, digits, and underscores.

Examples

Only uppercase names pass; validate_name() asserts the same predicate:

>>> from my.apis import env
>>> env.is_valid_name('MY_VAR')
True
>>> env.is_valid_name('my_var')
False
static Environment.validate_name(key: str) → None#

Validate environment variable name format.

Parameters:

key – Variable name to validate.

Raises:

AssertionError – If key is invalid.

static Environment.interpolate(val: str) → str#

Replace envvar references in the value with their corresponding values.

Parameters:

val – A string, e.g. ${HOME}/data/${DATASET}.

Returns:

Interpolated string, e.g. /home/user/data/mnist.

Examples

Both $VAR and ${VAR} references are expanded:

>>> from my.apis import env
>>> env.set('DEMO_BASE', '/srv/app')
>>> env.interpolate('${DEMO_BASE}/data')
'/srv/app/data'