Module for handling configuration from multiple sources.
  • Python 99%
  • Makefile 1%
Find a file
François Schmidts cc210ad5b4 **Critical: Source Priority System** - Fixed bug where later sources incorrectly overwrote earlier sources, ignoring source_order configuration. Now correctly implements first-wins priority (e.g., with source_order: ["env", "files"], ENV values are never overwritten by FILES).
**List Options** - Fixed TypeError when list parameters were present. List options now automatically skip command line parsing and work correctly from ENV and FILES sources only.

- Added `CLAUDE.md` with architecture overview, development workflows, and code style requirements
- Rewrote `README.md` with practical examples, quick start guide, and comprehensive usage documentation

Added 10 new tests covering source priority and list option behavior. Total: 35 tests (up from 25).

If you relied on the buggy behavior where later sources overwrote earlier sources, adjust your `source_order`:

```yaml
source_order: ['cmd', 'files', 'env']

source_order: ['env', 'files', 'cmd']

The first source in source_order now correctly takes precedence.

This version:
- Reduces from ~200 lines to ~30 lines
- Keeps all essential information
- Maintains the breaking change warning with examples
- Removes redundant details while keeping key facts
2026-01-12 23:32:57 +01:00
.claude style: fix line length violations and document code style requirements 2026-01-12 23:29:44 +01:00
tests fix: skip list options in command line parsing and add priority tests 2026-01-12 23:18:37 +01:00
the_conf style: fix line length violations and document code style requirements 2026-01-12 23:29:44 +01:00
.gitignore Initial commit 2017-07-28 14:23:59 +02:00
.travis.yml bootstraping test 2017-10-21 13:11:31 +02:00
CLAUDE.md style: fix line length violations and document code style requirements 2026-01-12 23:29:44 +01:00
LICENSE Initial commit 2017-07-28 14:23:59 +02:00
Makefile bumping dependencies, cleaning style, bumping base python version 2023-11-28 11:24:27 +01:00
poetry.lock Better list option support 2024-12-30 17:21:46 +01:00
pyproject.toml **Critical: Source Priority System** - Fixed bug where later sources incorrectly overwrote earlier sources, ignoring source_order configuration. Now correctly implements first-wins priority (e.g., with source_order: ["env", "files"], ENV values are never overwritten by FILES). 2026-01-12 23:32:57 +01:00
README.md docs: add CLAUDE.md and rewrite README with practical examples 2026-01-12 23:22:38 +01:00
the_conf.example.yml Partial support for list option 2023-01-10 13:55:54 +01:00

the_conf

Build Status Coverage Status

A Python configuration management library that merges values from multiple sources (files, command line, environment variables) with schema validation and configurable priority ordering.

Installation

pip install the_conf
# or
poetry add the_conf

Quick Start

1. Define a Meta Configuration (Schema)

Create a YAML file defining your configuration schema (myapp.meta.yml):

source_order: ['env', 'files', 'cmd']  # Priority order (first wins)
config_files: ['config.yml']

parameters:
  - database_url:
      type: str
      required: true
      help_txt: Database connection string
  - debug:
      type: bool
      default: false
  - max_connections:
      type: int
      default: 10
      among: [5, 10, 20, 50]  # Valid choices
  - nested:
    - timeout:
        type: int
        default: 30

2. Load Configuration

from the_conf import TheConf

# Load meta configuration and gather values from all sources
conf = TheConf('myapp.meta.yml')

# Access values
print(conf.database_url)
print(conf.debug)
print(conf.nested.timeout)

# Modify values (writes to main config file)
conf.max_connections = 20
conf.write()

3. Provide Values from Different Sources

From environment variables:

export DATABASE_URL="postgresql://localhost/mydb"
export NESTED_TIMEOUT="60"

From config file (config.yml):

database_url: postgresql://localhost/mydb
debug: true
nested:
  timeout: 45

From command line:

python myapp.py --database-url postgresql://localhost/mydb --debug --nested-timeout 60

Source Priority System

The source_order defines which source takes precedence when the same parameter is provided from multiple sources. The first source in the list wins - later sources do not overwrite values from earlier sources.

Default order: ["cmd", "files", "env"] (command line > files > environment)

Example with source_order: ["env", "files", "cmd"]:

  • If DEBUG is set in environment variables, the value from config files or command line will be ignored
  • This is useful when you want environment variables (e.g., in containers) to always take precedence

Parameter Options

  • type: str, int, bool, list, dict
  • default: Default value (cannot be combined with required)
  • required: Must be provided from at least one source
  • among: List of valid choices
  • read_only: Prevents modification after initial load
  • no_cmd: Exclude this parameter from command line parsing
  • no_env: Exclude this parameter from environment variable parsing
  • cmd_line_opt: Override the auto-generated command line flag
  • help_txt: Help text for documentation and CLI

List Parameters

Simple Lists

parameters:
  - allowed_ips:
      type: list
      allowed_ips: {type: str}

From environment:

export ALLOWED_IPS_0="192.168.1.1"
export ALLOWED_IPS_1="192.168.1.2"

From file:

allowed_ips:
  - 192.168.1.1
  - 192.168.1.2

In Python:

conf.allowed_ips.append("192.168.1.3")
print(conf.allowed_ips[0])  # 192.168.1.1

Complex Lists (Lists of Dicts)

parameters:
  - servers:
      type: list
      servers:
        - host: {type: str}
        - port: {type: int}

From environment:

export SERVERS_0_HOST="localhost"
export SERVERS_0_PORT="8080"
export SERVERS_1_HOST="remote.host"
export SERVERS_1_PORT="8081"

From file:

servers:
  - host: localhost
    port: 8080
  - host: remote.host
    port: 8081

In Python:

print(conf.servers[0].host)  # localhost
print(conf.servers[0].port)  # 8080

Note: List parameters are not available via command line arguments due to technical limitations.

File Encryption

the_conf supports encrypted configuration files using AES encryption:

# Save encrypted config
conf = TheConf('myapp.meta.yml')
conf.database_password = "secret"
conf.write('config.yml', passkey='my-encryption-key')

# Load encrypted config
conf = TheConf('myapp.meta.yml', passkey='my-encryption-key')

Or via command line/environment:

python myapp.py --passkey my-encryption-key
# or
export THECONF_PASSKEY="my-encryption-key"

Nested Configuration

Create hierarchical configuration structures:

parameters:
  - database:
    - host: {type: str, default: localhost}
    - port: {type: int, default: 5432}
    - credentials:
      - username: {type: str}
      - password: {type: str}

Access with dot notation:

conf.database.host
conf.database.credentials.username

Interactive Configuration Generation

Use the interactive mode to generate configuration files:

conf = TheConf('myapp.meta.yml', prompt_values=True)
# Prompts user for required values and generates config file

Design Philosophy

From this article, a good configuration library should:

  • Provide a standardized API to define parameters via a data schema
  • Generate command line and environment variable parsers from the schema
  • Generate validators from the schema
  • Separate program configuration from user parameters
  • Support read-only settings and permissions
  • Load settings from compatible sources (database, files, APIs, services)
  • Support configuration hierarchies with cascading value retrieval
  • Be simple enough for small scripts yet powerful for complex applications
  • Auto-document settings

Terminology

  • Meta Configuration: The schema file (YAML/JSON) that defines parameter names, types, defaults, and validators
  • User Configuration: The actual values loaded from files, command line, or environment variables

Development

# Run tests
make test

# Run linters
make lint

# Build package
make build

License

GPLv3 - See LICENSE file for details