Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 12 additions & 42 deletions app/routers/v2.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
"""app.routers.v2"""
from typing import Any
from app.services.repo.metricsprovider import MetricsProvider
import enum

from fastapi import APIRouter, HTTPException, Request
Expand All @@ -7,6 +9,7 @@
from ..models import LatestResponse, LocationResponse, LocationsResponse

V2 = APIRouter()
metrics_provider = MetricsProvider()


class Sources(str, enum.Enum):
Expand All @@ -26,14 +29,7 @@ async def get_latest(
"""
Getting latest amount of total confirmed cases, deaths, and recoveries.
"""
locations = await request.state.source.get_all()
return {
"latest": {
"confirmed": sum(map(lambda location: location.confirmed, locations)),
"deaths": sum(map(lambda location: location.deaths, locations)),
"recovered": sum(map(lambda location: location.recovered, locations)),
}
}
return await metrics_provider.get_latest_global(request.state.source)


# pylint: disable=unused-argument,too-many-arguments,redefined-builtin
Expand All @@ -56,38 +52,13 @@ async def get_locations(
params.pop("source", None)
params.pop("timelines", None)

# Retrieve all the locations.
locations = await request.state.source.get_all()

# Attempt to filter out locations with properties matching the provided query params.
for key, value in params.items():
# Clean keys for security purposes.
key = key.lower()
value = value.lower().strip("__")

# Do filtering.
try:
locations = [
location
for location in locations
if str(getattr(location, key)).lower() == str(value)
]
except AttributeError:
pass
if not locations:
raise HTTPException(
404, detail=f"Source `{source}` does not have the desired location data.",
)

# Return final serialized data.
return {
"latest": {
"confirmed": sum(map(lambda location: location.confirmed, locations)),
"deaths": sum(map(lambda location: location.deaths, locations)),
"recovered": sum(map(lambda location: location.recovered, locations)),
},
"locations": [location.serialize(timelines) for location in locations],
}
# # Retrieve all the locations.
try:
return await metrics_provider.get_available_locations(request.state.source, params, timelines)
except Exception as err:
raise HTTPException(404, str(err))




# pylint: disable=invalid-name
Expand All @@ -98,8 +69,7 @@ async def get_location_by_id(
"""
Getting specific location by id.
"""
location = await request.state.source.get(id)
return {"location": location.serialize(timelines)}
return await metrics_provider.get_location_by_id(request.state.source, id, timelines)


@V2.get("/sources")
Expand Down
57 changes: 57 additions & 0 deletions app/services/repo/metricsprovider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
class MetricsProvider():
"""
Gets latest global metrics from the given source
"""
async def get_latest_global(self, source):
locations = await source.get_all()
return {
"latest": {
"confirmed": sum(map(lambda location: location.confirmed, locations)),
"deaths": sum(map(lambda location: location.deaths, locations)),
"recovered": sum(map(lambda location: location.recovered, locations)),
}
}

"""
Gets the available locations for a given source, params and with timeline (if requested)
"""
async def get_available_locations(self, source, params, timelines):
# Retrieve all the locations.
locations = await source.get_all()

# Attempt to filter out locations with properties matching the provided query params.
for key, value in params.items():
# Clean keys for security purposes.
key = key.lower()
value = value.lower().strip("__")

# Do filtering.
try:
locations = [
location
for location in locations
if str(getattr(location, key)).lower() == str(value)
]
except AttributeError:
pass
if not locations:
raise Exception(
detail=f"Source `{source}` does not have the desired location data.",
)

# Return final serialized data.
return {
"latest": {
"confirmed": sum(map(lambda location: location.confirmed, locations)),
"deaths": sum(map(lambda location: location.deaths, locations)),
"recovered": sum(map(lambda location: location.recovered, locations)),
},
"locations": [location.serialize(timelines) for location in locations],
}

"""
Gets the location data by id
"""
async def get_location_by_id(self, source, id, timelines):
location = await source.get(id)
return {"location": location.serialize(timelines)}