Skip to main content

Reusable pydantic/dataclass-driven configuration framework with an optional Hydra bridge.

Project description

cfgable

cfgable

English | 简体中文

Python License: MIT Built on pydantic

A small, reusable configuration framework for Python, built on pydantic. It lets every component declare a single config object and be constructed uniformly — from Python, from a YAML file, or from Hydra — with validation happening once at the boundary.

The core depends only on pydantic; the Hydra bridge is optional.

Requirements

  • Python 3.8 or newer
  • pydantic 2.x
  • Hydra support requires the optional hydra extra

Install

pip install cfgable
pip install "cfgable[hydra]"

From a local checkout, use pip install . for the core package or pip install ".[hydra]" for the optional Hydra bridge.

The idea

  1. A component's settings are a pydantic model (*Config), documented with attribute docstrings.
  2. Every class takes one config parameter and reads fields off it.
  3. Inheriting ConfigurableBasis lets the same class be built from an explicit config, a plain mapping, or flat keyword arguments — the shape Hydra's instantiate passes — because the InitConfigMeta metaclass assembles and validates the config for you, then calls config_post_init().
from typing import Optional
from pydantic import BaseModel, ConfigDict, PositiveInt
from cfgable import ConfigurableBasis


class CameraConfig(BaseModel, frozen=True):
    """Configuration for a camera."""

    model_config = ConfigDict(use_attribute_docstrings=True, extra="forbid")

    device: str = "/dev/video0"
    """Video device path."""
    fps: PositiveInt = 30
    """Capture rate in frames per second."""
    serial: Optional[str] = None
    """Optional camera serial number for disambiguation."""


class Camera(ConfigurableBasis):
    """A camera built from a single validated config."""

    def __init__(self, config: CameraConfig):
        self.config = config

    def config_post_init(self):
        super().config_post_init()
        self._opened = False

    def on_configure(self) -> bool:
        self._opened = True
        return True


# All three build the same object:
cam = Camera(CameraConfig(fps=60))            # explicit config
cam = Camera({"fps": 60})                     # mapping
cam = Camera(fps=60)                          # flat kwargs (Hydra-style)

Use ConfigurableBasis when the component has a configure lifecycle. For plain objects that only need config assembly, inherit from InitConfigMixin.

With Hydra

Point _target_ at the class and list the config fields as siblings; the metaclass turns them into the config model:

# camera.yaml
_target_: my_pkg.Camera
fps: 60
device: /dev/video2
from cfgable.hydra_utils import init_hydra_config, hydra_instance

cam = hydra_instance(init_hydra_config("camera.yaml"))

For plain classes you can also nest the config under its own _target_ so standard hydra.utils.instantiate builds Camera(config=CameraConfig(...)).

Round-tripping

Because a component keeps its whole config, it can serialize back to the config that would rebuild it:

cam.dump()                 # -> dict of fields + a "_target_" pointing at the class
cam.save_config("cam.yaml")

The saved YAML can be loaded again by passing the path back to the component:

cam = Camera("cam.yaml")

What's in the box

  • ConfigurableBasis, InitConfigMixin, InitConfigABCMixin — base classes for the single-config construction protocol.
  • InitConfigMeta / InitConfigABCMeta — the metaclass that assembles configs.
  • NoConfig — placeholder for components that need no settings.
  • StrEnum, ReprEnum — a string-enum backport (use this StrEnum, not enum.StrEnum, for consistent behavior across Python 3.8–3.13).
  • ForceSetAttr / force_set_attr — controlled mutation of otherwise-frozen configs.
  • import_string, get_fully_qualified_class_name, dump_or_repr, fetch_config.
  • cfgable.hydra_utilsinit_hydra_config, hydra_instance, hydra_instance_from_dict, hydra_instance_from_config_path (needs [hydra]).

import cfgable never imports Hydra — the bridge is loaded only when you import cfgable.hydra_utils.

Development

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest

Contributing

Issues and pull requests are welcome — see CONTRIBUTING.md for the development setup and conventions, and please follow the Code of Conduct. To report a security issue, see SECURITY.md. Release notes are tracked in CHANGELOG.md, and support options are listed in SUPPORT.md.

License

Released under the MIT License.

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

cfgable-0.1.1.tar.gz (486.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cfgable-0.1.1-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

Details for the file cfgable-0.1.1.tar.gz.

File metadata

  • Download URL: cfgable-0.1.1.tar.gz
  • Upload date:
  • Size: 486.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.18

File hashes

Hashes for cfgable-0.1.1.tar.gz
Algorithm Hash digest
SHA256 dab5a6bcaaff4b81cee3e38290a81e41da353c1ad0d12529524d813eee5a6010
MD5 20707ec7c53d906eda7025e36b6f033f
BLAKE2b-256 c06724736737f6c8b83b46d367dab12bc2a534abd26fa52369a72404137e2767

See more details on using hashes here.

File details

Details for the file cfgable-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: cfgable-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 14.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.18

File hashes

Hashes for cfgable-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 86589dbdead48aaedb4ba671eea41f07eec864958e2326577ca0ac0b5b5ccba5
MD5 226a9ee31539dfc4d3c916489a80db39
BLAKE2b-256 9cf9a071252729e5ea6a830ab21b1bafb5956348869dde74b3b26cbf47050f25

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page