Skip to main content

Zero-dependency typed environment variable loader for Python

Project description

specenv

Zero-dependency typed environment variable loader for Python

PyPI version Python versions License MIT CI


The Problem

Reading environment variables in plain Python is verbose, fragile, and produces cryptic errors at runtime:

import os

PORT    = int(os.environ.get("PORT", "8080"))
DEBUG   = os.environ.get("DEBUG", "false").lower() in ("1", "true", "yes")
TIMEOUT = float(os.environ.get("TIMEOUT", "30.0"))
HOSTS   = [h.strip() for h in os.environ.get("ALLOWED_HOSTS", "").split(",") if h.strip()]

# If PORT is "abc" you get:
# ValueError: invalid literal for int() with base 10: 'abc'
# — no variable name, no hint on how to fix it.

The Solution

import specenv

PORT    = specenv.get("PORT",           default=8080,  cast=int)
DEBUG   = specenv.get("DEBUG",          default=False, cast=bool)
TIMEOUT = specenv.get("TIMEOUT",        default=30.0,  cast=float)
HOSTS   = specenv.get("ALLOWED_HOSTS",  default=[],    cast=list)

# If PORT is "abc" you get:
# EnvCastError: Cannot cast PORT="abc" to int.
#     → Set PORT to a valid integer (e.g. PORT=8080)

Install

pip install specenv

Python 3.10+ required. No runtime dependencies.


Usage

Simple get

import specenv

PORT    = specenv.get("PORT",    default=8080,  cast=int)
DEBUG   = specenv.get("DEBUG",   default=False, cast=bool)
TIMEOUT = specenv.get("TIMEOUT", default=30.0,  cast=float)
HOSTS   = specenv.get("ALLOWED_HOSTS", default=[], cast=list)        # list[str]
PORTS   = specenv.get("PORTS",   default=[8080],  cast=list[int])    # list[int]

When default is omitted and the variable is not set, EnvCastError is raised immediately.

Bool casting

Environment value Result
1, true, yes, on True
0, false, no, off False
anything else EnvCastError

Matching is case-insensitive (TRUE, Yes, ON all work).

Schema-based loading

Group all variables into a single class for easier testing and injection:

from specenv import Schema, Var

class AppConfig(Schema):
    PORT        = Var(int,      default=8080)
    DEBUG       = Var(bool,     default=False)
    DB_URL      = Var(str,      required=True)
    TIMEOUT     = Var(float,    default=30.0)
    ALLOWED_IPS = Var(list[str], default=[])

config = AppConfig.load()
print(config.PORT)   # 8080 (or whatever PORT is set to)

Pass a plain dict to load() in tests to avoid touching the real environment:

cfg = AppConfig.load(env={"DB_URL": "sqlite:///test.db"})

Validation

PORT = specenv.get(
    "PORT",
    cast=int,
    validate=lambda v: 1 <= v <= 65535,
)

Or inside a Schema:

class Config(Schema):
    PORT = Var(int, default=8080, validate=lambda v: 1 <= v <= 65535)

Namespace / prefix

db    = specenv.namespace("DB_")
HOST  = db.get("HOST", default="localhost")      # reads DB_HOST
PORT  = db.get("PORT", default=5432, cast=int)   # reads DB_PORT

cache = specenv.namespace("CACHE_")
URL   = cache.get("URL", default="redis://localhost:6379")  # reads CACHE_URL

Error Messages

Every error is designed to tell you what went wrong and how to fix it.

EnvCastError: Cannot cast PORT="abc" to int.
    → Set PORT to a valid integer (e.g. PORT=8080)

EnvCastError: Required variable DB_URL is not set.
    → Add DB_URL to your environment or .env file.

EnvValidationError: PORT=99999 failed validation (must satisfy the provided lambda).

API Reference

Symbol Description
specenv.get(name, *, default, cast, validate) Read and optionally cast one variable
specenv.namespace(prefix) Return a Namespace that prepends prefix to every key
specenv.reset() Reset internal state (no-op in 0.1.0; safe to call in teardowns)
Schema Base class for declarative config
Var(cast_type, *, default, required, validate) Field descriptor used inside a Schema
Namespace Prefix-scoped view returned by namespace()
EnvCastError Raised on missing required variable or bad cast
EnvValidationError Raised when a validate callable returns False

Supported cast types: int, float, bool, str, list, list[int], list[float], list[str], pathlib.Path, and any list[T] where T is one of the above.


Contributing

Bug reports and pull requests are welcome on the GitHub issues page. Please open an issue before starting large changes so we can discuss the approach first.


License

MIT — see LICENSE.

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

specenv-0.2.0.tar.gz (10.2 kB view details)

Uploaded Source

Built Distribution

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

specenv-0.2.0-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file specenv-0.2.0.tar.gz.

File metadata

  • Download URL: specenv-0.2.0.tar.gz
  • Upload date:
  • Size: 10.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for specenv-0.2.0.tar.gz
Algorithm Hash digest
SHA256 b615fa10dd10d5889483352f1952f3647a8bf9a02c1fde589ad5646cce42d666
MD5 41a2db4d3e42362458dae2154d25384a
BLAKE2b-256 6f3ab15ffa5060cc4c617d2f850007f6b7a70814c6ba09ce22f307b5982222e2

See more details on using hashes here.

Provenance

The following attestation bundles were made for specenv-0.2.0.tar.gz:

Publisher: publish.yml on abhijatchaturvedi/envspec

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file specenv-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: specenv-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 9.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for specenv-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c6810e9c6261c9a39b31dfb8faa05390b75d62eb68e6024aaf6541f49345c65d
MD5 5fa2f191280fd0d20f5cb0e5e358b0a3
BLAKE2b-256 ea269d87eb5e7570ed3b776aa232ab5560fb2c8834a169186d8489d38f1a9abb

See more details on using hashes here.

Provenance

The following attestation bundles were made for specenv-0.2.0-py3-none-any.whl:

Publisher: publish.yml on abhijatchaturvedi/envspec

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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