Yaml to Dataclass parser for Config files (Rust-powered for performance)
Project description
Heracless
Type-safe YAML configuration management for Python
Transform your YAML config files into strongly-typed Python dataclasses with full IDE autocomplete support
Why Heracless?
Stop wrestling with dictionaries and string keys. Heracless automatically converts your YAML configuration files into Python dataclasses with full type safety and IDE autocomplete support. Plus it's written in Rust for blazing-fast performance.
# WITHOUT Heracless - prone to typos, no autocomplete
config = yaml.load(open("config.yaml"))
db_host = config["database"]["host"] # Runtime errors waiting to happen
db_port = config["databse"]["port"] # Typo goes unnoticed!
# WITH Heracless - type-safe, autocomplete, catch errors at write-time
config = load_config()
db_host = config.database.host # Autocomplete works!
db_port = config.database.port # Typos caught by IDE/mypy
Features
- Automatic Type Generation - Generates
.pyistub files for full IDE support - Type Safety - Catch configuration errors at development time, not runtime
- Zero Boilerplate - No manual dataclass definitions needed
- IDE Autocomplete - Full IntelliSense/autocomplete for all config values
- Immutable by Default - Frozen dataclasses prevent accidental modifications
- Rust-Powered Performance - Native Rust backend for blazing-fast YAML parsing and stub generation
Installation
From PyPI (Recommended)
pip install heracless
From Source
git clone https://github.com/felixscode/heracless.git
cd heracless
pip install -e .
Requirements
| Python Version | Status |
|---|---|
| 3.10 - 3.13 | Fully Supported |
| 3.9 and below | Not Supported |
Dependencies: PyYAML, black, art
Note: Prebuilt Rust wheels are available for Linux, macOS, and Windows. No Rust installation required!
Quick Start
1. Create your configuration file
Create a config.yaml file with your settings:
# config.yaml
database:
host: localhost
port: 5432
name: myapp_db
credentials:
username: admin
password: secret123 # don't use this in production
api:
base_url: https://api.example.com
timeout: 30
retries: 3
features:
enable_caching: true
max_cache_size: 1000
2. Set up the config loader
Create a load_config.py file in your project:
# src/myproject/load_config.py
from pathlib import Path
from typing import TypeVar
from heracless import load_config as _load_config
# Point to your config file
CONFIG_YAML_PATH = Path(__file__).parent.parent / "config.yaml"
Config = TypeVar("Config")
def load_config(config_path: Path | str = CONFIG_YAML_PATH,
frozen: bool = True,
stub_dump: bool = True) -> Config:
"""Load configuration and generate type stubs."""
file_path = Path(__file__).resolve() if stub_dump else None
return _load_config(config_path, file_path, frozen=frozen)
3. Use your config with full type safety
# src/myproject/main.py
from myproject.load_config import load_config
# Load config - first run generates load_config.pyi with types!
config = load_config()
# Access config with autocomplete and type checking
print(f"Connecting to {config.database.host}:{config.database.port}")
print(f"Database: {config.database.name}")
print(f"API URL: {config.api.base_url}")
print(f"Caching enabled: {config.features.enable_caching}")
Output:
Connecting to localhost:5432
Database: myapp_db
API URL: https://api.example.com
Caching enabled: True
Generated Type Stub Example
After the first run, Heracless automatically generates a load_config.pyi file:
# load_config.pyi (auto-generated)
from dataclasses import dataclass
from typing import TypeVar
@dataclass(frozen=True)
class Credentials:
username: str
password: str
@dataclass(frozen=True)
class Database:
host: str
port: int
name: str
credentials: Credentials
@dataclass(frozen=True)
class Api:
base_url: str
timeout: int
retries: int
@dataclass(frozen=True)
class Features:
enable_caching: bool
max_cache_size: int
@dataclass(frozen=True)
class Config:
database: Database
api: Api
features: Features
This stub file enables full IDE autocomplete and type checking
Usage Examples
Basic Configuration Loading
from myproject.load_config import load_config
# Load with defaults (frozen, with stub generation)
config = load_config()
# Access nested values with autocomplete
db_url = f"{config.database.host}:{config.database.port}"
Mutable Configuration
# Load mutable config for testing or dynamic updates
config = load_config(frozen=False)
# Modify values (only works with frozen=False)
config.database.host = "192.168.1.100"
Converting to Dictionary
from heracless.utils.helper import as_dict
config = load_config()
config_dict = as_dict(config)
# Now a regular Python dictionary
print(config_dict["database"]["host"]) # localhost
Creating Config from Dictionary
from heracless.utils.helper import from_dict
config_dict = {
"database": {
"host": "localhost",
"port": 5432
},
"api": {
"base_url": "https://api.example.com",
"timeout": 30
}
}
config = from_dict(config_dict, frozen=True)
print(config.database.host) # localhost (with type checking!)
Updating Configuration Values
from heracless.utils.helper import mutate_config
config = load_config()
# Create a new config with updated value (immutable pattern)
new_config = mutate_config(config, "database.host", "production-db.example.com")
print(config.database.host) # localhost (original unchanged)
print(new_config.database.host) # production-db.example.com
CLI Tool Usage
Heracless includes a CLI tool for generating stub files and validating configs:
# Generate stub file from config
python -m heracless config.yaml --parse types.pyi
# Dry run (validate config without generating files)
python -m heracless config.yaml --dry
# Show help
python -m heracless --help
Project Structure Example
Here's a recommended project structure:
my_project/
├── src/
│ └── myproject/
│ ├── __init__.py
│ ├── main.py
│ └── config/
│ ├── __init__.py
│ ├── load_config.py # Your config loader
│ └── load_config.pyi # Auto-generated types
├── config/
│ ├── config.yaml # Main config
│ ├── config.dev.yaml # Development overrides
│ └── config.prod.yaml # Production overrides
├── tests/
│ └── test_config.py
├── pyproject.toml
└── README.md
Troubleshooting
Issue: IDE not showing autocomplete
Solutions:
- Ensure the
.pyifile exists next to yourload_config.py - Reload your IDE/editor window
- Check that your language server is running (VSCode: check Python extension)
- For PyCharm: File → Invalidate Caches → Restart
Issue: TypeError: 'Config' object is immutable
Solution: This is by design (frozen dataclass). To modify configs:
- Use
mutate_config()helper to create updated copies - Or load with
frozen=Falsefor mutable configs (not recommended)
Issue: YAML parsing errors
Solution: Ensure your YAML is valid:
# Validate YAML syntax
python -c "import yaml; yaml.safe_load(open('config.yaml'))"
API Reference
Core Functions
load_config(config_path, file_path, frozen)
Load a YAML configuration file and convert it to a typed dataclass.
Parameters:
config_path(Path | str): Path to the YAML configuration filefile_path(Path | str | None): Path where stub file should be generated (None to skip)frozen(bool): Whether the resulting dataclass should be immutable (default: True)
Returns: Config dataclass with attributes matching your YAML structure
Raises:
FileNotFoundError: If config file doesn't existyaml.YAMLError: If YAML file is malformed
Helper Functions
mutate_config(config, name, value)
Create a new config with an updated value (immutable pattern).
from heracless.utils.helper import mutate_config
config = load_config()
new_config = mutate_config(config, "database.port", 3306)
as_dict(config)
Convert a Config dataclass to a nested dictionary.
from heracless.utils.helper import as_dict
config = load_config()
config_dict = as_dict(config) # Returns: dict
from_dict(config_dict, frozen)
Create a Config dataclass from a dictionary.
from heracless.utils.helper import from_dict
config_dict = {"database": {"host": "localhost"}}
config = from_dict(config_dict, frozen=True)
Contributing
Contributions are welcome! Here's how you can help:
Development Setup
# Clone the repository
git clone https://github.com/felixscode/heracless.git
cd heracless
# Install with development dependencies
pip install -e .[dev]
# Run tests
pytest
# Run type checking
mypy heracless
# Run code formatting
black heracless tests
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=heracless --cov-report=html
# Run specific test file
pytest tests/test_config.py
Development Dependencies
Install development dependencies with:
pip install -e .[dev]
This includes:
pytest- Testing frameworkpytest-cov- Coverage reportingmypy- Static type checkingtypes-PyYAML- Type stubs for PyYAML
Documentation Development
To work on the documentation:
# Install documentation dependencies
pip install -e .[doc]
# Serve documentation locally
mkdocs serve
# Build documentation
mkdocs build
Reporting Issues
Found a bug or have a feature request? Open an issue on GitHub.
Please include:
- Heracless version (
pip show heracless) - Python version
- Operating system
- Minimal reproducible example
- Expected vs actual behavior
Roadmap
Current Version: 0.5.1
Planned Features
- Config variants - Support for environment-specific configs (dev/staging/prod)
- Environment variable interpolation -
${ENV_VAR}syntax in YAML
License
Heracless is released under the MIT License. See LICENSE file for details.
MIT License
Copyright (c) 2023 Felix Schelling
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
TL;DR: You can freely use, modify, and distribute this software, even for commercial purposes.
Links & Resources
- PyPI Package: pypi.org/project/heracless
- Documentation: heracless.io
- GitHub Repository: github.com/felixscode/heracless
- Issues & Support: GitHub Issues
Author
Felix Schelling
- GitHub: @felixscode
- Website: felixschelling.de
If Heracless helps your project, consider giving it a star on GitHub!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
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 heracless-0.5.1-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: heracless-0.5.1-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 875.4 kB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afca2333b611762864e66806863870704d6b1a638e3a9f4404c1a2877a847fbd
|
|
| MD5 |
080f4c6cce043699449c936585834025
|
|
| BLAKE2b-256 |
1d274a410a33ac9d1c6901875d320eb1a232e18f563ca7aca7b9ab669ddd3922
|
File details
Details for the file heracless-0.5.1-cp313-cp313-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: heracless-0.5.1-cp313-cp313-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 1.1 MB
- Tags: CPython 3.13, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba476422cfa0fd857876a37d09a9b47b4ab132f42174c6643e87b49185fb88c2
|
|
| MD5 |
1c5e2044a2cafc50770829476b750b3c
|
|
| BLAKE2b-256 |
bdf67fe4e2dc8aaeee5f7925c4cda21bb690a804c90eb70753edbcffc0d92d5a
|
File details
Details for the file heracless-0.5.1-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: heracless-0.5.1-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 977.0 kB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
61fb6eaf21cd86dccfaed25e68e250bb3dd6e89f89bb3576d383cce13bc6a93a
|
|
| MD5 |
340f45a49eda549462725e1b4003e589
|
|
| BLAKE2b-256 |
5ee3d2857c82066e70b3caa204d11100d64ff68cc573a26e404ef70d1066f143
|
File details
Details for the file heracless-0.5.1-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: heracless-0.5.1-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 876.2 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f64c398c6854b2d9d16cf4aef5cee9e2041a38ec2f2f1a90b5405a277d97f3c
|
|
| MD5 |
9b8bbc3cebed83aa1ec0ff6f23e134dc
|
|
| BLAKE2b-256 |
994ef16b8f410c5fe0c61e5702c7f9dd7ab2646bb8acf0f35c3e7381c02781d1
|
File details
Details for the file heracless-0.5.1-cp312-cp312-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: heracless-0.5.1-cp312-cp312-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 1.1 MB
- Tags: CPython 3.12, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ca2aabd06da1ca8d8cbe521bcc2907e02bf98c2dc818a2ef3ec2091466c55d0
|
|
| MD5 |
57433a33d2342f5a498815fa89fb8596
|
|
| BLAKE2b-256 |
30c4e67961a0ff423a1cbbca8a43e65946b96b151036c4522f3106aa2cf56d51
|
File details
Details for the file heracless-0.5.1-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: heracless-0.5.1-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 977.9 kB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2bf6cbd2920942d9917c0c545917dc42efe4dac9ad9c465609bfbf6031b01c9b
|
|
| MD5 |
68bfae0b7d6416f6814ad2cb5fd0468c
|
|
| BLAKE2b-256 |
4ba5e0595c8606f29eb9ef67cd83c9f2f6c432cb0db558ae17c8e3a9855355c0
|
File details
Details for the file heracless-0.5.1-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: heracless-0.5.1-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 876.1 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78b434a7c469f5e59bdd9ddf01bd2239aac7f28851d9023cb248ca3e1ead9c12
|
|
| MD5 |
e7be4e5f5fb47e2cf61a93c58bbd558d
|
|
| BLAKE2b-256 |
897b123261f92b38844ee891408aec5854966738430e627fdc66aed9dd803601
|
File details
Details for the file heracless-0.5.1-cp311-cp311-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: heracless-0.5.1-cp311-cp311-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 1.1 MB
- Tags: CPython 3.11, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d385d1a7e8d85329782bd0aa42b714ac4b0e283661d2b438ebb6254ca1230ac0
|
|
| MD5 |
fdb84deda55a453ab1001563b0b51117
|
|
| BLAKE2b-256 |
6f431f3aeda954d7ae7dc7a197392bbee053bd3b52ca280584888c9d8e2d1e08
|
File details
Details for the file heracless-0.5.1-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: heracless-0.5.1-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 978.0 kB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65a24bb960bd8e29304dd7656a1b0c291abc874af358552dd45acd244e0ecf01
|
|
| MD5 |
ddd233263b1e84b91e14897edeca290b
|
|
| BLAKE2b-256 |
99d2a939844867fab05a2b580ed0611350399a4648fe6fd4994da59b108913c2
|
File details
Details for the file heracless-0.5.1-cp310-cp310-win_amd64.whl.
File metadata
- Download URL: heracless-0.5.1-cp310-cp310-win_amd64.whl
- Upload date:
- Size: 876.0 kB
- Tags: CPython 3.10, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f4c7b7a58ef25356f34e7d1b9d17a55e66b5bc01238a842e3dad2540d8821356
|
|
| MD5 |
b04371601a8c557816ad336d0bb13cdf
|
|
| BLAKE2b-256 |
f970e9fe77cff0c48933fd5dbb367719fc0f7d38eb13c8da05742b37085b3d8a
|
File details
Details for the file heracless-0.5.1-cp310-cp310-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: heracless-0.5.1-cp310-cp310-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 1.1 MB
- Tags: CPython 3.10, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b1ffc3e22cd38921c33b402ab836e11010e11b23cbaf0e75886395fe8220edc
|
|
| MD5 |
6020e553903bf35c7dbfce7c3bf1d59c
|
|
| BLAKE2b-256 |
548a6749068e41ff216b08253ecffa8d495bac5eb65d12665cf53187880c2f36
|
File details
Details for the file heracless-0.5.1-cp310-cp310-macosx_11_0_arm64.whl.
File metadata
- Download URL: heracless-0.5.1-cp310-cp310-macosx_11_0_arm64.whl
- Upload date:
- Size: 977.9 kB
- Tags: CPython 3.10, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
04c8aea56743071cfa77c0fe52de5ca5183939d6af86dc86b3301205b6890a5b
|
|
| MD5 |
e1e45f3436a52f5285e49a0660cadecc
|
|
| BLAKE2b-256 |
b4f69f0a26853dc40ee788f0ffdaa596cd3861e933dc8b37ac095343152e09b6
|