Skip to main content

Validate your .env files against a schema before your app blows up.

Project description

envguard ๐Ÿ›ก๏ธ

Validate your .env files against a schema โ€” before your app blows up in production.

CI PyPI Python 3.9+ License: MIT Zero dependencies


Ever deployed an app only to discover SECRET_KEY was missing, or PORT was set to "eight-thousand" by a copy-paste mistake? envguard catches those problems at startup, with clear human-readable error messages.

envguard validation failed:
  โœ— 'DATABASE_URL' is required but not set
  โœ— 'PORT' must be an integer, got: 'eight-thousand'
  โœ— 'LOG_LEVEL' must be one of 'DEBUG', 'INFO', 'WARNING', 'ERROR', got: 'VERBOSE'

Features

  • โœ… Zero runtime dependencies โ€” stdlib only
  • โœ… Rich type support โ€” str, int, float, bool, url, email, json
  • โœ… Smart defaults โ€” optional fields with fallback values
  • โœ… Constraint checking โ€” min/max length, min/max value, allowed choices
  • โœ… Custom validators โ€” bring your own logic
  • โœ… .env file loading โ€” built-in parser, no python-dotenv required
  • โœ… CLI tool โ€” check your env from CI or the terminal
  • โœ… All errors at once โ€” see every problem in one shot, not one at a time

Installation

pip install envguard

Quickstart

1. Define your schema

# envguard_schema.py
from envguard import EnvGuard, EnvSchema, EnvField

schema = EnvSchema({
    "DATABASE_URL": EnvField(type="url",   description="PostgreSQL DSN"),
    "SECRET_KEY":   EnvField(type="str",   min_length=32),
    "PORT":         EnvField(type="int",   default=8000, min_value=1, max_value=65535),
    "DEBUG":        EnvField(type="bool",  default=False),
    "LOG_LEVEL":    EnvField(type="str",   default="INFO",
                             choices=["DEBUG", "INFO", "WARNING", "ERROR"]),
})

guard = EnvGuard(schema, env_file=".env")

2. Validate at startup

# main.py  /  settings.py  /  app.py โ€” wherever your app boots
from envguard_schema import guard

config = guard.validate()   # raises ValidationError with ALL problems if anything is wrong

DB_URL  = config["DATABASE_URL"]
PORT    = config["PORT"]    # already cast to int โœ“
DEBUG   = config["DEBUG"]   # already cast to bool โœ“

That's it. If anything is wrong your app refuses to start with a clear error. If everything is fine you get a plain dict of correctly-typed values.


Field reference

EnvField(
    type        = "str",    # str | int | float | bool | url | email | json
    required    = True,     # False if you set a default
    default     = None,     # any value; makes field optional
    description = "",       # shown in CLI `envguard list`
    choices     = None,     # ["DEBUG", "INFO", "WARNING"]
    min_length  = None,     # string length (pre-cast)
    max_length  = None,
    min_value   = None,     # numeric range (post-cast)
    max_value   = None,
    validator   = None,     # callable(value) -> bool | raises ValueError
)

Type details

Type Accepted values Returns
str Any non-empty string str
int "42", "-1" int
float "3.14" float
bool true/false, 1/0, yes/no, on/off (case-insensitive) bool
url Must start with http://, https://, or ftp:// str
email Basic user@domain.tld check str
json Any valid JSON string parsed Python object

Custom validators

import re

EnvField(
    type="str",
    validator=lambda v: bool(re.match(r"^[a-z0-9_-]+$", v)),
    description="Slug-safe identifier",
)

# Or raise ValueError for a custom message:
def must_be_https(url: str) -> bool:
    if not url.startswith("https://"):
        raise ValueError("must use HTTPS in production")
    return True

EnvField(type="url", validator=must_be_https)

.env file loading

envguard has a built-in .env parser โ€” no extra packages needed.

guard = EnvGuard(schema, env_file=".env")          # os.environ takes precedence
guard = EnvGuard(schema, env_file=".env", override=True)  # .env wins

Supported syntax:

# Comments are ignored
DATABASE_URL=postgres://localhost/mydb
SECRET_KEY="my super secret key with spaces"
DEBUG=true
PORT=8000

Non-raising mode

ok, errors = guard.check()
if not ok:
    for error in errors:
        print(f"Config error: {error}")

CLI

# Generate a starter schema
envguard init

# Validate your .env against the schema
envguard check
envguard check --schema my_schema.py --env-file .env.production

# List all variables defined in the schema
envguard list
envguard list --schema my_schema.py

Example output of envguard list:

Variable                       Type     Required   Default         Description
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
  DATABASE_URL                 url      yes        โ€”               PostgreSQL connection string
  SECRET_KEY                   str      yes        โ€”               Secret key for session signing
  PORT                         int      no         8000            Port to listen on
  DEBUG                        bool     no         False           Enable debug mode
  LOG_LEVEL                    str      no         INFO            Logging verbosity

Framework integration

FastAPI / Starlette

# settings.py
from envguard import EnvGuard, EnvSchema, EnvField

_guard = EnvGuard(EnvSchema({
    "DATABASE_URL": EnvField(type="url"),
    "SECRET_KEY":   EnvField(type="str", min_length=32),
    "DEBUG":        EnvField(type="bool", default=False),
}), env_file=".env")

config = _guard.validate()   # fails fast at import time

Django

# manage.py / wsgi.py โ€” before django.setup()
from envguard import EnvGuard, EnvSchema, EnvField

EnvGuard(EnvSchema({
    "DJANGO_SECRET_KEY": EnvField(type="str", min_length=50),
    "DJANGO_DEBUG":      EnvField(type="bool", default=False),
    "DATABASE_URL":      EnvField(type="url"),
}), env_file=".env").validate()

Contributing

Pull requests are welcome! Please open an issue first to discuss what you'd like to change.

git clone https://github.com/yourusername/envguard
cd envguard
pip install -e ".[dev]"
pytest

License

MIT ยฉ Your Name

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

envguard_sarve-0.1.0.tar.gz (7.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

envguard_sarve-0.1.0-py3-none-any.whl (5.3 kB view details)

Uploaded Python 3

File details

Details for the file envguard_sarve-0.1.0.tar.gz.

File metadata

  • Download URL: envguard_sarve-0.1.0.tar.gz
  • Upload date:
  • Size: 7.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for envguard_sarve-0.1.0.tar.gz
Algorithm Hash digest
SHA256 67e5a48dbfedccc7843625aa972e122b6e171b0c55fa1f35b5b2800f4a6b79bc
MD5 d3764fa8fea32120cb4c42894eb54de2
BLAKE2b-256 4783fe13f131ec11888df848a4b77f0d421e2290db71fe17a6313729cdc89f45

See more details on using hashes here.

File details

Details for the file envguard_sarve-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: envguard_sarve-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 5.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for envguard_sarve-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1a9781bfdb1f7b062338ec001edcba7cb4d39d720d292fa7410c2220b91cebb8
MD5 93afd5fb770e5304934601a51a24ae91
BLAKE2b-256 91bc9e1b8ed85992d2b3f6139a1d18a48c8c3932a2711f566e96e26df0d5a97b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page