Skip to main content

A flexible configuration management library for Python applications

Project description

Confii

Confii Logo

Python Version License CI Status PyPI Version Downloads Coverage Ruff Typed Pre-commit Docs OpenSSF Scorecard

A comprehensive, production-ready configuration management library for Python

InstallationQuick StartFeaturesExamplesDocumentation


Overview

Confii is a modern, feature-rich configuration management library designed for Python applications. It provides a unified interface for loading, merging, validating, and accessing configuration from multiple sources with enterprise-grade features like secret management, schema validation, observability, versioning, and async support.

Why Confii?

  • 🎯 Unified Interface - Single API for all configuration sources
  • 🔐 Secret Management - Built-in support for AWS, Azure, GCP, Vault
  • Type Safety - Full type hints and Pydantic/JSON Schema validation
  • 🔄 Dynamic Reloading - Hot reload with incremental updates
  • 📊 Observability - Metrics, tracing, and event emission
  • 🚀 Async Support - Async/await API for non-blocking config loading
  • 🎨 Developer Experience - IDE autocomplete, debugging tools, CLI
  • 🏢 Enterprise Ready - Versioning, drift detection, advanced merging

Installation

# Basic installation
pip install confii

# With optional dependencies
pip install confii[watch]         # File watching for dynamic reloading
pip install confii[cli]           # CLI tools (confii command)
pip install confii[validation]    # Schema validation (Pydantic, JSON Schema)
pip install confii[cloud]         # Cloud storage support (AWS S3, Azure, GCP)
pip install confii[secrets]       # Secret store support (AWS, Azure, GCP, Vault)
pip install confii[all]           # All features

Requirements: Python 3.9+

📖 See examples/basic_usage.py for getting started


Quick Start

Basic Usage

from confii import Config
from confii.loaders import YamlLoader

# Load from a single file
config = Config(loaders=[YamlLoader("config.yaml")])

# Access configuration values with attribute-style syntax
print(config.database.host)
print(config.database.port)

Multiple Sources

from confii import Config
from confii.loaders import YamlLoader, EnvironmentLoader

# Load from multiple sources (later sources override earlier ones)
config = Config(
    env="production",
    loaders=[
        YamlLoader("config/base.yaml"),
        YamlLoader("config/production.yaml"),
        EnvironmentLoader("APP"),  # APP_* environment variables
    ]
)

Type-Safe Config (North Star Feature)

from pydantic import BaseModel
from confii import Config
from confii.loaders import YamlLoader

class DatabaseConfig(BaseModel):
    host: str
    port: int = 5432
    ssl: bool = False

class AppConfig(BaseModel):
    database: DatabaseConfig
    debug: bool = False

# Config[AppConfig] gives you full type safety
config = Config[AppConfig](
    loaders=[YamlLoader("config.yaml")],
    schema=AppConfig,
    validate_on_load=True,
)

# Full IDE autocomplete and mypy/pyright type checking:
config.typed.database.host   # IDE knows: str
config.typed.database.port   # IDE knows: int
config.typed.database.ssl    # IDE knows: bool
config.typed.nonexistent     # mypy error at dev time!

Load from any source (YAML, JSON, env vars, SSM, Vault) — access with full type safety.

📖 See examples/typed_config.py

With Secret Stores

from confii import Config
from confii.secret_stores import AWSSecretsManager, SecretResolver
from confii.loaders import YamlLoader

# Initialize secret store
secret_store = AWSSecretsManager(region_name='us-east-1')

# Use with Config
config = Config(
    loaders=[YamlLoader("config.yaml")],
    secret_resolver=SecretResolver(secret_store)
)

# Secrets in config.yaml like "${secret:db/password}" are automatically resolved
print(config.database.password)  # Resolved from AWS Secrets Manager

📖 See examples/basic_usage.py for more examples


Features

🎯 Core Features

Multiple Configuration Sources

  • Files: JSON, YAML, TOML, INI, .env
  • Cloud Storage: AWS S3, Azure Blob, Google Cloud Storage, IBM COS
  • AWS Services: SSM Parameter Store, Secrets Manager
  • Remote: HTTP/HTTPS endpoints, Git repositories
  • Environment Variables: System environment with prefix support
  • Secret Stores: AWS, Azure, GCP, HashiCorp Vault
  • Custom Loaders: Extensible loader interface

Schema Validation

from confii import Config
from confii.loaders import YamlLoader
from pydantic import BaseModel

class DatabaseConfig(BaseModel):
    host: str
    port: int = 5432

config = Config(
    loaders=[YamlLoader("config.yaml")],
    schema=DatabaseConfig,
    validate_on_load=True
)

📖 See examples/validation_example.py

Dynamic Reloading

Requires pip install confii[watch] for file watching.

config = Config(
    loaders=[YamlLoader("config.yaml")],
    dynamic_reloading=True  # Watches files for changes
)

# Config automatically reloads when files change
# Or manually reload with incremental updates (no watchdog needed)
config.reload(incremental=True)  # Only reloads changed files

AWS SSM Parameter Store

from confii import Config
from confii.loaders import SSMLoader, YamlLoader

# Load base config from file, override with SSM parameters
config = Config(
    env="production",
    loaders=[
        YamlLoader("config.yaml"),
        SSMLoader("/myapp/production/", decrypt=True),
    ],
)

# /myapp/production/database/host → config.database.host
print(config.database.host)

Introspection API

# List all keys
keys = config.keys()

# Check if key exists
exists = config.has("database.host")

# Get value with default
value = config.get("database.host", "localhost")

# Get schema information
schema = config.schema("database")

# Explain how a value was resolved
info = config.explain("database.host")

📖 See examples/introspection_api.py

Configuration Overrides

# Programmatic overrides
config.set("database.host", "remote.db.example.com")
config.set("database.port", 3306)

# Or via CLI
# confii load production --override "database.host=remote.db.example.com"

🔐 Secret Store Integration

Comprehensive secret management with automatic resolution:

from confii.secret_stores import (
    AWSSecretsManager,
    HashiCorpVault,
    AzureKeyVault,
    GCPSecretManager,
    SecretResolver
)

# AWS Secrets Manager
store = AWSSecretsManager(region_name='us-east-1')

# HashiCorp Vault with OIDC + Kerberos (SSO)
from confii.secret_stores.vault_auth import OIDCAuth
auth = OIDCAuth(role='myapp-role', use_kerberos=True)
store = HashiCorpVault(url='https://vault.example.com', auth_method=auth)

# Multi-store fallback
from confii.secret_stores import MultiSecretStore, DictSecretStore
store = MultiSecretStore([
    DictSecretStore({"local/key": "override"}),  # Highest priority
    AWSSecretsManager(region_name='us-east-1'),  # Production
])

config = Config(
    loaders=[YamlLoader("config.yaml")],
    secret_resolver=SecretResolver(store)
)

Configuration file with secret placeholders:

database:
  host: prod-db.example.com
  password: "${secret:prod/database/password}"
api:
  key: "${secret:prod/api/key:api_key}"  # JSON path extraction

Supported Secret Stores:

  • AWS Secrets Manager - Native AWS secret management
  • HashiCorp Vault - Enterprise secrets with 10+ auth methods
    • OIDC with Kerberos (SSO, no browser if kinit done)
    • LDAP with PIN+Token (complex password policies)
    • JWT, Kubernetes, AWS, Azure, GCP, AppRole, Token
  • Azure Key Vault - Azure native secret management
  • GCP Secret Manager - Google Cloud secret management
  • Environment Variables - Simple env-based secrets
  • Multi-Store - Combine multiple stores with fallback hierarchy

📖 See examples/secret_store_example.py and docs/SECRET_STORES.md

🚀 Advanced Features

Async/Await Support

from confii.async_config import AsyncConfig, AsyncYamlLoader

async def main():
    loader = AsyncYamlLoader("config.yaml")
    config = await AsyncConfig.create(loaders=[loader])
    value = await config.get_async("database.host")

📖 See examples/async_example.py

Configuration Versioning

# Enable versioning
version_manager = config.enable_versioning()

# Save current configuration as a version
version = config.save_version(metadata={
    "author": "user@example.com",
    "message": "Updated database config"
})

# Rollback to a previous version
config.rollback_to_version(version.version_id)

# List all versions
versions = version_manager.list_versions(limit=10)

Configuration Diff & Drift Detection

# Compare two configurations
config1 = Config(loaders=[YamlLoader("dev.yaml")])
config2 = Config(loaders=[YamlLoader("prod.yaml")])
diffs = config1.diff(config2)

for diff in diffs:
    print(f"{diff.path}: {diff.diff_type.value}")

# Detect configuration drift
intended = Config(loaders=[YamlLoader("intended.yaml")])
actual = Config(loaders=[YamlLoader("actual.yaml")])
drift = actual.detect_drift(intended)

Observability & Metrics

# Enable metrics collection
observer = config.enable_observability()

# Use configuration normally
host = config.database.host

# Get metrics statistics
metrics = config.get_metrics()
print(f"Config accessed {metrics['accessed_keys']} times")
print(f"Reload count: {metrics['reload_count']}")

# Enable event emission
emitter = config.enable_events()

@emitter.on("reload")
def handle_reload(new_config, duration):
    print(f"Config reloaded in {duration}s")

# Or register without decorator
emitter.on("change", lambda old, new: print("Config changed"))

Advanced Merging Strategies

from confii.merge_strategies import AdvancedConfigMerger, MergeStrategy

merger = AdvancedConfigMerger(MergeStrategy.MERGE)
merger.set_strategy("database", MergeStrategy.REPLACE)  # Replace entire section
merger.set_strategy("app.debug", MergeStrategy.REPLACE)  # Replace specific key

result = merger.merge(base_config, override_config)

Configuration Composition

# config/base.yaml
_defaults:
  - database: postgres
  - cache: redis

_include:
  - config/shared.yaml
  - config/features.yaml

app:
  name: MyApp
  version: 1.0.0

📖 See examples/advanced_features.py

🛠️ Developer Experience

Debug Mode & Source Tracking

config = Config(debug_mode=True)

# Find where a value came from
source = config.get_source("database.port")
print(f"database.port loaded from: {source}")

# Get detailed information
info = config.get_source_info("database.port")
print(f"Value: {info.value}")
print(f"Source: {info.source_file}")
print(f"Override count: {info.override_count}")

# Export debug report
config.export_debug_report("config_debug.json")

IDE Support

# Auto-generates type stubs for IDE autocomplete
config = Config(
    loaders=[YamlLoader("config.yaml")],
    enable_ide_support=True,
    ide_stub_path=".confii/stubs.pyi"
)

# Your IDE will now provide autocomplete for config keys!

ConfigBuilder Pattern

from confii import ConfigBuilder
from confii.loaders import YamlLoader

config = (ConfigBuilder()
    .with_env("production")
    .add_loader(YamlLoader("config.yaml"))
    .enable_deep_merge()
    .with_schema(AppConfig, validate_on_load=True)
    .build())

CLI Tools

Requires pip install confii[cli]

Confii includes a CLI for common operations:

# Validate configuration
confii validate production --loader yaml:config.yaml

# Lint configuration for best practices
confii lint production --loader yaml:config.yaml

# Export configuration
confii export production --format=json --output=config.json

# Show configuration sources
confii debug production --key=database.host

# Explain how a configuration value was resolved
confii explain production --key=database.host

# Compare two configurations
confii diff development production \
    --loader1 yaml:dev.yaml \
    --loader2 yaml:prod.yaml

# Migrate from other tools
confii migrate dotenv .env --output config.yaml
confii migrate dynaconf settings.yaml --output config.yaml
confii migrate hydra conf/config.yaml --output config.yaml

# Load with overrides
confii load production \
    --loader yaml:config.yaml \
    --override "database.host=remote.db.example.com" \
    --override "database.port=3306"

Examples

We provide comprehensive, runnable examples for every feature. Each file is self-contained — creates temp files, demonstrates the feature, and cleans up.

Quick Reference

Feature What You'll Learn Example File
YAML / JSON loading Load config from YAML and JSON files basic_usage.py
TOML loading Load config from TOML files with sections loaders_showcase.py
INI loading Load config from INI files, section→dict mapping loaders_showcase.py
.env file loading Comments, quotes, dot-notation, type coercion loaders_showcase.py
Environment variables EnvironmentLoader with prefix and nesting loaders_showcase.py
HTTP remote loading HTTPLoader with auth and headers loaders_showcase.py
AWS SSM Parameter Store SSMLoader with path prefix and decryption loaders_showcase.py
Deep merge vs shallow How multi-source merge preserves/replaces keys loaders_showcase.py
Environment resolution default + production section merging basic_usage.py
env_prefix auto-override Config(env_prefix="MYAPP") env var overrides config_management.py
merge_strategy Per-path REPLACE/MERGE/APPEND strategies config_management.py
Config reload Manual config.reload(), incremental, dry_run config_management.py
on_change callbacks React to config changes during reload config_management.py
freeze() Make config immutable after loading config_management.py
Versioning Save, list, rollback config versions config_management.py
Config diff Compare two configs, see added/removed/modified config_management.py
Drift detection Detect actual vs intended config drift config_management.py
config.layers Inspect source precedence stack config_management.py
Custom hooks Global, key-specific, and condition hooks extensibility.py
Custom loaders Extend Loader base class for custom sources extensibility.py
Observability / metrics Access counts, reload stats, performance extensibility.py
Event emission @emitter.on("reload") decorator pattern extensibility.py
Composition _include and _defaults directives extensibility.py
Export config.export("json"), YAML, TOML extensibility.py
Standalone validate() Post-hoc validation with Pydantic models extensibility.py
Introspection API keys(), has(), get(), schema(), explain() introspection_api.py
Pydantic validation Model-based schema validation validation_example.py
JSON Schema validation Dictionary schema with defaults validation_example.py
Secret stores DictSecretStore, EnvSecretStore, MultiSecretStore secret_store_example.py
Vault authentication OIDC, LDAP, Kerberos, K8s, AWS, JWT, AppRole vault_auth_examples.py
Async config AsyncConfig, AsyncYamlLoader, async reload async_example.py
ConfigBuilder Fluent builder pattern basic_usage.py
Config[T] typed access Full IDE autocomplete via Pydantic models typed_config.py
End-to-end demo Complete working application working_demo.py

Example Files

File Focus Area Examples
loaders_showcase.py All loader types TOML, INI, .env, env vars, HTTP, SSM, deep/shallow merge
config_management.py Config lifecycle Reload, freeze, versioning, diff, drift, callbacks, layers
extensibility.py Customization Hooks, custom loaders, observability, events, composition, export
basic_usage.py Getting started YAML/JSON, env resolution, ConfigBuilder
introspection_api.py Querying config keys, has, get, schema, explain, set
validation_example.py Validation Pydantic models, JSON Schema, defaults
secret_store_example.py Secrets Multiple providers, fallback chains, caching
vault_auth_examples.py Vault auth 10+ authentication methods
async_example.py Async support Async loading, parallel sources, async validation
typed_config.py Type safety Config[T], nested models, multi-source typed
working_demo.py End-to-end Complete real-world application

Run any example:

python examples/loaders_showcase.py      # All loader types
python examples/config_management.py     # Reload, freeze, versioning, diff
python examples/extensibility.py         # Hooks, custom loaders, events
python examples/basic_usage.py           # Getting started

Documentation

API Reference

Guides


Feature Comparison

Feature Confii python-dotenv Dynaconf Hydra OmegaConf pydantic-settings
Multiple file formats ✅✅ Limited
Source tracking ✅✅
Cloud storage ✅✅
Secret stores ✅✅ ⚠️
Schema validation ⚠️ ✅✅
Type safety ✅✅
Configuration composition ✅✅
Override system ✅✅ ⚠️ ✅✅ ✅✅
Introspection API ✅✅
Incremental reloading ✅✅
Async/await support
Configuration versioning
Drift detection
Observability/metrics
IDE autocomplete ✅✅
Hot reload
Type casting

Legend: ✅✅ = Strong/Unique feature, ✅ = Supported, ⚠️ = Partial support, ❌ = Not supported


Testing

import pytest
from confii import Config
from confii.loaders import YamlLoader

@pytest.fixture
def test_config():
    return Config(loaders=[
        YamlLoader("tests/fixtures/test_config.yaml")
    ])

def test_database_config(test_config):
    assert test_config.database.host == "localhost"
    assert test_config.database.port == 5432

Run tests:

# Run all tests
pytest

# Run with coverage
pytest --cov=confii

# Run specific test file
pytest tests/test_config.py

Contributing

We welcome contributions! Please see our Contributing Guide for details.

# Clone repository
git clone https://github.com/confiify/confii-py.git
cd confii-py

# Install development dependencies
make setup

# Run tests
make test

# Run all checks (lint, type check, tests)
make check

License

MIT License. See LICENSE.txt for details.


Links


Built with ❤️ by confiify and contributors.

Made for developers who value type safety, observability, and developer experience.

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

confii-2026.3.30.2.tar.gz (11.3 MB view details)

Uploaded Source

Built Distribution

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

confii-2026.3.30.2-py3-none-any.whl (170.4 kB view details)

Uploaded Python 3

File details

Details for the file confii-2026.3.30.2.tar.gz.

File metadata

  • Download URL: confii-2026.3.30.2.tar.gz
  • Upload date:
  • Size: 11.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for confii-2026.3.30.2.tar.gz
Algorithm Hash digest
SHA256 51d99b55aa9b947d5952809f664d86975af2c2b5e3409679c84cb6c0575c0704
MD5 3571c71178e1fc13d8697c5e89dd165d
BLAKE2b-256 9a54bec7768bc8dd514e63709f277afeb4fe3780ba5dfa275690827024eb25e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for confii-2026.3.30.2.tar.gz:

Publisher: release.yml on confiify/confii-py

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

File details

Details for the file confii-2026.3.30.2-py3-none-any.whl.

File metadata

  • Download URL: confii-2026.3.30.2-py3-none-any.whl
  • Upload date:
  • Size: 170.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for confii-2026.3.30.2-py3-none-any.whl
Algorithm Hash digest
SHA256 48d810947cfb8bdce98a2e64b925b8fb80965abaa31205fe9390dc558c01ff65
MD5 00675fc304592caf750197973f023780
BLAKE2b-256 3586b29d7989e9ec19e97f1906915a142350e5c259cf117994b344a27698dd83

See more details on using hashes here.

Provenance

The following attestation bundles were made for confii-2026.3.30.2-py3-none-any.whl:

Publisher: release.yml on confiify/confii-py

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