diff --git a/app/routers/v2.py b/app/routers/v2.py index 31eb408c..a7a14196 100644 --- a/app/routers/v2.py +++ b/app/routers/v2.py @@ -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 @@ -7,6 +9,7 @@ from ..models import LatestResponse, LocationResponse, LocationsResponse V2 = APIRouter() +metrics_provider = MetricsProvider() class Sources(str, enum.Enum): @@ -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 @@ -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 @@ -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") diff --git a/app/services/repo/metricsprovider.py b/app/services/repo/metricsprovider.py new file mode 100644 index 00000000..ab8c1892 --- /dev/null +++ b/app/services/repo/metricsprovider.py @@ -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)} \ No newline at end of file