fix(ptu): refuse ptu_shares declared without ptu_count and cost_per_ptu_per_hour

This commit is contained in:
mateo-berri 2026-10-01 16:57:07 -07:00
parent f8425f3ba4
commit d2eda3adc0
3 changed files with 26 additions and 1 deletions

View file

@ -229,8 +229,11 @@ def ptu_config_error(model_info: Mapping[str, object], *, model_name: str | None
has_count: Final = model_info.get("ptu_count") is not None
has_rate: Final = model_info.get("cost_per_ptu_per_hour") is not None
if not has_count and not has_rate:
has_shares: Final = model_info.get("ptu_shares") is not None
if not has_count and not has_rate and not has_shares:
return None
if not has_count and not has_rate:
return _named("ptu_count and cost_per_ptu_per_hour are required when ptu_shares is set", model_name)
if has_count != has_rate:
return _named("ptu_count and cost_per_ptu_per_hour must be set together", model_name)
if effective_from is None:

View file

@ -439,6 +439,21 @@ def test_a_fractional_count_reserves_nothing():
assert ptu_terms({**_SHARED, "ptu_count": 100.5}) is None
@pytest.mark.parametrize(
"shares_only",
[
{"ptu_shares": {"team-a": 60, "team-b": 40}},
{"ptu_shares": {"team-a": 60, "team-b": 40}, "ptu_effective_from": "2026-01-01T00:00:00Z"},
],
ids=["shares alone", "shares with a window"],
)
def test_shares_without_the_count_and_rate_are_refused_instead_of_registering_unpriced(shares_only):
"""Shares split a count, so a split with no count has nothing to add up to and would register a
deployment the share filter and ceiling honour while flat cost never rolls up."""
assert ptu_config_error(shares_only) == "ptu_count and cost_per_ptu_per_hour are required when ptu_shares is set"
assert ptu_terms(shares_only) is None
def test_the_split_is_named_after_the_deployment_when_the_caller_supplies_one():
error = ptu_config_error({**_SHARED, "ptu_shares": {"team-a": 1}}, model_name="gpt-4.1-ptu")

View file

@ -1334,6 +1334,13 @@ def test_validate_helper_refuses_shares_that_do_not_add_up_to_the_count():
assert "4 of 5 allocated" in exc.value.detail
def test_validate_helper_refuses_shares_declared_without_a_count_and_rate():
with pytest.raises(HTTPException) as exc:
_validate_ptu_model_info({"ptu_shares": {"team-a": 3, "team-b": 2}, "ptu_effective_from": _SHARED_START})
assert exc.value.status_code == 400
assert exc.value.detail == "ptu_count and cost_per_ptu_per_hour are required when ptu_shares is set"
class _TeamLookup:
def __init__(self, existing: frozenset[str]) -> None:
self.existing: Final = existing