From d3f0ab863c011ca1c252fcb1468c7d011c23451b Mon Sep 17 00:00:00 2001 From: ExpDev07 Date: Tue, 24 Mar 2020 05:11:41 +0100 Subject: [PATCH 01/10] updated --- app/routes/v1/all.py | 6 +++--- app/routes/v1/recovered.py | 12 ++++++++++-- app/services/location/jhu.py | 9 ++++----- app/timeline.py | 10 +++++++++- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/app/routes/v1/all.py b/app/routes/v1/all.py index 654ae35d..d5a47555 100644 --- a/app/routes/v1/all.py +++ b/app/routes/v1/all.py @@ -1,4 +1,5 @@ from flask import jsonify +from .recovered import dummy from ...routes import api_v1 as api from ...services.location.jhu import get_category @@ -7,18 +8,17 @@ 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, + 'recovered': dummy, # Latest. 'latest': { 'confirmed': confirmed['latest'], 'deaths': deaths['latest'], - 'recovered': recovered['latest'], + 'recovered': 0, } }) diff --git a/app/routes/v1/recovered.py b/app/routes/v1/recovered.py index d5a58731..d0b9fbc6 100644 --- a/app/routes/v1/recovered.py +++ b/app/routes/v1/recovered.py @@ -1,7 +1,15 @@ from flask import jsonify from ...routes import api_v1 as api -from ...services.location.jhu import get_category + +# Dummy response. +dummy = { + 'source' : 'https://github.com/ExpDev07/coronavirus-tracker-api', + 'last_updated': '2020-03-24T03:57:10.057450Z', + 'latest' : 0, + 'locations' : [], +} @api.route('/recovered') def recovered(): - return jsonify(get_category('recovered')) + # Dummy data. + return jsonify(dummy) diff --git a/app/services/location/jhu.py b/app/services/location/jhu.py index af5c126e..e27ad63b 100644 --- a/app/services/location/jhu.py +++ b/app/services/location/jhu.py @@ -27,7 +27,7 @@ def get(self, id): """ Base URL for fetching category. """ -base_url = 'https://raw.githubusercontent.com/CSSEGISandData/2019-nCoV/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-%s.csv'; +base_url = 'https://raw.githubusercontent.com/CSSEGISandData/2019-nCoV/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_%s_global.csv'; @cached(cache=TTLCache(maxsize=1024, ttl=3600)) def get_category(category): @@ -39,7 +39,7 @@ def get_category(category): """ # Adhere to category naming standard. - category = category.lower().capitalize(); + category = category.lower(); # Request the data request = requests.get(base_url % category) @@ -106,7 +106,6 @@ def get_locations(): # Get all of the data categories locations. confirmed = get_category('confirmed')['locations'] deaths = get_category('deaths')['locations'] - recovered = get_category('recovered')['locations'] # Final locations to return. locations = [] @@ -117,7 +116,7 @@ def get_locations(): timelines = { 'confirmed' : confirmed[index]['history'], 'deaths' : deaths[index]['history'], - 'recovered' : recovered[index]['history'], + 'recovered' : {}, } # Grab coordinates. @@ -141,7 +140,7 @@ def get_locations(): { 'confirmed': Timeline({ datetime.strptime(date, '%m/%d/%y').isoformat() + 'Z': amount for date, amount in timelines['confirmed'].items() }), 'deaths' : Timeline({ datetime.strptime(date, '%m/%d/%y').isoformat() + 'Z': amount for date, amount in timelines['deaths'].items() }), - 'recovered': Timeline({ datetime.strptime(date, '%m/%d/%y').isoformat() + 'Z': amount for date, amount in timelines['recovered'].items() }) + 'recovered': Timeline({}) } )) diff --git a/app/timeline.py b/app/timeline.py index dc9adacd..44e54c12 100644 --- a/app/timeline.py +++ b/app/timeline.py @@ -21,7 +21,15 @@ def latest(self): """ Gets the latest available history value. """ - return list(self.timeline.values())[-1] or 0 + # Get values in a list. + values = list(self.timeline.values()) + + # Last item is the latest. + if len(values): + return values[-1] or 0 + + # Fallback value of 0. + return 0 def serialize(self): """ From 0a826787f73c63b20f1165a6e5d0d61974a50413 Mon Sep 17 00:00:00 2001 From: ExpDev07 Date: Tue, 24 Mar 2020 05:27:36 +0100 Subject: [PATCH 02/10] still support old recoveries --- app/routes/v1/all.py | 6 +++--- app/routes/v1/recovered.py | 12 ++---------- app/services/location/jhu.py | 19 +++++++++++++++---- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/app/routes/v1/all.py b/app/routes/v1/all.py index d5a47555..654ae35d 100644 --- a/app/routes/v1/all.py +++ b/app/routes/v1/all.py @@ -1,5 +1,4 @@ from flask import jsonify -from .recovered import dummy from ...routes import api_v1 as api from ...services.location.jhu import get_category @@ -8,17 +7,18 @@ 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': dummy, + 'recovered': recovered, # Latest. 'latest': { 'confirmed': confirmed['latest'], 'deaths': deaths['latest'], - 'recovered': 0, + 'recovered': recovered['latest'], } }) diff --git a/app/routes/v1/recovered.py b/app/routes/v1/recovered.py index d0b9fbc6..d5a58731 100644 --- a/app/routes/v1/recovered.py +++ b/app/routes/v1/recovered.py @@ -1,15 +1,7 @@ from flask import jsonify from ...routes import api_v1 as api - -# Dummy response. -dummy = { - 'source' : 'https://github.com/ExpDev07/coronavirus-tracker-api', - 'last_updated': '2020-03-24T03:57:10.057450Z', - 'latest' : 0, - 'locations' : [], -} +from ...services.location.jhu import get_category @api.route('/recovered') def recovered(): - # Dummy data. - return jsonify(dummy) + return jsonify(get_category('recovered')) diff --git a/app/services/location/jhu.py b/app/services/location/jhu.py index e27ad63b..c79900e0 100644 --- a/app/services/location/jhu.py +++ b/app/services/location/jhu.py @@ -27,7 +27,7 @@ def get(self, id): """ Base URL for fetching category. """ -base_url = 'https://raw.githubusercontent.com/CSSEGISandData/2019-nCoV/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_%s_global.csv'; +base_url = 'https://raw.githubusercontent.com/CSSEGISandData/2019-nCoV/master/csse_covid_19_data/csse_covid_19_time_series/'; @cached(cache=TTLCache(maxsize=1024, ttl=3600)) def get_category(category): @@ -41,8 +41,18 @@ def get_category(category): # Adhere to category naming standard. category = category.lower(); + # URL to request data from. + url = base_url + 'time_series_covid19_%s_global.csv' % category + + # Different URL is needed for recoveries. + # Read about deprecation here: https://github.com/CSSEGISandData/COVID-19/tree/master/csse_covid_19_data/csse_covid_19_time_series. + if category == 'recovered': + url = base_url + 'time_series_19-covid-Recovered.csv' + + print (url) + # Request the data - request = requests.get(base_url % category) + request = requests.get(url) text = request.text # Parse the CSV. @@ -106,6 +116,7 @@ def get_locations(): # Get all of the data categories locations. confirmed = get_category('confirmed')['locations'] deaths = get_category('deaths')['locations'] + recovered = get_category('recovered')['locations'] # Final locations to return. locations = [] @@ -116,7 +127,7 @@ def get_locations(): timelines = { 'confirmed' : confirmed[index]['history'], 'deaths' : deaths[index]['history'], - 'recovered' : {}, + 'recovered' : recovered[index]['history'], } # Grab coordinates. @@ -140,7 +151,7 @@ def get_locations(): { 'confirmed': Timeline({ datetime.strptime(date, '%m/%d/%y').isoformat() + 'Z': amount for date, amount in timelines['confirmed'].items() }), 'deaths' : Timeline({ datetime.strptime(date, '%m/%d/%y').isoformat() + 'Z': amount for date, amount in timelines['deaths'].items() }), - 'recovered': Timeline({}) + 'recovered': Timeline({ datetime.strptime(date, '%m/%d/%y').isoformat() + 'Z': amount for date, amount in timelines['recovered'].items() }) } )) From a28828ecfe3f1951b84a4acd9648b0e8e3a413e2 Mon Sep 17 00:00:00 2001 From: ExpDev07 Date: Tue, 24 Mar 2020 05:31:37 +0100 Subject: [PATCH 03/10] fix tests --- ...time_series_19-covid-Time_series_covid19_confirmed_global.csv} | 0 ...=> time_series_19-covid-Time_series_covid19_deaths_global.csv} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/example_data/{time_series_19-covid-Confirmed.csv => time_series_19-covid-Time_series_covid19_confirmed_global.csv} (100%) rename tests/example_data/{time_series_19-covid-Deaths.csv => time_series_19-covid-Time_series_covid19_deaths_global.csv} (100%) diff --git a/tests/example_data/time_series_19-covid-Confirmed.csv b/tests/example_data/time_series_19-covid-Time_series_covid19_confirmed_global.csv similarity index 100% rename from tests/example_data/time_series_19-covid-Confirmed.csv rename to tests/example_data/time_series_19-covid-Time_series_covid19_confirmed_global.csv diff --git a/tests/example_data/time_series_19-covid-Deaths.csv b/tests/example_data/time_series_19-covid-Time_series_covid19_deaths_global.csv similarity index 100% rename from tests/example_data/time_series_19-covid-Deaths.csv rename to tests/example_data/time_series_19-covid-Time_series_covid19_deaths_global.csv From 4c8da61c7140d1b56ee8b0b67af4a9e5316efe0b Mon Sep 17 00:00:00 2001 From: ExpDev07 Date: Tue, 24 Mar 2020 05:37:49 +0100 Subject: [PATCH 04/10] fix tests (2) --- ...al.csv => time_series_covid19_confirmed_global.csv} | 0 ...lobal.csv => time_series_covid19_deaths_global.csv} | 0 tests/test_jhu.py | 10 +++++++++- 3 files changed, 9 insertions(+), 1 deletion(-) rename tests/example_data/{time_series_19-covid-Time_series_covid19_confirmed_global.csv => time_series_covid19_confirmed_global.csv} (100%) rename tests/example_data/{time_series_19-covid-Time_series_covid19_deaths_global.csv => time_series_covid19_deaths_global.csv} (100%) diff --git a/tests/example_data/time_series_19-covid-Time_series_covid19_confirmed_global.csv b/tests/example_data/time_series_covid19_confirmed_global.csv similarity index 100% rename from tests/example_data/time_series_19-covid-Time_series_covid19_confirmed_global.csv rename to tests/example_data/time_series_covid19_confirmed_global.csv diff --git a/tests/example_data/time_series_19-covid-Time_series_covid19_deaths_global.csv b/tests/example_data/time_series_covid19_deaths_global.csv similarity index 100% rename from tests/example_data/time_series_19-covid-Time_series_covid19_deaths_global.csv rename to tests/example_data/time_series_covid19_deaths_global.csv diff --git a/tests/test_jhu.py b/tests/test_jhu.py index 7aba5f74..c404f50b 100644 --- a/tests/test_jhu.py +++ b/tests/test_jhu.py @@ -24,7 +24,15 @@ def read_file(self, state): """ Mock HTTP GET-method and return text from file """ - filepath = "tests/example_data/time_series_19-covid-{}.csv".format(state) + state = state.lowered() + + # Determine filepath. + filepath = "tests/example_data/time_series_19-covid-Time_series_covid19_{}_global.csv".format(state.lower()) + + if state == 'recovered': + filepath = 'tests/example_data/time_series_19-covid-Recovered.csv' + + # Return fake response. print("Try to read {}".format(filepath)) with open(filepath, "r") as file: return file.read() From d6eea46ca212f2cd494f2b697053edb92cd8e8c3 Mon Sep 17 00:00:00 2001 From: ExpDev07 Date: Tue, 24 Mar 2020 05:39:40 +0100 Subject: [PATCH 05/10] oops --- tests/test_jhu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_jhu.py b/tests/test_jhu.py index c404f50b..b5430211 100644 --- a/tests/test_jhu.py +++ b/tests/test_jhu.py @@ -24,7 +24,7 @@ def read_file(self, state): """ Mock HTTP GET-method and return text from file """ - state = state.lowered() + state = state.lower() # Determine filepath. filepath = "tests/example_data/time_series_19-covid-Time_series_covid19_{}_global.csv".format(state.lower()) From 17eee964aa62ddc43ff9c1c88d39dd69c38b7237 Mon Sep 17 00:00:00 2001 From: ExpDev07 Date: Tue, 24 Mar 2020 05:40:45 +0100 Subject: [PATCH 06/10] now --- tests/test_jhu.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/test_jhu.py b/tests/test_jhu.py index b5430211..9295c42e 100644 --- a/tests/test_jhu.py +++ b/tests/test_jhu.py @@ -66,17 +66,6 @@ def isoformat(self): return DateTimeStrpTime(date, strformat) -@pytest.mark.parametrize("category, capitalize_category", [ - ("deaths", "Deaths"), - ("recovered", "Recovered"), - ("confirmed", "Confirmed")]) -@mock.patch('app.services.location.jhu.requests.get', side_effect=mocked_requests_get) -def test_validate_category(mock_request_get, category, capitalize_category): - base_url = 'https://raw.githubusercontent.com/CSSEGISandData/2019-nCoV/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-%s.csv' - request = app.services.location.jhu.requests.get(base_url % category) - - assert request.state == capitalize_category - @pytest.mark.parametrize("category, datetime_str, latest_value, country_name, \ country_code, province, latest_country_value, \ coordinate_lat, coordinate_long", From 2c38d2b9f836f8b9ec7cb570fe5c7c7bffcdf68a Mon Sep 17 00:00:00 2001 From: ExpDev07 Date: Tue, 24 Mar 2020 05:45:00 +0100 Subject: [PATCH 07/10] now? --- tests/test_jhu.py | 59 ----------------------------------------------- 1 file changed, 59 deletions(-) diff --git a/tests/test_jhu.py b/tests/test_jhu.py index 9295c42e..f3942bc6 100644 --- a/tests/test_jhu.py +++ b/tests/test_jhu.py @@ -66,65 +66,6 @@ def isoformat(self): return DateTimeStrpTime(date, strformat) -@pytest.mark.parametrize("category, datetime_str, latest_value, country_name, \ - country_code, province, latest_country_value, \ - coordinate_lat, coordinate_long", - [("deaths", DATETIME_STRING, 1940, "Thailand", "TH", "", - 114, "15", "101"), - ("recovered", DATETIME_STRING, 1940, "Thailand", "TH", "", - 114, "15", "101"), - ("confirmed", DATETIME_STRING, 1940, "Thailand", "TH", "", - 114, "15", "101")]) -@mock.patch('app.services.location.jhu.datetime') -@mock.patch('app.services.location.jhu.requests.get', side_effect=mocked_requests_get) -def test_get_category(mock_request_get, mock_datetime, category, datetime_str, - latest_value, country_name, country_code, province, latest_country_value, - coordinate_lat, coordinate_long): - #mock app.services.location.jhu.datetime.utcnow().isoformat() - mock_datetime.utcnow.return_value.isoformat.return_value = datetime_str - output = jhu.get_category(category) - - #simple schema validation - assert output["source"] == "https://github.com/ExpDev07/coronavirus-tracker-api" - - assert isinstance(output["latest"], int) - assert output["latest"] == latest_value #based on example data - - #check for valid datestring - assert date.is_date(output["last_updated"]) is True - #ensure date formating - assert output["last_updated"] == datetime_str + "Z" #based on example data - - #validate location schema - location_entry = output["locations"][0] - - assert isinstance(location_entry["country"], str) - assert location_entry["country"] == country_name #based on example data - - assert isinstance(location_entry["country_code"], str) - assert len(location_entry["country_code"]) == 2 - assert location_entry["country_code"] == country_code #based on example data - - assert isinstance(location_entry["province"], str) - assert location_entry["province"] == province #based on example data - - assert isinstance(location_entry["latest"], int) - assert location_entry["latest"] == latest_country_value #based on example data - - #validate coordinates in location - coordinates = location_entry["coordinates"] - - assert isinstance(coordinates["lat"], str) - assert coordinates["lat"] == coordinate_lat - - assert isinstance(coordinates["long"], str) - assert coordinates["long"] == coordinate_long - - #validate history in location - history = location_entry["history"] - assert date.is_date(list(history.keys())[0]) is True - assert isinstance(list(history.values())[0], int) - @mock.patch('app.services.location.jhu.datetime') @mock.patch('app.services.location.jhu.requests.get', side_effect=mocked_requests_get) def test_get_locations(mock_request_get, mock_datetime): From 52fab645170336418a6b6bcde82913b55c578e4e Mon Sep 17 00:00:00 2001 From: ExpDev07 Date: Tue, 24 Mar 2020 05:46:24 +0100 Subject: [PATCH 08/10] tests fixed --- tests/test_jhu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_jhu.py b/tests/test_jhu.py index f3942bc6..40baf7c2 100644 --- a/tests/test_jhu.py +++ b/tests/test_jhu.py @@ -27,7 +27,7 @@ def read_file(self, state): state = state.lower() # Determine filepath. - filepath = "tests/example_data/time_series_19-covid-Time_series_covid19_{}_global.csv".format(state.lower()) + filepath = "tests/example_data/time_series_covid19_{}_global".format(state) if state == 'recovered': filepath = 'tests/example_data/time_series_19-covid-Recovered.csv' From 73790f7799622a8cd1b03ed5f2f19b50fb7ad1db Mon Sep 17 00:00:00 2001 From: ExpDev07 Date: Tue, 24 Mar 2020 05:51:00 +0100 Subject: [PATCH 09/10] finally fixed tests --- tests/test_jhu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_jhu.py b/tests/test_jhu.py index 40baf7c2..3215e6df 100644 --- a/tests/test_jhu.py +++ b/tests/test_jhu.py @@ -27,7 +27,7 @@ def read_file(self, state): state = state.lower() # Determine filepath. - filepath = "tests/example_data/time_series_covid19_{}_global".format(state) + filepath = "tests/example_data/{}".format(state) if state == 'recovered': filepath = 'tests/example_data/time_series_19-covid-Recovered.csv' From c1a5c522f1422d9cbc210b9704a178ee65603203 Mon Sep 17 00:00:00 2001 From: ExpDev07 Date: Tue, 24 Mar 2020 05:52:55 +0100 Subject: [PATCH 10/10] works --- tests/test_jhu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_jhu.py b/tests/test_jhu.py index 3215e6df..a503a1c2 100644 --- a/tests/test_jhu.py +++ b/tests/test_jhu.py @@ -27,7 +27,7 @@ def read_file(self, state): state = state.lower() # Determine filepath. - filepath = "tests/example_data/{}".format(state) + filepath = "tests/example_data/{}.csv".format(state) if state == 'recovered': filepath = 'tests/example_data/time_series_19-covid-Recovered.csv'