diff --git a/app/main.py b/app/main.py index 44876182..f977622d 100644 --- a/app/main.py +++ b/app/main.py @@ -10,7 +10,6 @@ import uvicorn from fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware -from fastapi.middleware.wsgi import WSGIMiddleware from fastapi.responses import JSONResponse from .core import create_app @@ -18,7 +17,8 @@ from .models.latest import LatestResponse as Latest from .models.location import LocationResponse as Location from .models.location import LocationsResponse as Locations -from .router import router +from .router.v1 import router as v1router +from .router.v2 import router as v2router # ############ # FastAPI App @@ -83,11 +83,9 @@ async def handle_validation_error(request: Request, exc: pydantic.error_wrappers # Include routers. -APP.include_router(router, prefix="/v2", tags=["v2"]) +APP.include_router(v1router, prefix="", tags=["v1"]) +APP.include_router(v2router, prefix="/v2", tags=["v2"]) -# mount the existing Flask app -# v1 @ / -APP.mount("/", WSGIMiddleware(create_app())) # Running of app. if __name__ == "__main__": diff --git a/app/router/__init__.py b/app/router/__init__.py index eefb5f0a..e37fdd9f 100644 --- a/app/router/__init__.py +++ b/app/router/__init__.py @@ -1,7 +1,6 @@ from fastapi import APIRouter -# Create the router. -router = APIRouter() +from .v1 import all, confirmed, deaths, recovered # The routes. -from . import latest, sources, locations # isort:skip +from .v2 import latest, sources, locations # isort:skip diff --git a/app/router/v1/__init__.py b/app/router/v1/__init__.py new file mode 100644 index 00000000..af9233c5 --- /dev/null +++ b/app/router/v1/__init__.py @@ -0,0 +1,3 @@ +from fastapi import APIRouter + +router = APIRouter() diff --git a/app/router/v1/all.py b/app/router/v1/all.py new file mode 100644 index 00000000..e528ed5a --- /dev/null +++ b/app/router/v1/all.py @@ -0,0 +1,19 @@ +from ...services.location.jhu import get_category +from . import router + + +@router.get("/all") +def all(): + # Get all the categories. + confirmed = get_category("confirmed") + deaths = get_category("deaths") + recovered = get_category("recovered") + + return { + # Data. + "confirmed": confirmed, + "deaths": deaths, + "recovered": recovered, + # Latest. + "latest": {"confirmed": confirmed["latest"], "deaths": deaths["latest"], "recovered": recovered["latest"],}, + } diff --git a/app/router/v1/confirmed.py b/app/router/v1/confirmed.py new file mode 100644 index 00000000..0a8ab1c3 --- /dev/null +++ b/app/router/v1/confirmed.py @@ -0,0 +1,9 @@ +from ...services.location.jhu import get_category +from . import router + + +@router.get("/confirmed") +def confirmed(): + confirmed = get_category("confirmed") + + return confirmed diff --git a/app/router/v1/deaths.py b/app/router/v1/deaths.py new file mode 100644 index 00000000..b3d90413 --- /dev/null +++ b/app/router/v1/deaths.py @@ -0,0 +1,9 @@ +from ...services.location.jhu import get_category +from . import router + + +@router.get("/deaths") +def deaths(): + deaths = get_category("deaths") + + return deaths diff --git a/app/router/v1/recovered.py b/app/router/v1/recovered.py new file mode 100644 index 00000000..e9ae8f72 --- /dev/null +++ b/app/router/v1/recovered.py @@ -0,0 +1,9 @@ +from ...services.location.jhu import get_category +from . import router + + +@router.get("/recovered") +def recovered(): + recovered = get_category("recovered") + + return recovered diff --git a/app/router/v2/__init__.py b/app/router/v2/__init__.py new file mode 100644 index 00000000..af9233c5 --- /dev/null +++ b/app/router/v2/__init__.py @@ -0,0 +1,3 @@ +from fastapi import APIRouter + +router = APIRouter() diff --git a/app/router/latest.py b/app/router/v2/latest.py similarity index 86% rename from app/router/latest.py rename to app/router/v2/latest.py index 81b254cf..8e2e561b 100644 --- a/app/router/latest.py +++ b/app/router/v2/latest.py @@ -1,7 +1,7 @@ from fastapi import Request -from ..enums.sources import Sources -from ..models.latest import LatestResponse as Latest +from ...enums.sources import Sources +from ...models.latest import LatestResponse as Latest from . import router diff --git a/app/router/locations.py b/app/router/v2/locations.py similarity index 92% rename from app/router/locations.py rename to app/router/v2/locations.py index af4b1cfd..2fde5c9e 100644 --- a/app/router/locations.py +++ b/app/router/v2/locations.py @@ -1,8 +1,8 @@ from fastapi import HTTPException, Request -from ..enums.sources import Sources -from ..models.location import LocationResponse as Location -from ..models.location import LocationsResponse as Locations +from ...enums.sources import Sources +from ...models.location import LocationResponse as Location +from ...models.location import LocationsResponse as Locations from . import router diff --git a/app/router/sources.py b/app/router/v2/sources.py similarity index 85% rename from app/router/sources.py rename to app/router/v2/sources.py index 538921f4..4ade2fef 100644 --- a/app/router/sources.py +++ b/app/router/v2/sources.py @@ -1,4 +1,4 @@ -from ..data import data_sources +from ...data import data_sources from . import router diff --git a/app/routes/__init__.py b/app/routes/__init__.py deleted file mode 100644 index 2a584490..00000000 --- a/app/routes/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -""" -app.routes - -isort:skip_file -""" -from flask import Blueprint, redirect, request, abort, current_app as app -from ..data import data_source - -# Follow the import order to avoid circular dependency -api_v1 = Blueprint("api_v1", __name__, url_prefix="") - -# API version 1. -from .v1 import confirmed, deaths, recovered, all diff --git a/app/routes/v1/__init__.py b/app/routes/v1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/app/routes/v1/all.py b/app/routes/v1/all.py deleted file mode 100644 index 9638c4bd..00000000 --- a/app/routes/v1/all.py +++ /dev/null @@ -1,23 +0,0 @@ -from flask import jsonify - -from ...routes import api_v1 as api -from ...services.location.jhu import get_category - - -@api.route("/all") -def all(): - # Get all the categories. - confirmed = get_category("confirmed") - deaths = get_category("deaths") - recovered = get_category("recovered") - - return jsonify( - { - # Data. - "confirmed": confirmed, - "deaths": deaths, - "recovered": recovered, - # Latest. - "latest": {"confirmed": confirmed["latest"], "deaths": deaths["latest"], "recovered": recovered["latest"],}, - } - ) diff --git a/app/routes/v1/confirmed.py b/app/routes/v1/confirmed.py deleted file mode 100644 index 85cfe039..00000000 --- a/app/routes/v1/confirmed.py +++ /dev/null @@ -1,9 +0,0 @@ -from flask import jsonify - -from ...routes import api_v1 as api -from ...services.location.jhu import get_category - - -@api.route("/confirmed") -def confirmed(): - return jsonify(get_category("confirmed")) diff --git a/app/routes/v1/deaths.py b/app/routes/v1/deaths.py deleted file mode 100644 index cb65874b..00000000 --- a/app/routes/v1/deaths.py +++ /dev/null @@ -1,9 +0,0 @@ -from flask import jsonify - -from ...routes import api_v1 as api -from ...services.location.jhu import get_category - - -@api.route("/deaths") -def deaths(): - return jsonify(get_category("deaths")) diff --git a/app/routes/v1/recovered.py b/app/routes/v1/recovered.py deleted file mode 100644 index be5fe646..00000000 --- a/app/routes/v1/recovered.py +++ /dev/null @@ -1,9 +0,0 @@ -from flask import jsonify - -from ...routes import api_v1 as api -from ...services.location.jhu import get_category - - -@api.route("/recovered") -def recovered(): - return jsonify(get_category("recovered")) diff --git a/tests/test_routes.py b/tests/test_routes.py index 9e1c03ef..48d804e5 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -6,8 +6,8 @@ import pytest from fastapi.testclient import TestClient -import app -from app import services +# import app +# from app import services from app.main import APP from .test_jhu import DATETIME_STRING, mocked_requests_get, mocked_strptime_isoformat @@ -22,11 +22,7 @@ class FlaskRoutesTest(unittest.TestCase): Store all integration testcases in one class to ensure app context """ - # load app context only once. - app = app.create_app() - def setUp(self): - self.client = FlaskRoutesTest.app.test_client() self.asgi_client = TestClient(APP) self.date = DATETIME_STRING @@ -48,36 +44,36 @@ def test_v1_confirmed(self, mock_request_get, mock_datetime): mock_datetime.strptime.side_effect = mocked_strptime_isoformat state = "confirmed" expected_json_output = self.read_file_v1(state=state) - return_data = self.client.get("/{}".format(state)).data.decode() + return_data = self.asgi_client.get("/{}".format(state)).json() - assert return_data == expected_json_output + assert return_data == json.loads(expected_json_output) def test_v1_deaths(self, mock_request_get, mock_datetime): mock_datetime.utcnow.return_value.isoformat.return_value = self.date mock_datetime.strptime.side_effect = mocked_strptime_isoformat state = "deaths" expected_json_output = self.read_file_v1(state=state) - return_data = self.client.get("/{}".format(state)).data.decode() + return_data = self.asgi_client.get("/{}".format(state)).json() - assert return_data == expected_json_output + assert return_data == json.loads(expected_json_output) def test_v1_recovered(self, mock_request_get, mock_datetime): mock_datetime.utcnow.return_value.isoformat.return_value = self.date mock_datetime.strptime.side_effect = mocked_strptime_isoformat state = "recovered" expected_json_output = self.read_file_v1(state=state) - return_data = self.client.get("/{}".format(state)).data.decode() + return_data = self.asgi_client.get("/{}".format(state)).json() - assert return_data == expected_json_output + assert return_data == json.loads(expected_json_output) def test_v1_all(self, mock_request_get, mock_datetime): mock_datetime.utcnow.return_value.isoformat.return_value = self.date mock_datetime.strptime.side_effect = mocked_strptime_isoformat state = "all" expected_json_output = self.read_file_v1(state=state) - return_data = self.client.get("/{}".format(state)).data.decode() - # print(return_data) - assert return_data == expected_json_output + return_data = self.asgi_client.get("/{}".format(state)).json() + + assert return_data == json.loads(expected_json_output) def test_v2_latest(self, mock_request_get, mock_datetime): mock_datetime.utcnow.return_value.isoformat.return_value = DATETIME_STRING