Skip to main content

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

Project description

cfgable

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.

Install

pip install cfgable            # core
pip install "cfgable[hydra]"   # + Hydra bridge (hydra-core, omegaconf)

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)

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")

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.9–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.

License

MIT.

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.0.tar.gz (13.4 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.0-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: cfgable-0.1.0.tar.gz
  • Upload date:
  • Size: 13.4 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.0.tar.gz
Algorithm Hash digest
SHA256 75b7c8fa5ee8e2ec8637cc6278986d6f798dee376150d31bb14ec42690e2e2c2
MD5 eeae5226fffe3c7145ece5f4d4fa678a
BLAKE2b-256 854aa60519789f2c12ac5ec718bb0dd3ade5c7399cbbd64473c94de87246c15e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: cfgable-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.6 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1344c0a0a13a54ad719ca0bfae1a56aeafc71d4ae911088ac2354022852d764d
MD5 e6048c92eb6c7df8d2d403702e106490
BLAKE2b-256 6bb73f1ce6ac69df7ad5f21a2f895832aa81cb3bd08e761bf51b142c598f9149

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