project-conf
Dictionary-style configuration with path helpers and automatic environment variable handling.
A simple, powerful configuration system that behaves like a dictionary but provides convenient path helpers and automatic environment variable integration. Perfect for Python projects that need clean, flexible configuration management.
✨ Features
- 🗂️ Dictionary Interface: Full dict compatibility - use
config['key'],config.get(),config.update(), etc. - 📁 Path Helpers: Automatic directory creation with
config.data_path(),config.logs_path(), etc. - 🌐 Environment Integration: Automatic override from environment variables and
.envfiles - 🎯 Type-Safe Conversion: Smart type conversion based on your defaults
- 🚀 Auto Project Detection: Finds your project root automatically
- 🔧 Runtime Modification: Change configuration at runtime, visible globally
- 📦 Zero Dependencies: Pure Python, no external dependencies
🚀 Quick Start
Installation
pip install project-conf
Basic Usage
from project_conf import setup, get_config
# 1. Define your configuration schema with defaults
setup({
'database_url': 'sqlite:///app.db',
'debug': False,
'max_workers': 4,
'api_key': '',
'features': ['auth', 'cache']
})
# 2. Use anywhere in your application
config = get_config()
# Dictionary-style access
print(config['database_url']) # sqlite:///app.db
config['debug'] = True # Runtime modification
config.update({'timeout': 30}) # Bulk updates
# Path helpers (creates directories automatically)
db_path = config.data_path('app.db') # /project/data/app.db
log_file = config.logs_path('server.log') # /project/logs/server.log
cache_dir = config.cache_path() # /project/cache/
📖 Documentation
Environment Variable Override
Configuration values are automatically overridden by environment variables:
# config.py
setup({
'database_url': 'sqlite:///dev.db',
'debug': True,
'max_workers': 2
})
# Environment variables (case-insensitive, converts types)
export DATABASE_URL="postgresql://localhost/prod"
export DEBUG=false
export MAX_WORKERS=8
config = get_config()
print(config['database_url']) # postgresql://localhost/prod
print(config['debug']) # False
print(config['max_workers']) # 8
.env File Support
Create a .env file in your project root:
# .env
DATABASE_URL=postgresql://localhost/myapp
DEBUG=false
MAX_WORKERS=8
API_KEY=secret-key-123
FEATURES=["auth", "admin", "analytics"]
Values are automatically loaded and type-converted based on your defaults.
Path Helpers
Any method ending with _path becomes a path helper:
config = get_config()
# Directory paths (creates directories)
config.data_path() # /project/data/
config.logs_path() # /project/logs/
config.uploads_path() # /project/uploads/
config.my_custom_path() # /project/my_custom/
# File paths (creates parent directories)
config.data_path('app.db') # /project/data/app.db
config.logs_path('server.log') # /project/logs/server.log
config.uploads_path('image.jpg') # /project/uploads/image.jpg
config.my_custom_path('file.txt') # /project/my_custom/file.txt
Type Conversion
Environment variables are automatically converted to match your default types:
setup({
'debug': False, # bool: 'true'/'false', '1'/'0', 'yes'/'no'
'workers': 4, # int: '8' -> 8
'timeout': 30.0, # float: '45.5' -> 45.5
'name': 'app', # str: kept as string
'features': ['auth'] # list: '["auth", "admin"]' -> ['auth', 'admin']
})
Project Root Detection
The project root is automatically detected by looking for:
.gitdirectory (most reliable)pyproject.tomlsetup.pyrequirements.txtpoetry.lockPipfilepackage.json.env
You can also override with PROJECT_ROOT environment variable or pass it directly:
setup(defaults, project_root='/custom/path')
🎯 Real-World Example
Clean, Simple Pattern - Handle everything in your config module:
# myproject/config.py - ONLY file that deals with project_conf
from project_conf import setup, get_config
# Single source of truth for configuration
DEFAULTS = {
'database_url': 'sqlite:///myproject.db',
'redis_url': 'redis://localhost:6379',
'debug': False,
'max_workers': 4,
'timeout': 30.0,
'api_key': '',
'log_level': 'INFO',
'features': {
'auth': True,
'admin': False,
'analytics': True
}
}
# Initialize configuration
setup(DEFAULTS)
# Export clean interface - no need for project_conf anywhere else!
config = get_config()
# myproject/database.py - Clean imports, no project_conf needed!
from .config import config
def create_connection():
# Use as dictionary
db_url = config['database_url']
timeout = config.get('timeout', 30)
# Use path helper for file location
if 'sqlite' in db_url:
db_file = config.data_path('myproject.db')
return f"sqlite://{db_file}"
return db_url
# myproject/api.py - Clean imports, no project_conf needed!
from .config import config
def setup_logging():
# Runtime configuration changes
if not config.get('api_key'):
config['api_key'] = 'development-key'
# Path helpers for log files
log_file = config.logs_path('api.log')
return setup_logger(
level=config['log_level'],
file=log_file
)
That's it! No complex imports, no worrying about initialization order. Your config.py handles everything, and the rest of your code just imports from there.
✨ Why This Pattern Works
- 🎯 Single Responsibility: Only
config.pydeals withproject_conf - 🧹 Clean Imports: Rest of your code just imports from your own config module
- 🔄 No Initialization Worries: Configuration is ready when you import it
- 📦 Encapsulation:
project_confis an implementation detail, hidden from your app - 🚀 Simple Testing: Mock
myproject.config.configin tests, not the underlying library
🧪 Testing
Run the test suite:
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run with coverage
pytest --cov=project_conf --cov-report=html
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🔗 Links
Metadata
Release files for project-conf 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| project_conf-0.1.2.tar.gz | 20.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| project_conf-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.3 kB
Release files / project_conf-0.1.2.tar.gz
| Download URL | project_conf-0.1.2.tar.gz |
|---|---|
| Size | 20.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
771a4919d0cde6362fa2cd67328c6d1240f34584a4ae5b41fdd0030e061b17d7
|
|
BLAKE2b-256 checksum How to use checksums |
f015952b87fe1f6bb995e463d491f6de6302912556c00ff1a9b85c49449b482d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.5
|
Release files / project_conf-0.1.2-py3-none-any.whl
| Download URL | project_conf-0.1.2-py3-none-any.whl |
|---|---|
| Size | 9.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
377dced8947a238c64b3ed4498b43a05c98def18059191906d5b81ed4c39b5c4
|
|
BLAKE2b-256 checksum How to use checksums |
1074d363ee8c0d2c36422ad9790ee2d5f020b65b9628ab6bfe6b58ceb4f4ba12
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.5
|
Security for project-conf 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.