Metadata-Version: 2.4
Name: ezconfy
Version: 0.1.1
Summary: Add your description here
Author-email: Alessio Arcara <alessio.arcara@studio.unibo.it>, Francesco Baiocchi <francesco.baiocchi2@studio.unibo.it>
Requires-Python: >=3.11
Requires-Dist: loguru>=0.7.3
Requires-Dist: pydantic>=2.12.5
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: twine>=6.2.0
Requires-Dist: typer>=0.24.1
Provides-Extra: dev
Requires-Dist: mkdocs-material>=9.7.5; extra == 'dev'
Requires-Dist: mkdocstrings[python]>=1.0.3; extra == 'dev'
Requires-Dist: mypy>=1.19.1; extra == 'dev'
Requires-Dist: pre-commit>=4.5.1; extra == 'dev'
Requires-Dist: pytest-cov>=7.1.0; extra == 'dev'
Requires-Dist: pytest>=9.0.2; extra == 'dev'
Requires-Dist: ruff>=0.15.5; extra == 'dev'
Requires-Dist: types-pyyaml>=6.0.12.20250915; extra == 'dev'
Description-Content-Type: text/markdown

# ezconfy

A lightweight Python library for YAML-based configuration with automatic Pydantic validation and dynamic object instantiation.

## Installation

```bash
pip install ezconfy
```

## Quick Start

Define a schema and a config file, then load them:

```python
from ezconfy import ConfigBuilder

cfg = ConfigBuilder.from_files(config_paths="config.yaml", schema_path="schema.yaml")
print(cfg.training.batch_size)  # validated, typed access
```

## Schema

A schema file describes the expected shape and types of your configuration. It can define custom types and the root structure:

```yaml
types:
  OptimizerType:
    - adam
    - sgd
    - rmsprop

schema:
  model:
    hidden_dims: list[int]
  training:
    batch_size: int = 32
    num_epochs: int = 10
    shuffle: bool = true
    dropout: float?
    optimizer: OptimizerType
```

### Supported type syntax

| Syntax | Meaning |
|---|---|
| `int`, `float`, `str`, `bool` | Primitive types |
| `type?` | Optional (defaults to `None`) |
| `type = value` | Type with default |
| `list[T]` | List of T |
| `A \| B` | Union type |
| `[a, b, c]` | Enum |
| `Child < Parent` | Model inheritance |
| `pathlib:Path` | External type (import path) |
| `/path/to/file.py:ClassName` | External type (file path) |

If no `types` are needed, the entire YAML is treated as the root schema (no `schema:` wrapper required).

## Object Instantiation

ezconfy can instantiate Python objects directly from config using `_target_type_`:

```yaml
dataset:
  _target_type_: mypackage.data:MyDataset
  _init_args_:
    num_classes: 100
    root: /data
```

Use `_init_method_` to call an alternative constructor (e.g. `from_pretrained`):

```yaml
encoder:
  _target_type_: mypackage.models:BertEncoder
  _init_method_: from_pretrained
  _init_args_:
    model_name: bert-base-uncased
```

## Placeholder Injection

Reference other config values with `${key}`. Supports attribute access and method calls:

```yaml
num_classes: 10

dataset:
  _target_type_: mypackage.data:MyDataset
  _init_args_:
    num_classes: ${num_classes}   # scalar reference

model:
  _target_type_: mypackage.models:Classifier
  _init_args_:
    in_features: ${dataset.num_classes}   # attribute access
    params: ${encoder.parameters()}       # method call
```

Objects are instantiated in topological order based on their dependencies, so forward references work automatically.

## Multi-file Configs & Overrides

Pass multiple files — they are deep-merged in order (later files win on conflicts):

```python
cfg = ConfigBuilder.from_files(config_paths=["base.yaml", "experiment.yaml"])
```

Apply programmatic overrides on top:

```python
cfg = ConfigBuilder.from_files(
    config_paths="config.yaml",
    overrides={"training": {"batch_size": 64}},
)
```

## Code Generation CLI

Generate a Pydantic model file from a schema:

```bash
ezconfy generate schema.yaml output.py
```

This produces a standalone `.py` file with `BaseModel` classes matching the schema, useful for editor autocompletion and static analysis.

## Requirements

- Python 3.11+
