Skip to main content

envo

Environment variable loading utility.

envo provides a powerful, type-safe way to manage environment variables in Python projects. It automatically discovers .env files, coerces values to appropriate types, validates against specifications, and offers both programmatic and CLI interfaces.

Features

  • Load From Many Sources - .env.sample + .env.base + .other.yaml + c.json + d.toml + .env + os.environ
  • Refs - ENV_VAR_B=$ENV_VAR_A
  • Math - ITEM_COUNT=($MODE=="prod")?5:10
  • Chaining - ENVO_EXTENDS=.env.base ENVO_EXTENDED_BY=.env.overrides
  • Auto-Coerced Types - env.MY_VAL # 5 <int> automatically converts strings to int, float, bool, Path, dict, list, and more
  • Validation - using @min/@max/@type/etc declarations in sample.env
  • Self-Documenting - comments in the sample.env get loaded into the Env object and used/shown in commandline tools
  • CLI Tools - for validating, configuring, etc.
  • Path Substitution - % references the project root, and can be used for filepath env variables
  • Path Fallbacks - /file-a.txt|/file-b.txt will use the firs path that exists
  • Multiple file formats — Load from .env, .json, .yaml, and .toml files
  • Variable grouping — Auto-detected from sample.env, helps with grabbing chunks of env variables
  • Customizable — Override behavior with ENVO_* environment variables
  • Supports .py env specs - Allow using .py files to specify default values

How to use?

Requirements

  • Python 3.10+

Install

pip install modularizer-envo

Your job is simple:

  • write a sample.env in your project root
  • let the user overwrite variables using .env or by running envo config
  • load in parsed variables with from envo import Env and env = Env()

Quick Start

Programmatic Usage

from envo import Env

# Auto-discover and load environment
env = Env()

# Access with automatic type coercion
debug = env.DEBUG          # bool
port = env.PORT            # int
db_url = env.DATABASE_URL  # str

# Or use the pre-built global instance
from envo import env
print(env.DEBUG)

Using a Spec File

Create a sample.env file to define your environment schema:

# sample.env - Environment Variable Specification

# =============================================================================
# database - Database Configuration
# =============================================================================
DB_HOST=localhost          # Database hostname @required
DB_PORT=5432               # Port number @type:int @range:1-65535
DB_NAME=myapp              # Database name

# =============================================================================
# server - Server Configuration  
# =============================================================================
DEBUG=false                # Enable debug mode @type:bool
PORT=8080                  # Server port @type:int
LOG_LEVEL=info             # Log level @choices:debug,info,warn,error

Then in your code:

from envo import Env

env = Env()  # Automatically uses sample.env as spec

# Values are validated and coerced according to spec
port = env.DB_PORT    # int: 5432
debug = env.DEBUG     # bool: False

CLI Commands

envo show - Display environment variables with colored output.

envo validate - Validate a .env file against a spec.

envo config - Interactive TUI for browsing and editing environment variables.

Spec File Format

Basic .env Spec

# =============================================================================
# group_name - Group Description
# =============================================================================

VARIABLE_NAME=default_value  # Documentation text @directive:value

# Supported directives:
#   @type:int|float|bool|str|path|json|list|glob
#   @min:N          - Minimum value
#   @max:N          - Maximum value
#   @range:N-M      - Range constraint
#   @choices:a,b,c  - Valid choices
#   @pattern:regex  - Regex pattern
#   @required       - Value must be non-empty

JSON/YAML Spec

# config.yaml
database:
  DB_HOST:
    default: localhost
    help: Database hostname
    required: true
  DB_PORT:
    default: 5432
    type: int
    min: 1
    max: 65535

server:
  DEBUG:
    default: false
    type: bool
  PORT:
    default: 8080
    type: int

Type Coercion

envo automatically coerces values based on content or explicit type hints:

Type Examples Notes
bool true, false, 1, 0, yes, no, on, off Case-insensitive
int 42, 1_000_000 Underscores allowed
float 3.14, 1_000.5 Underscores allowed
path /home/user, ~/data, %/config % = project root
dict/list {"key": "value"}, ["a", "b"] JSON format
null null, none Becomes Python None
# Explicit type override
env.get("PORT", type=int)
env.get("HOSTS", type=list)
env.get_as("CONFIG_PATH", Path)

File Chaining

Chain multiple configuration files with priority control:

# base.env - Load another file with LOWER priority (we override it)
ENVO_EXTENDS=defaults.env
DB_HOST=production-db

# .env - Load another file with HIGHER priority (it overrides us)
ENVO_EXTENDED_BY=.env.local

Priority order (lowest to highest):

  1. Spec file defaults (sample.env)
  2. Extended files (ENVO_EXTENDS)
  3. Main .env file
  4. Extending files (ENVO_EXTENDED_BY)
  5. System environment variables (os.environ)

Variable References

Reference other variables with $VAR_NAME:

BASE_DIR=/app
DATA_DIR=$BASE_DIR/data
LOG_DIR=$BASE_DIR/logs
FULL_URL=http://$HOST:$PORT/api

Use % to reference the project root:

CONFIG_PATH=%/config
DATA_PATH=%/data

Expression Operators

Envo supports logical and arithmetic expressions for dynamic configuration:

Operator Syntax Description Result
Ternary $VAR?yes:no If VAR is truthy, use "yes", else "no" yes or no
NOT !$VAR Logical negation true or false
AND $A&&$B Logical AND true or false
OR $A||$B Logical OR true or false
Equals $A==$B Equality check true or false
Not Equals $A!=$B Inequality check true or false

Note: Single | and / are NOT operators to avoid conflicts with path separators.

# Ternary - conditional values
DEBUG_MSG=$DEBUG?Debugging enabled:Production mode
DB_HOST=$USE_DOCKER?db:localhost

# Logical operators (use && and ||)
IS_READY=$DB_CONFIGURED&&$CACHE_CONFIGURED
USE_FALLBACK=$PRIMARY_DOWN||$FORCE_FALLBACK
FEATURE_OFF=!$FEATURE_ENABLED

# Comparisons
IS_PROD=$ENV==production
NOT_LOCAL=$ENV!=local

# Arithmetic
TOTAL_WORKERS=$CPU_COUNT*2
ADJUSTED_PORT=$BASE_PORT+$INSTANCE_ID

# String concatenation (when values aren't both numeric)
GREETING=$HELLO+$WORLD

# Combine with parentheses
SHOW_DEBUG=($DEBUG&&$VERBOSE)||$FORCE_DEBUG
COMPLEX_CALC=($A+$B)*$C

Truthiness: Values are truthy unless they are empty, false, 0, no, off, null, or none.

Variable Groups

Filter variables by group for organized access:

# Get all database variables
db_env = env.get_group("database")
print(db_env.DB_HOST)

# List all available groups
print(env.list_groups())

# Access all groups as a dict
for name, group_env in env.groups.items():
    print(f"{name}: {list(group_env.keys())}")

Configuration

Customize envo behavior with environment variables:

Variable Default Description
ENVO_DEFAULT_ENV_FILE .env Default env file name
ENVO_DEFAULT_SPEC_FILES sample.env,.env.sample Spec file search order
ENVO_DEFAULT_GROUP unknown Default group for ungrouped vars
ENVO_USE_SPEC_DEFAULT <default> Special value to use spec default
ENVO_BOOL_TRUE_VALUES true,1,yes,on,y,enable,enabled Values coerced to True
ENVO_BOOL_FALSE_VALUES false,0,no,off,n,disable,disabled Values coerced to False
ENVO_PROJECT_ROOT_CHAR % Character for project root substitution
ENVO_REF_CHAR $ Character for variable references

See sample.env in the repository for the complete list of configuration options, including color scheme customization.

Advanced Usage

Custom Spec

from envo import Env

env = Env(
    ".env",
    spec={
        "PORT": int,
        "DEBUG": bool,
        "HOSTS": list,
        "DB_*": {"groups": ("database",), "type": str},
        "API_*": {"groups": ("api",), "required": True},
    }
)

Multiple Files with Priority

# Load with explicit priority order
env = Env(
    "defaults.env",      # Lowest priority
    ".env",              # Medium priority
    ".env.local",        # Highest priority
)

# Control system environment handling
env = Env(
    ".env",
    existing_env_priority="lowest",  # or "highest" (default), "none"
)

Validation Pipeline

from envo import Env
from envo.spec_type import VariableSpec

env = Env(
    spec={
        "PORT": VariableSpec(
            type=int,
            default=8080,
            validator=lambda x: x if 1 <= x <= 65535 else ValueError("Invalid port"),
        ),
        "EMAIL": VariableSpec(
            type=str,
            pattern=r"^[^@]+@[^@]+\.[^@]+$",
            required=True,
        ),
    }
)

Access Raw Values

# Get the raw string value before coercion
raw_port = env.raw["PORT"]  # "8080" (string)

# Get the parsed/coerced value
port = env.PORT  # 8080 (int)

License

Unlicense — Public Domain

Metadata

Release files for modularizer-envo 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for modularizer-envo 0.2.0
File Size Uploaded
modularizer_envo-0.2.0.tar.gz 57.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for modularizer-envo 0.2.0
File Interpreter ABI Platform
modularizer_envo-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 116.4 kB

Release files / modularizer_envo-0.2.0.tar.gz

Download URL modularizer_envo-0.2.0.tar.gz
Size 57.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9b5492e96bb789688bbb945cbf1524804c4b142283d8f22868dce2d2f5e7bcef
BLAKE2b-256 checksum
How to use checksums
7a0b6f729ca8f2a21dedbd912cda5aa4788c71dc69987f97264608f5e08b9333
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 22, 2026.

Transparency log

Release files / modularizer_envo-0.2.0-py3-none-any.whl

Download URL modularizer_envo-0.2.0-py3-none-any.whl
Size 59.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
369fe12cc23434d15d459d2ef0d8ec7db4a03253f7cd1235585abea09bf05af9
BLAKE2b-256 checksum
How to use checksums
68eb90e579a30bc58c8c9689c3d9c0db1f56f19d149a2009663856d8e3237ce5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page