Dataclass companion for config metadata and parsing, with a ConfigParser that generates and loads configs from files.
Project description
classconf
A declarative configuration library that transforms classes into typed dataclasses with metadata for seamless file-based parsing and serialization.
Core ideas
- Automatic Dataclasses: Use
@configclassto transform a class into a dataclass. - Integrated Metadata: Attach section names, field mappings, and custom logic directly to your schema.
- Type-Safe Parsing: Use
ConfigParserto load and generate typed instances from configuration files.
Basic usage
from pathlib import Path
from classconf import ConfigParser, configclass
from classconf.format import JSONFormat
@configclass
class PathsConfig:
output_dir: Path = Path("./out")
@configclass(top_level=True)
class AppConfig:
name: str = "demo"
paths: PathsConfig = field(default_factory=PathsConfig)
parser = ConfigParser(
"config.json",
AppConfig,
format=JSONFormat(),
create_noexist=True,
)
config = parser.get(AppConfig)
Generated config
{
"name": "demo",
"paths": {
"output_dir": "out"
}
}
Formats
TOMLFormat(default ifformatisNone)JSONFormat
from classconf.format import TOMLFormat
parser = ConfigParser("config.toml", AppConfig, PathsConfig, format=TOMLFormat())
TOMLFormat accepts none_value to control how None is written. Use
none_value=None to omit None fields entirely.
Custom formats
To add a new format, implement ConfigFormat with read and write methods.
read should return None when the file does not exist.
from pathlib import Path
from typing import Any
from classconf.format import ConfigFormat
class YAMLFormat(ConfigFormat):
def read(self, path: Path) -> dict[str, Any] | None:
...
def write(self, path: Path, data: dict[str, Any]) -> None:
...
Field mappings, serializers, deserializers
from classconf import ConfigParser, configclass
from classconf.format import JSONFormat
def deserialize_num(value: str, **_) -> int:
return int(value.rstrip("x"))
def serialize_num(value: int) -> str:
return f"{value}x"
@configclass(
name="metrics",
field_deserialzers={"count": deserialize_num},
field_serializers={"count": serialize_num},
field_name_mappings={"count": "count_value"},
)
class MetricsConfig:
count: int = 3
parser = ConfigParser(
"config.json",
MetricsConfig,
format=JSONFormat(),
create_noexist=True,
)
metrics = parser.get(MetricsConfig)
Generated config file
{
"metrics": {
"count_value": "3x"
}
}
Deserializers can also accept a parser to resolve other configs. This is useful when a field is typed as a protocol/ABC and a string selects which config section to load.
from typing import Protocol, runtime_checkable
from classconf import ConfigParser, configclass
from classconf.format import TOMLFormat
@runtime_checkable
class DatabaseConfig(Protocol):
driver: ClassVar[str]
@configclass(name="sqlite")
class SQLiteConfig:
driver: ClassVar[str] = "sqlite"
path: str = "app.db"
@configclass(name="postgres")
class PostgresConfig:
driver: ClassVar[str] = "postgres"
host: str = "localhost"
port: int = 5432
def resolve_database(name: str, parser: ConfigParser) -> DatabaseConfig:
return parser.get(SQLiteConfig if name == "sqlite" else PostgresConfig)
def serialize_database(db: DatabaseConfig) -> str:
return db.driver
@configclass(
top_level=True,
field_deserialzers={"database": resolve_database},
field_serializers={"database": serialize_database},
)
class AppConfig:
database: DatabaseConfig = field(default_factory=SQLiteConfig)
parser = ConfigParser(
"config.json",
AppConfig,
SQLiteConfig,
PostgresConfig,
format=TOMLFormat(),
create_noexist=True,
)
config = parser.get(AppConfig)
print(config.database.driver)
Generated config
database = "sqlite"
[postgres]
driver = "postgres"
host = "localhost"
port = 5432
[sqlite]
driver = "sqlite"
path = "app.db"
Generating configs from instances
ConfigParser.generate_config writes a config file from config class instances.
This is useful for preset generation when a CLI or UI offers a few known
configurations and only the selected one should be saved.
from classconf import ConfigParser, configclass
from classconf.format import JSONFormat
@configclass(name="logging")
class LoggingConfig:
level: str = "INFO"
file: str = "app.log"
preset = "debug" # could come from CLI/UI
if preset == "debug":
config = LoggingConfig(level="DEBUG", file="debug.log")
else:
config = LoggingConfig(level="INFO", file="app.log")
ConfigParser.generate_config(
"logging_preset.json",
config,
format=JSONFormat(),
override_existing=True,
)
Adding configs later
parser.add(OtherConfig)
other = parser.get(OtherConfig)
Quirks and constraints
- Only one top-level config class is allowed per parser.
create_noexist=Falserequires the file to exist.- Missing config keys raise
KeyErrorduring parsing. get()raises if the class was not provided to the parser.- With JSON/TOML, fields without defaults are written as
null/Noneplaceholders.
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 classconf-0.3.2.tar.gz.
File metadata
- Download URL: classconf-0.3.2.tar.gz
- Upload date:
- Size: 23.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63eba235a702927f747ae833d5008c2c4cc9c757a6abaaa5c08967b58b5e7d2b
|
|
| MD5 |
d3d5e2b64e54f1983f5f433497d0cad2
|
|
| BLAKE2b-256 |
019abe38338ed0b29f529936f022bccb38c007b07e8072df7db0f68ec1042926
|
File details
Details for the file classconf-0.3.2-py3-none-any.whl.
File metadata
- Download URL: classconf-0.3.2-py3-none-any.whl
- Upload date:
- Size: 9.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b8c63940150f73a1977c29edc4fb6b7bd9eb2b42eb158ef09a7b1df761cd6c0
|
|
| MD5 |
5ea0164c442c813113ad99b24ca613da
|
|
| BLAKE2b-256 |
118d41e3a39c287fc022a72d229a8df99e0af232ceb3ed47f161694388d0b0e8
|