Skip to content

Commit 05001f9

Browse files
committed
refactor Timeline class to pydantic model
1 parent 464453d commit 05001f9

File tree

7 files changed

+36
-61
lines changed

7 files changed

+36
-61
lines changed

app/models.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""app.models.py"""
22
from typing import Dict, List
33

4-
from pydantic import BaseModel
4+
from pydantic import BaseModel, validator
55

66

77
class Latest(BaseModel):
@@ -27,8 +27,25 @@ class Timeline(BaseModel):
2727
Timeline model.
2828
"""
2929

30-
latest: int
31-
timeline: Dict[str, int] = {}
30+
timeline: Dict[str, int] = dict()
31+
32+
@validator("timeline")
33+
@classmethod
34+
def sort_timeline(cls, value):
35+
"""Sort the timeline history before inserting into the model"""
36+
return dict(sorted(value.items()))
37+
38+
@property
39+
def latest(self):
40+
"""Get latest available history value."""
41+
return list(self.timeline.values())[-1] if self.timeline else 0
42+
43+
def serialize(self):
44+
"""
45+
Serialize the model into dict
46+
TODO: override dict() instead of using serialize
47+
"""
48+
return {**self.dict(), "latest": self.latest}
3249

3350

3451
class Timelines(BaseModel):

app/services/location/csbs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,6 @@ async def get_locations():
9797
await load_cache(data_id, locations)
9898
except TypeError as type_err:
9999
LOGGER.error(type_err)
100-
100+
101101
# Return the locations.
102102
return locations

app/services/location/jhu.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from ...caches import check_cache, load_cache
1212
from ...coordinates import Coordinates
1313
from ...location import TimelinedLocation
14-
from ...timeline import Timeline
14+
from ...models import Timeline
1515
from ...utils import countries
1616
from ...utils import date as date_util
1717
from ...utils import httputils
@@ -175,18 +175,18 @@ async def get_locations():
175175
# Timelines (parse dates as ISO).
176176
{
177177
"confirmed": Timeline(
178-
{
178+
timeline={
179179
datetime.strptime(date, "%m/%d/%y").isoformat() + "Z": amount
180180
for date, amount in timelines["confirmed"].items()
181181
}
182182
),
183183
"deaths": Timeline(
184-
{
184+
timeline={
185185
datetime.strptime(date, "%m/%d/%y").isoformat() + "Z": amount
186186
for date, amount in timelines["deaths"].items()
187187
}
188188
),
189-
"recovered": Timeline({}),
189+
"recovered": Timeline(),
190190
},
191191
)
192192
)

app/services/location/nyt.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from ...caches import check_cache, load_cache
1010
from ...coordinates import Coordinates
1111
from ...location.nyt import NYTLocation
12-
from ...timeline import Timeline
12+
from ...models import Timeline
1313
from ...utils import httputils
1414
from . import LocationService
1515

@@ -119,18 +119,18 @@ async def get_locations():
119119
last_updated=datetime.utcnow().isoformat() + "Z", # since last request
120120
timelines={
121121
"confirmed": Timeline(
122-
{
122+
timeline={
123123
datetime.strptime(date, "%Y-%m-%d").isoformat() + "Z": amount
124124
for date, amount in confirmed_history.items()
125125
}
126126
),
127127
"deaths": Timeline(
128-
{
128+
timeline={
129129
datetime.strptime(date, "%Y-%m-%d").isoformat() + "Z": amount
130130
for date, amount in deaths_history.items()
131131
}
132132
),
133-
"recovered": Timeline({}),
133+
"recovered": Timeline(),
134134
},
135135
)
136136
)

app/timeline.py

Lines changed: 0 additions & 42 deletions
This file was deleted.

tests/test_location.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import pytest
55

6-
from app import coordinates, location, timeline
6+
from app import coordinates, location, models
77

88

99
def mocked_timeline(*args, **kwargs):
@@ -22,7 +22,7 @@ def __init__(self, latest):
2222
(2, "Cruise Ship", "XX", "", 15, 100, 1000, 1111, 22222),
2323
],
2424
)
25-
@mock.patch("app.timeline.Timeline", side_effect=mocked_timeline)
25+
@mock.patch("app.models.Timeline", side_effect=mocked_timeline)
2626
def test_location_class(
2727
mocked_timeline,
2828
test_id,
@@ -39,9 +39,9 @@ def test_location_class(
3939
coords = coordinates.Coordinates(latitude=latitude, longitude=longitude)
4040

4141
# Timelines
42-
confirmed = timeline.Timeline(confirmed_latest)
43-
deaths = timeline.Timeline(deaths_latest)
44-
recovered = timeline.Timeline(recovered_latest)
42+
confirmed = models.Timeline(confirmed_latest)
43+
deaths = models.Timeline(deaths_latest)
44+
recovered = models.Timeline(recovered_latest)
4545

4646
# Date now.
4747
now = datetime.utcnow().isoformat() + "Z"

tests/test_timeline.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import pytest
55

6-
from app import timeline
6+
from app import models
77

88

99
def test_timeline_class():
@@ -15,7 +15,7 @@ def test_timeline_class():
1515
"1/23/20": 3,
1616
}
1717

18-
history_data = timeline.Timeline(history=timeseries)
18+
history_data = models.Timeline(timeline=timeseries)
1919

2020
# validate last value
2121
assert history_data.latest == 7

0 commit comments

Comments
 (0)