A framework for elegantly configuring complex applications
—
Centralized registry for storing and managing structured configuration schemas. The ConfigStore enables registration of Python dataclasses, dictionaries, and other objects as configuration templates that can be used by name in Hydra applications.
Singleton registry that stores configuration nodes organized hierarchically by groups and names.
class ConfigStore:
@staticmethod
def instance() -> "ConfigStore":
"""Get the singleton ConfigStore instance."""
def store(
self,
name: str,
node: Any,
group: Optional[str] = None,
package: Optional[str] = None,
provider: Optional[str] = None
) -> None:
"""
Store a configuration node in the repository.
Parameters:
- name: Config name (automatically gets .yaml suffix if missing)
- node: Config node (DictConfig, dataclass, dict, list, or any structured config)
- group: Config group for hierarchical organization (use "/" for subgroups)
- package: Config node parent hierarchy (use "." for nested packages)
- provider: Name of module/app providing this config (for debugging)
"""
def load(self, config_path: str) -> ConfigNode:
"""
Load a configuration node by path.
Parameters:
- config_path: Path to config (e.g., "group/name" or just "name")
Returns:
ConfigNode: Loaded configuration node with metadata
Raises:
ConfigLoadError: If config not found
"""
def list(self, path: str) -> List[str]:
"""
List available configurations at path.
Parameters:
- path: Group path to list
Returns:
List[str]: Sorted list of available config names
Raises:
IOError: If path not found or points to a file
"""
def get_type(self, path: str) -> ObjectType:
"""
Get the type of object at path.
Parameters:
- path: Path to check
Returns:
ObjectType: CONFIG, GROUP, or NOT_FOUND
"""Dataclass representing a stored configuration with metadata.
@dataclass
class ConfigNode:
name: str # Config name
node: DictConfig # The configuration data
group: Optional[str] # Config group
package: Optional[str] # Package hierarchy
provider: Optional[str] # Provider nameContext manager for storing multiple configs with the same provider.
class ConfigStoreWithProvider:
def __init__(self, provider: str) -> None:
"""
Create context manager with provider name.
Parameters:
- provider: Provider name for all configs stored in this context
"""
def store(
self,
name: str,
node: Any,
group: Optional[str] = None,
package: Optional[str] = None
) -> None:
"""Store config with the context provider."""from dataclasses import dataclass
from hydra.core.config_store import ConfigStore
@dataclass
class DatabaseConfig:
driver: str = "mysql"
host: str = "localhost"
port: int = 3306
user: str = "root"
password: str = "password"
# Get ConfigStore instance
cs = ConfigStore.instance()
# Store structured config
cs.store(name="db_config", node=DatabaseConfig)
# Store with group
cs.store(name="mysql", node=DatabaseConfig, group="db")
# Store with package hierarchy
cs.store(name="prod", node=DatabaseConfig, group="db", package="database.primary")from dataclasses import dataclass
from hydra.core.config_store import ConfigStore
@dataclass
class MySQLConfig:
driver: str = "mysql"
port: int = 3306
@dataclass
class PostgreSQLConfig:
driver: str = "postgresql"
port: int = 5432
cs = ConfigStore.instance()
# Store in db config group
cs.store(name="mysql", node=MySQLConfig, group="db")
cs.store(name="postgres", node=PostgreSQLConfig, group="db")
# Use in application
@hydra.main(version_base=None, config_path=None, config_name="config")
def my_app(cfg: DictConfig) -> None:
print(cfg.db.driver)
# Override from command line: python app.py db=postgresfrom dataclasses import dataclass
from hydra.core.config_store import ConfigStore
@dataclass
class ServerConfig:
host: str = "localhost"
port: int = 8080
cs = ConfigStore.instance()
# Store with package hierarchy - config will be nested under server.web
cs.store(
name="web_server",
node=ServerConfig,
package="server.web"
)
# Results in configuration structure:
# server:
# web:
# host: localhost
# port: 8080from hydra.core.config_store import ConfigStore
cs = ConfigStore.instance()
# Store multiple configs with same provider
with cs.provider("my_app"):
cs.store(name="config1", node={"key1": "value1"})
cs.store(name="config2", node={"key2": "value2"})
# Alternative using ConfigStoreWithProvider directly
from hydra.core.config_store import ConfigStoreWithProvider
with ConfigStoreWithProvider("my_app") as store:
store.store(name="config1", node={"key1": "value1"})
store.store(name="config2", node={"key2": "value2"})from hydra.core.config_store import ConfigStore
cs = ConfigStore.instance()
# Load a specific configuration
config_node = cs.load("db/mysql")
print(config_node.name)
print(config_node.node)
print(config_node.provider)
# List available configurations
db_configs = cs.list("db")
print(db_configs) # ['mysql.yaml', 'postgres.yaml']
# Check if path exists and get type
from hydra.core.object_type import ObjectType
obj_type = cs.get_type("db")
if obj_type == ObjectType.GROUP:
print("db is a group")
elif obj_type == ObjectType.CONFIG:
print("db is a config")
elif obj_type == ObjectType.NOT_FOUND:
print("db not found")from dataclasses import dataclass
from hydra import main
from hydra.core.config_store import ConfigStore
from omegaconf import DictConfig
@dataclass
class AppConfig:
name: str = "MyApp"
debug: bool = False
database: dict = None
# Register configuration
cs = ConfigStore.instance()
cs.store(name="config", node=AppConfig)
@main(version_base=None, config_path=None, config_name="config")
def my_app(cfg: AppConfig) -> None: # Type hint matches stored config
print(f"Running {cfg.name}")
if cfg.debug:
print("Debug mode enabled")from dataclasses import dataclass, field
from typing import Dict, Any
from hydra.core.config_store import ConfigStore
@dataclass
class DatabaseConfig:
host: str = "localhost"
port: int = 3306
@dataclass
class CacheConfig:
ttl: int = 3600
size: int = 1000
@dataclass
class AppConfig:
name: str = "MyApp"
database: Dict[str, Any] = field(default_factory=dict)
cache: Dict[str, Any] = field(default_factory=dict)
cs = ConfigStore.instance()
# Store main config
cs.store(name="config", node=AppConfig)
# Store component configs in groups
cs.store(name="mysql", node=DatabaseConfig, group="database")
cs.store(name="redis", node=CacheConfig, group="cache")
# Use with defaults in config file or via defaults list
# config.yaml:
# defaults:
# - database: mysql
# - cache: redisfrom hydra.core.config_store import ConfigStore
from hydra.plugins.config_source import ConfigLoadError
cs = ConfigStore.instance()
# Handle missing config
try:
config = cs.load("nonexistent/config")
except ConfigLoadError as e:
print(f"Config not found: {e}")
# Handle invalid paths
try:
configs = cs.list("nonexistent/path")
except IOError as e:
print(f"Path error: {e}")from hydra.core.config_store import ConfigStore
def discover_configs():
"""Discover all available configurations."""
cs = ConfigStore.instance()
def explore_path(path: str = "", indent: int = 0):
try:
items = cs.list(path)
for item in items:
full_path = f"{path}/{item}" if path else item
print(" " * indent + item)
obj_type = cs.get_type(full_path)
if obj_type == ObjectType.GROUP:
explore_path(full_path, indent + 1)
except IOError:
pass
print("Available configurations:")
explore_path()
discover_configs()Install with Tessl CLI
npx tessl i tessl/pypi-hydra-core