Skip to main content

Layered configuration loader merging env vars, files, and defaults.

Project description

philiprehberger-config-kit

Tests PyPI version Last updated

Layered configuration loader merging env vars, files, and defaults.

Installation

pip install philiprehberger-config-kit

Usage

from philiprehberger_config_kit import Config

config = Config(
    sources=[
        Config.defaults({"port": 3000, "debug": False, "log_level": "info"}),
        Config.json_file("config.json", optional=True),
        Config.env_file(".env", optional=True),
        Config.env(prefix="APP_"),
    ]
)

# Typed access
port = config.get_int("port")
debug = config.get_bool("debug")
db_url = config.get_str("database_url")
timeout = config.get_float("timeout", default=5.0)
hosts = config.get_list("allowed_hosts")

Dot-Notation Access

Retrieve nested values using dot-separated keys:

from philiprehberger_config_kit import Config

config = Config(
    sources=[
        Config.defaults({
            "database": {"host": "localhost", "port": 5432},
            "cache": {"redis": {"url": "redis://localhost"}},
        }),
    ]
)

host = config.get("database.host")           # "localhost"
port = config.get_int("database.port")        # 5432
url = config.get_str("cache.redis.url")       # "redis://localhost"

Source Priority

Sources are applied in order -- later sources override earlier ones:

from philiprehberger_config_kit import Config

config = Config(sources=[
    Config.defaults({...}),       # lowest priority
    Config.json_file("..."),      # overrides defaults
    Config.env_file(".env"),      # overrides JSON
    Config.env(prefix="APP_"),    # highest priority
])

Schema Validation

Define expected keys, types, and allowed values, then validate:

from philiprehberger_config_kit import Config, ConfigSchema, SchemaError

config = Config(sources=[
    Config.defaults({"host": "localhost", "port": 5432, "mode": "dev"}),
])

schema = ConfigSchema()
schema.required("host", str)
schema.required("port", int)
schema.optional("debug", bool)
schema.required("mode", str, choices=["dev", "prod", "test"])

config.validate(schema)  # raises SchemaError with all failures listed

Reload

Refresh configuration from all sources at runtime:

from philiprehberger_config_kit import Config

config = Config(sources=[Config.env(prefix="APP_")])
port = config.get("port")

# After environment changes...
config.reload()
port = config.get("port")  # picks up the new value

Export Methods

from philiprehberger_config_kit import Config

config = Config(sources=[
    Config.defaults({"db": {"host": "localhost", "port": 5432}, "debug": True}),
])

# Deep copy as nested dict
data = config.to_dict()
# {"db": {"host": "localhost", "port": 5432}, "debug": True}

# Flat dict with dot-notation keys (string values)
flat = config.flatten()
# {"db.host": "localhost", "db.port": "5432", "debug": "True"}

# Environment variable format (UPPER_SNAKE_CASE, string values)
env = config.to_env(prefix="APP")
# {"APP_DB_HOST": "localhost", "APP_DB_PORT": "5432", "APP_DEBUG": "True"}

Config Snapshot Diffing

Capture config state and compare snapshots to see what changed:

from philiprehberger_config_kit import Config

config = Config(sources=[
    Config.defaults({"host": "localhost", "port": 3000}),
    Config.env(prefix="APP_"),
])

before = config.snapshot()

# ... environment changes, then reload ...
config.reload()
after = config.snapshot()

diff = before.diff(after)
# {"added": {...}, "removed": {...}, "changed": {"port": {"old": "3000", "new": "8080"}}}

Typed List Getters

Parse comma-separated values into typed lists:

from philiprehberger_config_kit import Config

config = Config(sources=[
    Config.defaults({"ports": "8080,8081,8082", "rates": "1.5,2.0,3.7"}),
])

ports = config.get_int_list("ports")      # [8080, 8081, 8082]
rates = config.get_float_list("rates")    # [1.5, 2.0, 3.7]

# Custom separator
config2 = Config(sources=[Config.defaults({"ids": "1|2|3"})])
config2.get_int_list("ids", sep="|")      # [1, 2, 3]

Environment Variables

With prefix="APP_", env vars are mapped:

  • APP_PORT -> port
  • APP_DATABASE__HOST -> database.host (double underscore = nested)

Bool Coercion

get_bool() accepts: true/false, 1/0, yes/no, on/off

API

Function / Class Description
Config(sources) Layered configuration with typed access
Config.get(key, default) Get a value by key with dot-notation support
Config.get_str(key, default) Get a string value
Config.get_int(key, default) Get an integer value
Config.get_float(key, default) Get a float value
Config.get_bool(key, default) Get a boolean value with coercion
Config.get_list(key, separator, default) Get a list by splitting a string value
Config.get_int_list(key, sep) Split a string value and convert each element to int
Config.get_float_list(key, sep) Split a string value and convert each element to float
Config.require(*keys) Raise ConfigError if any keys are missing
Config.has(key) Check if a key exists
Config.validate(schema) Validate config against a ConfigSchema
Config.reload() Reload configuration from all sources
Config.to_dict() Return a deep copy as a nested dictionary
Config.to_env(prefix) Export as UPPER_SNAKE_CASE environment variable pairs
Config.flatten(prefix) Export as flat dict with dot-notation keys
Config.snapshot() Capture current state as a ConfigSnapshot
Config.freeze() Freeze the config to prevent mutation
ConfigSchema Define expected keys, types, required/optional, and choices
ConfigSchema.required(key, type, choices) Add a required field to the schema
ConfigSchema.optional(key, type, choices) Add an optional field to the schema
ConfigSnapshot Immutable snapshot of config state
ConfigSnapshot.diff(other) Compare two snapshots and return added/removed/changed keys
ConfigError(missing) Raised when required config keys are missing
SchemaError(errors) Raised when config values fail schema validation

Development

pip install -e .
python -m pytest tests/ -v

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT

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

philiprehberger_config_kit-0.3.0.tar.gz (12.8 kB view details)

Uploaded Source

Built Distribution

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

philiprehberger_config_kit-0.3.0-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

Details for the file philiprehberger_config_kit-0.3.0.tar.gz.

File metadata

File hashes

Hashes for philiprehberger_config_kit-0.3.0.tar.gz
Algorithm Hash digest
SHA256 790464318a6175a88902a982bf2f2a47c791f357e418066ea79eec0f0bd66cbe
MD5 945ad1ef53ef7f50cd8cf5cc92a94f02
BLAKE2b-256 36812a0732d18b7fc3fef265337ebfe281ab0696c22adfd1077d1ea567a60e6d

See more details on using hashes here.

File details

Details for the file philiprehberger_config_kit-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for philiprehberger_config_kit-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 605c0855994374cb2177cc9646d3f8281fa8f7ddac86b2ece28fb3375971e3df
MD5 18f82b86f9f5088aaad09a09a7dbc39b
BLAKE2b-256 23ae9e1f6638c3b8d1a686f47a2aca2fa642b779186fe3d3c4f4458ffe510980

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