Skip to content

Commit

Permalink
Merge pull request #30 from Kilo59/refactor#28
Browse files Browse the repository at this point in the history
refactor Timeline class to pydantic model
  • Loading branch information
Kilo59 authored Sep 14, 2020
2 parents ba5050e + cf65e6e commit d954534
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 230 deletions.
301 changes: 152 additions & 149 deletions Pipfile.lock

Large diffs are not rendered by default.

21 changes: 19 additions & 2 deletions app/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""app.models.py"""
from typing import Dict, List

from pydantic import BaseModel
from pydantic import BaseModel, validator


class Latest(BaseModel):
Expand All @@ -27,9 +27,26 @@ class Timeline(BaseModel):
Timeline model.
"""

latest: int
timeline: Dict[str, int] = {}

@validator("timeline")
@classmethod
def sort_timeline(cls, value):
"""Sort the timeline history before inserting into the model"""
return dict(sorted(value.items()))

@property
def latest(self):
"""Get latest available history value."""
return list(self.timeline.values())[-1] if self.timeline else 0

def serialize(self):
"""
Serialize the model into dict
TODO: override dict() instead of using serialize
"""
return {**self.dict(), "latest": self.latest}


class Timelines(BaseModel):
"""
Expand Down
10 changes: 5 additions & 5 deletions app/services/location/jhu.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ...caches import check_cache, load_cache
from ...coordinates import Coordinates
from ...location import TimelinedLocation
from ...timeline import Timeline
from ...models import Timeline
from ...utils import countries
from ...utils import date as date_util
from ...utils import httputils
Expand Down Expand Up @@ -178,25 +178,25 @@ async def get_locations():
location["country"],
location["province"],
# Coordinates.
Coordinates(coordinates["lat"], coordinates["long"]),
Coordinates(latitude=coordinates["lat"], longitude=coordinates["long"]),
# Last update.
datetime.utcnow().isoformat() + "Z",
# Timelines (parse dates as ISO).
{
"confirmed": Timeline(
{
timeline={
datetime.strptime(date, "%m/%d/%y").isoformat() + "Z": amount
for date, amount in timelines["confirmed"].items()
}
),
"deaths": Timeline(
{
timeline={
datetime.strptime(date, "%m/%d/%y").isoformat() + "Z": amount
for date, amount in timelines["deaths"].items()
}
),
"recovered": Timeline(
{
timeline={
datetime.strptime(date, "%m/%d/%y").isoformat() + "Z": amount
for date, amount in timelines["recovered"].items()
}
Expand Down
8 changes: 4 additions & 4 deletions app/services/location/nyt.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from ...caches import check_cache, load_cache
from ...coordinates import Coordinates
from ...location.nyt import NYTLocation
from ...timeline import Timeline
from ...models import Timeline
from ...utils import httputils
from . import LocationService

Expand Down Expand Up @@ -119,18 +119,18 @@ async def get_locations():
last_updated=datetime.utcnow().isoformat() + "Z", # since last request
timelines={
"confirmed": Timeline(
{
timeline={
datetime.strptime(date, "%Y-%m-%d").isoformat() + "Z": amount
for date, amount in confirmed_history.items()
}
),
"deaths": Timeline(
{
timeline={
datetime.strptime(date, "%Y-%m-%d").isoformat() + "Z": amount
for date, amount in deaths_history.items()
}
),
"recovered": Timeline({}),
"recovered": Timeline(),
},
)
)
Expand Down
42 changes: 0 additions & 42 deletions app/timeline.py

This file was deleted.

24 changes: 12 additions & 12 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,44 @@ astroid==2.4.2
async-asgi-testclient==1.4.4
async-generator==1.10
asyncmock==0.4.2
attrs==19.3.0
attrs==20.2.0
bandit==1.6.2
black==19.10b0
certifi==2020.6.20
chardet==3.0.4
click==7.1.2
coverage==5.2.1
coveralls==2.1.1
coverage==5.3
coveralls==2.1.2
docopt==0.6.2
gitdb==4.0.5
gitpython==3.1.7
gitpython==3.1.8
idna==2.10
importlib-metadata==1.7.0 ; python_version < '3.8'
iniconfig==1.0.1
invoke==1.4.1
isort==4.3.21
isort==5.5.2
lazy-object-proxy==1.4.3
mccabe==0.6.1
mock==4.0.2
more-itertools==8.4.0
more-itertools==8.5.0
multidict==4.7.6
packaging==20.4
pathspec==0.8.0
pbr==5.4.5
pbr==5.5.0
pluggy==0.13.1
py==1.9.0
pylint==2.5.3
pylint==2.6.0
pyparsing==2.4.7
pytest-asyncio==0.14.0
pytest-cov==2.10.0
pytest==6.0.1
pytest-cov==2.10.1
pytest==6.0.2
pyyaml==5.3.1
regex==2020.7.14
requests==2.24.0
responses==0.10.15
responses==0.12.0
six==1.15.0
smmap==3.0.4
stevedore==3.2.0
stevedore==3.2.2
toml==0.10.1
typed-ast==1.4.1
urllib3[secure]==1.25.10 ; python_version >= '3.5'
Expand Down
12 changes: 6 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ aioredis==1.3.1
asgiref==3.2.10 ; python_version >= '3.5'
async-timeout==3.0.1
asyncache==0.1.1
attrs==19.3.0
attrs==20.2.0
cachetools==4.1.1
certifi==2020.6.20
cffi==1.14.1
cffi==1.14.2
chardet==3.0.4
click==7.1.2
cryptography==3.0
cryptography==3.1
dataclasses==0.6 ; python_version < '3.7'
fastapi==0.60.1
fastapi==0.61.1
gunicorn==20.0.4
h11==0.9.0
hiredis==1.1.0
Expand All @@ -29,8 +29,8 @@ pyopenssl==19.1.0
python-dateutil==2.8.1
python-dotenv==0.14.0
requests==2.24.0
scout-apm==2.15.2
sentry-sdk==0.16.2
scout-apm==2.16.1
sentry-sdk==0.17.4
six==1.15.0
starlette==0.13.6
urllib3[secure]==1.25.10 ; python_version >= '3.5'
Expand Down
4 changes: 2 additions & 2 deletions tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
def sort(ctx, targets="."):
"""Sort module imports."""
print("sorting imports ...")
args = ["isort", "-rc", "--atomic", targets]
args = ["isort", "--atomic", targets]
ctx.run(" ".join(args))


Expand All @@ -40,7 +40,7 @@ def check(ctx, fmt=False, sort=False, diff=False): # pylint: disable=redefined-
sort = True

fmt_args = ["black", "--check", "."]
sort_args = ["isort", "-rc", "--check", "."]
sort_args = ["isort", "--check", "."]

if diff:
fmt_args.append("--diff")
Expand Down
1 change: 0 additions & 1 deletion tests/test_countries.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from app.utils import countries


"""
Todo:
* Test cases for capturing of stdout/stderr
Expand Down
10 changes: 5 additions & 5 deletions tests/test_location.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pytest

from app import coordinates, location, timeline
from app import coordinates, location, models


def mocked_timeline(*args, **kwargs):
Expand All @@ -22,7 +22,7 @@ def __init__(self, latest):
(2, "Cruise Ship", "XX", "", 15, 100, 1000, 1111, 22222),
],
)
@mock.patch("app.timeline.Timeline", side_effect=mocked_timeline)
@mock.patch("app.models.Timeline", side_effect=mocked_timeline)
def test_location_class(
mocked_timeline,
test_id,
Expand All @@ -39,9 +39,9 @@ def test_location_class(
coords = coordinates.Coordinates(latitude=latitude, longitude=longitude)

# Timelines
confirmed = timeline.Timeline(confirmed_latest)
deaths = timeline.Timeline(deaths_latest)
recovered = timeline.Timeline(recovered_latest)
confirmed = models.Timeline(confirmed_latest)
deaths = models.Timeline(deaths_latest)
recovered = models.Timeline(recovered_latest)

# Date now.
now = datetime.utcnow().isoformat() + "Z"
Expand Down
4 changes: 2 additions & 2 deletions tests/test_timeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pytest

from app import timeline
from app import models


def test_timeline_class():
Expand All @@ -15,7 +15,7 @@ def test_timeline_class():
"1/23/20": 3,
}

history_data = timeline.Timeline(history=timeseries)
history_data = models.Timeline(timeline=timeseries)

# validate last value
assert history_data.latest == 7
Expand Down

0 comments on commit d954534

Please sign in to comment.