| 1 |
"""`DlmTrainingConfig.weights` schema — validators + extras.""" |
| 2 |
|
| 3 |
from __future__ import annotations |
| 4 |
|
| 5 |
import pytest |
| 6 |
from pydantic import ValidationError |
| 7 |
|
| 8 |
from dlm.directives.schema import DlmTrainingConfig |
| 9 |
|
| 10 |
|
| 11 |
def test_weights_default_is_empty() -> None: |
| 12 |
cfg = DlmTrainingConfig() |
| 13 |
assert cfg.weights == {} |
| 14 |
|
| 15 |
|
| 16 |
def test_weights_accepts_positive_floats() -> None: |
| 17 |
cfg = DlmTrainingConfig(weights={"lang": {"py": 2.0, "rs": 0.5}}) |
| 18 |
assert cfg.weights["lang"]["py"] == 2.0 |
| 19 |
assert cfg.weights["lang"]["rs"] == 0.5 |
| 20 |
|
| 21 |
|
| 22 |
def test_weights_accepts_zero() -> None: |
| 23 |
"""Weight 0 drops the row — valid, not an error.""" |
| 24 |
cfg = DlmTrainingConfig(weights={"gen": {"true": 0.0}}) |
| 25 |
assert cfg.weights["gen"]["true"] == 0.0 |
| 26 |
|
| 27 |
|
| 28 |
def test_weights_rejects_negative() -> None: |
| 29 |
with pytest.raises(ValidationError) as exc: |
| 30 |
DlmTrainingConfig(weights={"gen": {"true": -1.0}}) |
| 31 |
assert "must be ≥ 0" in str(exc.value) |
| 32 |
|
| 33 |
|
| 34 |
def test_weights_rejects_negative_in_nested_entry() -> None: |
| 35 |
with pytest.raises(ValidationError): |
| 36 |
DlmTrainingConfig( |
| 37 |
weights={ |
| 38 |
"lang": {"py": 2.0, "rs": -0.5}, |
| 39 |
"gen": {"true": 1.0}, |
| 40 |
} |
| 41 |
) |
| 42 |
|
| 43 |
|
| 44 |
def test_weights_extra_fields_forbidden_at_config_level() -> None: |
| 45 |
"""The parent model forbids unknown keys — `weights` typo rejected.""" |
| 46 |
with pytest.raises(ValidationError): |
| 47 |
DlmTrainingConfig(wights={"lang": {"py": 2.0}}) # type: ignore[call-arg] |
| 48 |
|
| 49 |
|
| 50 |
def test_weights_frozen_after_construction() -> None: |
| 51 |
cfg = DlmTrainingConfig(weights={"lang": {"py": 2.0}}) |
| 52 |
with pytest.raises(ValidationError): |
| 53 |
cfg.weights = {} # type: ignore[misc] |