Skip to content

Commit

Permalink
Add validation for overlapping date ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
larsks committed May 17, 2024
1 parent bbff235 commit 7319223
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 13 deletions.
21 changes: 21 additions & 0 deletions src/nerc_rates/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,27 @@ class RateItem(Base):
name: str
history: list[RateValue]

@pydantic.model_validator(mode="after")
@classmethod
def validate_no_overlap(cls, data: Self):
for x in data.history:
for y in data.history:
if x is not y:
if (
(x.date_until is None and y.date_until is None)
or (
y.date_from >= x.date_from
and (x.date_until and y.date_from <= x.date_until)
)
or (
y.date_from <= x.date_from
and (y.date_until and y.date_until >= x.date_from)
)
):
raise ValueError("date ranges overlap")

return data


RateItemDict = Annotated[
dict[str, RateItem],
Expand Down
60 changes: 47 additions & 13 deletions src/nerc_rates/tests/test_rates.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest
import requests_mock

from nerc_rates import load_from_url, rates
from nerc_rates import load_from_url, rates, models


def test_load_from_url():
Expand All @@ -17,18 +17,52 @@ def test_load_from_url():
assert r.get_value_at("CPU SU Rate", "2023-06") == "0.013"


def test_invalid_dates():
mock_response_text = """
- name: CPU SU Rate
history:
- value: "0.013"
from: 2023-06
until: 2023-04
"""
with requests_mock.Mocker() as m:
m.get(rates.DEFAULT_URL, text=mock_response_text)
with pytest.raises(ValueError):
load_from_url()
def test_invalid_date_order():
rate = ({"value": "1", "from": "2020-04", "until": "2020-03"},)
with pytest.raises(ValueError):
models.RateValue.model_validate(rate)


@pytest.mark.parametrize(
"rate",
[
# Two values with no end date
{
"name": "Test Rate",
"history": [
{"value": "1", "from": "2020-01"},
{"value": "2", "from": "2020-03"},
],
},
# Second value overlaps first value at end
{
"name": "Test Rate",
"history": [
{"value": "1", "from": "2020-01", "until": "2020-04"},
{"value": "2", "from": "2020-03"},
],
},
# Second value overlaps first value at start
{
"name": "Test Rate",
"history": [
{"value": "1", "from": "2020-04", "until": "2020-06"},
{"value": "2", "from": "2020-03", "until": "2020-05"},
],
},
# Second value is contained by first value
{
"name": "Test Rate",
"history": [
{"value": "1", "from": "2020-01", "until": "2020-06"},
{"value": "2", "from": "2020-03", "until": "2020-05"},
],
},
],
)
def test_invalid_date_overlap(rate):
with pytest.raises(ValueError):
models.RateItem.model_validate(rate)


def test_rates_get_value_at():
Expand Down

0 comments on commit 7319223

Please sign in to comment.