Bridge YAML configuration files and environment variables for flexible app deployment
Project description
dotyaml
A Python library that bridges YAML configuration files and environment variables, providing the flexibility to configure applications using either approach.
The Problem dotyaml Solves
When building applications, you often face a configuration dilemma:
Environment variables are great for deployment flexibility and security (keeping secrets out of code), but they can become disorganized and hard to manage. You end up with a flat list of variables like DB_HOST, API_TIMEOUT, STRIPE_KEY, JWT_SECRET with no clear structure or organization.
YAML configuration files provide excellent organization with nested sections, clear structure, and are easy for humans and AI coding agents to understand. However, they're not ideal for secrets management and deployment flexibility.
dotyaml bridges this gap by letting you have the best of both worlds:
Structured Configuration with Automatic Environment Variable Generation
Define your configuration in organized YAML sections:
database:
host: localhost
port: 5432
name: myapp
api:
timeout: 30
retries: 3
stripe:
publishable_key: pk_test_123
dotyaml automatically generates properly namespaced environment variables following a consistent pattern:
APP_DATABASE_HOST=localhostAPP_DATABASE_PORT=5432APP_API_TIMEOUT=30APP_STRIPE_PUBLISHABLE_KEY=pk_test_123
Flexible Override System with Clear Precedence
The power comes from the precedence system - you can override any configuration value at multiple levels:
- Manual environment variables (highest precedence) - Always win
- YAML configuration with environment variable interpolation
- Automatic .env file loading (lowest precedence)
This means:
- Development: Use
.envfiles for secrets and local overrides - Staging/Production: Set environment variables directly to override anything
- Team sharing: Commit the YAML structure to git, keep secrets in
.env(gitignored) - AI/tooling friendly: The YAML structure clearly expresses your application's configuration needs
Example: Secrets Management Made Simple
.env file (gitignored, contains secrets):
DB_PASSWORD=super_secret_123
STRIPE_SECRET_KEY=sk_live_real_key
config.yaml (committed to git, safe to share):
database:
host: "{{ DB_HOST|localhost }}"
username: admin
password: "{{ DB_PASSWORD }}" # Comes from .env
stripe:
secret_key: "{{ STRIPE_SECRET_KEY }}" # Comes from .env
webhook_endpoint: /webhooks/stripe
Result: Clean, organized configuration with secure secrets management and full deployment flexibility.
Installation
pip install dotyaml
dotyaml automatically includes python-dotenv for .env file support and environment variable interpolation.
Quick Start
Just like python-dotenv, dotyaml is designed to be simple to use. It automatically loads .env files and supports environment variable interpolation:
from dotyaml import load_config
# Automatically loads .env file first, then processes YAML with variable interpolation
load_config('config.yaml')
# Now your app can access configuration via environment variables
import os
db_host = os.getenv('APP_DATABASE_HOST')
Example with secrets management:
.env file (keep secret):
DB_USERNAME=admin
DB_PASSWORD=secret123
config.yaml file (safe to commit):
database:
host: localhost
username: "{{ DB_USERNAME }}"
password: "{{ DB_PASSWORD }}"
Basic Usage
1. Create a YAML configuration file
config.yaml:
database:
host: localhost
port: 5432
name: myapp
api:
timeout: 30
retries: 3
2. Load configuration in your Python application
from dotyaml import load_config
# This will set environment variables based on your YAML structure
load_config('config.yaml', prefix='APP')
# Environment variables are now available:
# APP_DATABASE_HOST=localhost
# APP_DATABASE_PORT=5432
# APP_DATABASE_NAME=myapp
# APP_API_TIMEOUT=30
# APP_API_RETRIES=3
3. Use environment variables in your application
import os
# Your application code remains simple and flexible
database_config = {
'host': os.getenv('APP_DATABASE_HOST'),
'port': int(os.getenv('APP_DATABASE_PORT')),
'name': os.getenv('APP_DATABASE_NAME')
}
Alternative: Environment Variables Only
Your application works the same way even without a YAML file:
# Set environment variables directly
export APP_DATABASE_HOST=prod-db.example.com
export APP_DATABASE_PORT=5432
export APP_DATABASE_NAME=production
export APP_API_TIMEOUT=60
export APP_API_RETRIES=5
# Your application code doesn't change
import os
database_config = {
'host': os.getenv('APP_DATABASE_HOST'),
'port': int(os.getenv('APP_DATABASE_PORT')),
'name': os.getenv('APP_DATABASE_NAME')
}
Advanced Usage
Environment Variable Precedence
Environment variables always take precedence over YAML values:
# YAML file has database.host: localhost
# But environment variable is set:
os.environ['APP_DATABASE_HOST'] = 'prod-db.example.com'
load_config('config.yaml', prefix='APP')
# Result: APP_DATABASE_HOST=prod-db.example.com (env var wins)
Force Override
Override existing environment variables with YAML values:
load_config('config.yaml', prefix='APP', override=True)
ConfigLoader for Advanced Use Cases
from dotyaml import ConfigLoader
# Load configuration without setting environment variables
loader = ConfigLoader(prefix='APP')
config = loader.load_from_yaml('config.yaml') # Returns dict
# Load configuration from environment variables only
env_config = loader.load_from_env()
# Set environment variables from configuration dict
loader.set_env_vars(config)
Automatic .env File Loading and Environment Variable Interpolation
dotyaml automatically loads .env files and supports environment variable interpolation in YAML files using Jinja-like syntax. This is perfect for managing secrets securely:
Basic Environment Variable Interpolation
Use {{ VARIABLE_NAME }} syntax in your YAML files to interpolate environment variables:
# config.yaml
database:
host: localhost
username: "{{ DB_USERNAME }}"
password: "{{ DB_PASSWORD }}"
name: myapp
api:
key: "{{ API_SECRET_KEY }}"
timeout: 30
from dotyaml import load_config
# Automatically loads .env file first, then processes YAML with interpolation
config = load_config('config.yaml', prefix='APP')
Using Default Values
Provide default values using the pipe syntax {{ VARIABLE_NAME|default_value }}:
# config.yaml
database:
host: "{{ DB_HOST|localhost }}"
username: "{{ DB_USERNAME|dev_user }}"
password: "{{ DB_PASSWORD|dev_password }}"
port: "{{ DB_PORT|5432 }}"
Recommended Pattern: Secrets in .env, Config in YAML
Create .env file for secrets (add to .gitignore):
# .env - Keep this file secret and out of version control!
DB_USERNAME=production_admin
DB_PASSWORD=super_secret_password_123!
API_SECRET_KEY=sk_live_abc123def456ghi789
JWT_SECRET=jwt_signing_secret_xyz789
Create YAML config file (safe to commit to git):
# config.yaml - Safe to commit to version control
app:
name: MyApp
debug: false
database:
host: "{{ DB_HOST|localhost }}"
port: 5432
username: "{{ DB_USERNAME }}" # Required from .env
password: "{{ DB_PASSWORD }}" # Required from .env
name: "{{ DB_NAME|myapp_production }}"
ssl: true
api:
secret_key: "{{ API_SECRET_KEY }}" # Required from .env
jwt_secret: "{{ JWT_SECRET }}" # Required from .env
timeout: 30
Load in your application:
from dotyaml import load_config
# Automatically loads .env first, then interpolates variables in YAML
config = load_config('config.yaml', prefix='MYAPP')
# Your secrets are now available as environment variables:
# MYAPP_DATABASE_USERNAME=production_admin
# MYAPP_DATABASE_PASSWORD=super_secret_password_123!
# MYAPP_API_SECRET_KEY=sk_live_abc123def456ghi789
Advanced .env Integration
You can also customize .env file loading:
from dotyaml import load_config
# Custom .env path
config = load_config('config.yaml', prefix='APP', dotenv_path='.env.production')
# Disable automatic .env loading
config = load_config('config.yaml', prefix='APP', load_dotenv_first=False)
# Custom .env path with ConfigLoader
from dotyaml import ConfigLoader
loader = ConfigLoader(prefix='APP', dotenv_path='.env.staging')
yaml_config = loader.load_from_yaml('config.yaml')
Precedence order (highest to lowest):
- Manually set environment variables (highest precedence) - Never overridden
- Variables from
.envfile (loaded automatically) - Only set if not already defined - Interpolated values with defaults in YAML - Uses existing env vars or defaults
- Regular YAML configuration values (lowest precedence)
Critical guarantee: If you manually set any environment variable (either the final prefixed name like APP_DATABASE_HOST or an interpolation source like DB_PASSWORD), dotyaml will never override it. This ensures that manual configuration always takes precedence, whether set via command line, deployment scripts, or any other method.
This pattern gives you maximum flexibility and security:
- Development: Use
.envfor secrets and local overrides - Staging: Use different
.envfiles per environment - Production: Use environment variables only (no
.envfile) - Security: Keep secrets out of your git repository
Data Type Handling
dotyaml automatically handles various YAML data types:
- Strings: Passed through as-is
- Numbers: Converted to string representations
- Booleans: Converted to
"true"/"false" - Lists: Converted to comma-separated strings
- Null values: Converted to empty strings
License
MIT License - see LICENSE file for details.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dotyaml-0.1.2.tar.gz.
File metadata
- Download URL: dotyaml-0.1.2.tar.gz
- Upload date:
- Size: 23.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb1ea818cdea44a62389ff1662af4ce0e1bd5229ac1ec9c4a941b0b7385486d9
|
|
| MD5 |
742d67bfae08b8e04f50f3fbfd46475c
|
|
| BLAKE2b-256 |
b2b16d99738b01f07f1427fd006283032325090fd24430cf8961ce69c7b5efc9
|
File details
Details for the file dotyaml-0.1.2-py3-none-any.whl.
File metadata
- Download URL: dotyaml-0.1.2-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1dff86f3fac1f2fb36dea65859f4f5fe8695a507988863c812d85044b02da3ef
|
|
| MD5 |
781a024024014da4de6165fb3c6ee54f
|
|
| BLAKE2b-256 |
9d00788ac5127d45854c8e1125fa5625ea9356850b248074b6f87fffa2b55ad7
|