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
pathsproperty turns vars into filesystem paths with variable expansion, user home directory expansion, and automatic path resolution.2. The
flagsproperty interprets environment variables as int flags, recognizing common truthy values liketrue,yes, andONas1for 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
NOWHEREwhen both the variable and the default are empty.NOWHEREis a non-traversable sentinel: it compares equal only to itself, reportsexists()asFalse, and yields nothing fromiterdir()/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|onas 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_MODEvar.Any value starting with
devcounts, as does leaving$MY_MODEunset 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
$VARand${VAR}references are expanded:>>> from my.apis import env >>> env.set('DEMO_BASE', '/srv/app') >>> env.interpolate('${DEMO_BASE}/data') '/srv/app/data'