Index
Composition, computed fields, discriminated unions,
and a sweep engine — all in pure Python.
from canopee import ConfigBase
from pydantic import Field, computed_field
class TrainingConfig(ConfigBase):
lr: float = Field(default=1e-3, gt=0, le=1)
epochs: int = 10
batch_size: int = 128
@computed_field
@property
def warmup_steps(self) -> int:
return self.epochs * 100
cfg = TrainingConfig()
fast = cfg | {"lr": 3e-4, "epochs": 5} # immutable merge — new instance
fast.warmup_steps # → 500, auto-recomputed
Why Canopée?¶
🔒
Immutable by default
Every config is a frozen Pydantic model. Instances are safe to cache, hash, and share across threads without defensive copying.
⚡
Computed fields
Declare derived values as
@computed_field properties — pure Pydantic v2, no magic, full IDE support and serialisation.
🧩
Discriminated unions
Model optimizer/scheduler/architecture variants as tagged unions. Pydantic dispatches to the right class automatically — type-safe and serialisable.
🔗
Elegant composition
Override any field at any depth with
cfg | {"optimizer.lr": 3e-4}. Every override re-runs all validators and recomputes all derived fields.
🏗️
Type-safe Evolve
Use
cfg.evolve(lr=3e-4) for an IDE-autocomplete-friendly, type-checked way to create a modified copy of your config without any metaclass magic.
🎯
Sweep engine
Define distributions over config fields, generate variants via grid, random, or Optuna strategies — with a single, consistent API.
⌨️
CLI Reflection
Decorate any function with
@clify to generate a full CLI from your config. Supports nested models via dot-paths and multiple backends (Argparse, Click, Typer).
Canopée vs Hydra¶
| Feature | Canopée | Hydra |
|---|---|---|
| Config language | Pure Python | YAML-first |
| Type safety | Pydantic v2 — full | Structured Configs — verbose |
| Derived fields | @computed_field |
String interpolation ${field} |
| Immutability | Frozen by default | Mutable OmegaConf |
| IDE autocomplete | Full — evolve() with native Pydantic |
Limited |
| Discriminated unions | Native Pydantic discriminator | Manual type tags |
| Sweep support | Grid / Random / Optuna built-in | Basic multirun only |
| CLI support | Native @clify (Argparse/Click/Typer) |
First-class (Argparse-like) |
| Serialisation | JSON / TOML / Python dict | YAML-tied |
| Maintenance | Active | Stalled |
Install¶
pip install canopee
# With Optuna sweep support
pip install canopee[optuna]
# Everything
pip install canopee[all]
Requirements: Python ≥ 3.11, Pydantic ≥ 2.6
Dive in¶
🔬
Complete experiment config with multiple optimizers, schedulers, and model architectures — all type-safe.