Skip to main content

A powerful configuration management library with beautiful display, environment variables and YAML support

Project description

ConfigPlusPlus

Beautiful configuration management for Python with environment variables and YAML support

PyPI version Python License: MIT

Features

โœจ Beautiful Display - Pretty formatted configuration output with automatic grouping and secret masking

๐Ÿ” Secret Masking - Automatically hides sensitive values (API keys, passwords, tokens)

๐ŸŒ Environment Variables - Load configuration from environment variables with type casting

๐Ÿ“„ YAML Support - Load configuration from YAML files with custom parsing

๐ŸŽฏ Type Casting - Automatic type conversion (str, int, float, bool, Path)

๐Ÿท๏ธ Static & Instance - Support for both static class-based and instance-based configs

Installation

pip install configplusplus

Or with Poetry:

poetry add configplusplus

Quick Start

Environment-Based Configuration

from configplusplus import EnvConfigLoader, env
import pathlib

class AppConfig(EnvConfigLoader):
    # Required variables
    DATABASE_HOST = env("DATABASE_HOST")
    DATABASE_PORT = env("DATABASE_PORT", cast=int)
    
    # Optional with defaults
    DEBUG_MODE = env("DEBUG_MODE", cast=bool, default=False)
    
    # Paths
    DATA_DIR = env("DATA_DIR", cast=pathlib.Path)
    
    # Secrets (automatically masked in output)
    SECRET_API_KEY = env("SECRET_API_KEY")

# Use as static class
print(AppConfig.DATABASE_HOST)
print(AppConfig)  # Beautiful formatted output

Output:

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘              APPCONFIG                     โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

โ–ถ DATABASE
    DATABASE_HOST = 'localhost'
    DATABASE_PORT = 5432

โ–ถ DEBUG
    DEBUG_MODE = False

โ–ถ DATA
    DATA_DIR = '/var/data/myapp'

โ–ถ SECRET
    SECRET_API_KEY = 'sec...et (hidden)'

YAML-Based Configuration

from configplusplus import YamlConfigLoader

class UiConfig(YamlConfigLoader):
    def __post_init__(self) -> None:
        # Parse the loaded YAML data
        self.app_name = self._raw_config["application"]["name"]
        self.theme = self._raw_config["display"]["theme"]
        
        # Parse nested structures
        self.filters = [
            FilterConfig(**f) 
            for f in self._raw_config["filters"]
        ]

# Instantiate with path
config = UiConfig("config.yaml")
print(config.app_name)
print(config)  # Beautiful formatted output

Environment Variables

Basic Usage

from configplusplus import env

# String (default)
DATABASE_HOST = env("DATABASE_HOST")

# Integer
DATABASE_PORT = env("DATABASE_PORT", cast=int)

# Boolean
DEBUG_MODE = env("DEBUG_MODE", cast=bool)

# Float
TEMPERATURE = env("TEMPERATURE", cast=float)

# Path
DATA_DIR = env("DATA_DIR", cast=pathlib.Path)

# With default value
TIMEOUT = env("TIMEOUT", cast=int, default=30)

# Optional (won't raise if missing)
OPTIONAL = env("OPTIONAL", required=False, default=None)

Boolean Casting

When cast=bool, these strings are considered False:

  • "false", "False", "FALSE"
  • "0"
  • "no", "No", "NO"
  • "" (empty string)

All other values are considered True.

Loading .env Files

from configplusplus import safe_load_envs

# Load .env file with logging
safe_load_envs()  # Loads from ".env"

# Load from custom path
safe_load_envs("config/.env")

# Silent loading
safe_load_envs(verbose=False)

YAML Configuration

Basic Usage

from configplusplus import YamlConfigLoader

class MyConfig(YamlConfigLoader):
    def __post_init__(self) -> None:
        # Access raw YAML data
        self.database_host = self._raw_config["database"]["host"]
        self.database_port = self._raw_config["database"]["port"]

Helper Methods

config = MyConfig("config.yaml")

# Get values with dot notation
host = config.get("database.host")
port = config.get("database.port")

# Get with default
timeout = config.get("api.timeout", default=30)

# Check if key exists
if config.has("database.host"):
    print("Database configured")

# Convert to dictionary
config_dict = config.to_dict()

Advanced Features

Custom Validation

class ValidatedConfig(EnvConfigLoader):
    DATABASE_PORT = env("DATABASE_PORT", cast=int)
    
    @classmethod
    def validate(cls) -> None:
        super().validate()
        if cls.DATABASE_PORT < 1024:
            raise RuntimeError("DATABASE_PORT must be >= 1024")

# Validate configuration
ValidatedConfig.validate()

Structured Data from YAML

from dataclasses import dataclass
from typing import List

@dataclass
class FilterConfig:
    name: str
    type: str
    enabled: bool = True

class UiConfig(YamlConfigLoader):
    def __post_init__(self) -> None:
        # Parse list of structured objects
        self.filters: List[FilterConfig] = [
            FilterConfig(**f)
            for f in self._raw_config["filters"]
        ]

Multiple Configuration Sources

# Combine environment and YAML configs
class AppConfig(EnvConfigLoader):
    # From environment
    SECRET_API_KEY = env("SECRET_API_KEY")
    DATABASE_HOST = env("DATABASE_HOST")
    
    # Load YAML for features
    @classmethod
    def load_features(cls) -> None:
        yaml_config = YamlConfigLoader("features.yaml")
        cls.FEATURES = yaml_config.get("features")

AppConfig.load_features()

Secret Masking

Variables containing these keywords are automatically masked in output:

  • SECRET
  • API_KEY
  • PASSWORD
  • TOKEN
  • CREDENTIAL

Example:

SECRET_API_KEY = "sk_live_abc123xyz789"
# Output: "sk_...89 (hidden)"

PASSWORD = "short"
# Output: "***hidden***"

Configuration Grouping

Configuration values are automatically grouped by prefix:

class AppConfig(EnvConfigLoader):
    DATABASE_HOST = env("DATABASE_HOST")
    DATABASE_PORT = env("DATABASE_PORT", cast=int)
    API_ENDPOINT = env("API_ENDPOINT")
    API_KEY = env("API_KEY")

Output shows grouped display:

โ–ถ DATABASE
    DATABASE_HOST = 'localhost'
    DATABASE_PORT = 5432

โ–ถ API
    API_ENDPOINT = 'https://api.example.com'
    API_KEY = 'key...23 (hidden)'

Real-World Examples

FastAPI Application Config

from configplusplus import EnvConfigLoader, env, safe_load_envs
import pathlib

safe_load_envs()

class APIConfig(EnvConfigLoader):
    # Server
    HOST = env("HOST", default="0.0.0.0")
    PORT = env("PORT", cast=int, default=8000)
    
    # Database
    DATABASE_URL = env("DATABASE_URL")
    DATABASE_POOL_SIZE = env("DATABASE_POOL_SIZE", cast=int, default=10)
    
    # Redis
    REDIS_HOST = env("REDIS_HOST", default="localhost")
    REDIS_PORT = env("REDIS_PORT", cast=int, default=6379)
    
    # Security
    SECRET_JWT_KEY = env("SECRET_JWT_KEY")
    TOKEN_EXPIRE_MINUTES = env("TOKEN_EXPIRE_MINUTES", cast=int, default=60)
    
    # Features
    ENABLE_CORS = env("ENABLE_CORS", cast=bool, default=True)
    ENABLE_DOCS = env("ENABLE_DOCS", cast=bool, default=False)
    
    @classmethod
    def validate(cls) -> None:
        if cls.PORT < 1024 or cls.PORT > 65535:
            raise RuntimeError("Invalid PORT")

# Use in FastAPI
from fastapi import FastAPI

app = FastAPI(
    title="My API",
    docs_url="/docs" if APIConfig.ENABLE_DOCS else None,
)

Document Processing Pipeline Config

from configplusplus import YamlConfigLoader
from typing import List
from dataclasses import dataclass

@dataclass
class ProcessorConfig:
    name: str
    enabled: bool
    priority: int

class PipelineConfig(YamlConfigLoader):
    def __post_init__(self) -> None:
        # Parse processors
        self.processors: List[ProcessorConfig] = [
            ProcessorConfig(**p)
            for p in self._raw_config["processors"]
        ]
        
        # Parse paths
        self.input_dir = pathlib.Path(self._raw_config["paths"]["input"])
        self.output_dir = pathlib.Path(self._raw_config["paths"]["output"])
        
        # Parse settings
        self.batch_size = self._raw_config["settings"]["batch_size"]
        self.max_workers = self._raw_config["settings"]["max_workers"]

# Load configuration
config = PipelineConfig("pipeline.yaml")

# Use in pipeline
for processor in sorted(config.processors, key=lambda x: x.priority):
    if processor.enabled:
        print(f"Running {processor.name}")

Documentation

  • Quick Reference: See REFERENCE.md for a cheat sheet
  • Detailed Guide: See USAGE.md for comprehensive documentation
  • Examples: Check the examples/ directory for working code samples

Links

License

MIT License - See LICENSE file for details.

Author: Florian BARRE

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

configplusplus-0.1.1.tar.gz (11.5 kB view details)

Uploaded Source

Built Distribution

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

configplusplus-0.1.1-py3-none-any.whl (12.5 kB view details)

Uploaded Python 3

File details

Details for the file configplusplus-0.1.1.tar.gz.

File metadata

  • Download URL: configplusplus-0.1.1.tar.gz
  • Upload date:
  • Size: 11.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for configplusplus-0.1.1.tar.gz
Algorithm Hash digest
SHA256 80b618c059bf9b71e67b8490bf6b0c6d77620eb33d92bdac08725347f6131fe2
MD5 a13a7d385b3620a876a73ce7c48521f0
BLAKE2b-256 535ba2b8fc6b5ce248b919f7ad160fb09388403f62518dd6a89cfe4afe8f96b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for configplusplus-0.1.1.tar.gz:

Publisher: publish.yml on Florian-BARRE/ConfigPlusPlus

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

File details

Details for the file configplusplus-0.1.1-py3-none-any.whl.

File metadata

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

File hashes

Hashes for configplusplus-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 78da6ee3c4e84cdce46eead581ebd9999137fecb31cc1cd53f6d1668abb7a385
MD5 676ee8df9be2d2728d83cb3af0622b0e
BLAKE2b-256 e6973adb7f0cb39b319dd3f9aea0caca8d89f95615d083d70f9b85d2cee33d42

See more details on using hashes here.

Provenance

The following attestation bundles were made for configplusplus-0.1.1-py3-none-any.whl:

Publisher: publish.yml on Florian-BARRE/ConfigPlusPlus

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