src.config¶
Configuration loader module. Uses Hydra's Compose API to load config.yaml with support for CLI overrides.
Architecture¶
Unlike the typical @hydra.main decorator approach, this module uses Hydra's Compose API for maximum flexibility:
initialize_config_dir()points Hydra at the project rootcompose()loadsconfig.yamland applies any overridesOmegaConf.to_container()converts the result to a plain Python dict- The config is loaded once at import time and shared globally as
CONFIG
This avoids Hydra's side-effects (output directories, working directory changes) while keeping its powerful override system.
Module-Level Constants¶
PROJECT_ROOT¶
PROJECT_ROOT: Path
The absolute path to the project root directory (where config.yaml lives). Resolved at import time by walking up from config.py until config.yaml is found.
CONFIG¶
CONFIG: dict
The parsed configuration dictionary, loaded once at import time via load_config(). If CLI arguments contain Hydra-style overrides (e.g. training.n_trials=5), they are applied automatically.
Example usage:
from src.config import CONFIG, resolve_path
train_csv = resolve_path(CONFIG["data"]["train_csv"])
n_trials = CONFIG["training"]["n_trials"]
Functions¶
get_project_root¶
def get_project_root() -> Path
Walks up the directory tree from the location of config.py until it finds a directory containing config.yaml.
Returns:
| Type | Description |
|---|---|
Path |
Absolute path to the project root directory |
Raises:
| Exception | Condition |
|---|---|
FileNotFoundError |
If config.yaml is not found in any parent directory |
_parse_cli_overrides¶
def _parse_cli_overrides() -> list[str]
Extracts Hydra-style key=value overrides from sys.argv. This is necessary because the Compose API (unlike @hydra.main) does not automatically parse CLI arguments.
Filtering logic:
- Includes arguments that contain
= - Excludes arguments starting with
-(flags like--verbose)
Returns:
| Type | Description |
|---|---|
list[str] |
List of override strings, e.g. ["training.n_trials=5", "training.cv_folds=3"] |
Example:
# Running:
python -m src.train training.n_trials=5 --verbose
# _parse_cli_overrides() returns:
# ["training.n_trials=5"]
# (--verbose is excluded because it starts with "-")
load_config¶
def load_config(overrides: list[str] | None = None) -> dict
Loads config.yaml via Hydra's Compose API with optional overrides.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
overrides |
list[str] \| None |
None |
Hydra override strings. If None, auto-detects from CLI args via _parse_cli_overrides(). |
Returns:
| Type | Description |
|---|---|
dict |
Parsed YAML configuration as a nested dictionary with all overrides applied |
Example — programmatic overrides:
from src.config import load_config
# Override programmatically (ignores CLI args)
cfg = load_config(overrides=["training.n_trials=10", "preprocessing.test_size=0.3"])
print(cfg["training"]["n_trials"]) # 10
Example — automatic CLI detection:
# When called with no arguments, reads overrides from sys.argv
cfg = load_config() # picks up CLI args automatically
resolve_path¶
def resolve_path(relative_path: str) -> Path
Converts a config-relative path string to an absolute path by prepending PROJECT_ROOT.
Parameters:
| Parameter | Type | Description |
|---|---|---|
relative_path |
str |
A path relative to the project root (e.g. "data/raw/train.csv") |
Returns:
| Type | Description |
|---|---|
Path |
Absolute path |
Example:
from src.config import resolve_path
path = resolve_path("models/best_model.pkl")
# → /absolute/path/to/mlops-lab0/models/best_model.pkl