From dd8c5c848723fbcbae47ef661b594891a91ef4e5 Mon Sep 17 00:00:00 2001 From: LeonLu2 Date: Sun, 19 Feb 2023 22:03:40 -0500 Subject: [PATCH 01/26] 1. add geo_value validator in _params 2. modified test_covidcast and test_delphi_epidata for server geo_value validation passing 3. add TODO for patch and mock part --- integrations/client/test_delphi_epidata.py | 41 ++++++++++------ integrations/server/test_covidcast.py | 57 +++++++++++++--------- requirements.api.txt | 1 + src/server/_params.py | 8 +++ 4 files changed, 69 insertions(+), 38 deletions(-) diff --git a/integrations/client/test_delphi_epidata.py b/integrations/client/test_delphi_epidata.py index 625d2859d..80b7be1aa 100644 --- a/integrations/client/test_delphi_epidata.py +++ b/integrations/client/test_delphi_epidata.py @@ -19,6 +19,14 @@ from delphi.epidata.acquisition.covidcast.test_utils import CovidcastBase import delphi.operations.secrets as secrets +# TODO replace these real geo_values with fake values, and use patch and mock to mock the return values of +# delphi_utils.geomap.GeoMapper().get_geo_values(geo_type) in parse_geo_sets() of _params.py + +global fips, msa # add two global lists of valid geo_values of these types to pass the validation in parse_geo_sets() of _params.py + +fips = ['04019', '19143', '29063'] # Example list of valid FIPS codes as strings +msa = ['40660', '44180', '48620'] # Example list of valid MSAs as strings + # py3tester coverage target __test_target__ = 'delphi.epidata.client.delphi_epidata' @@ -54,12 +62,12 @@ def test_covidcast(self): # insert placeholder data: three issues of one signal, one issue of another rows = [ - self._make_placeholder_row(issue=self.DEFAULT_ISSUE + i, value=i, lag=i)[0] + self._make_placeholder_row(geo_type='msa', geo_value=msa[0], issue=self.DEFAULT_ISSUE + i, value=i, lag=i)[0] for i in range(3) ] row_latest_issue = rows[-1] rows.append( - self._make_placeholder_row(signal="sig2")[0] + self._make_placeholder_row(geo_type='msa', geo_value=msa[0], signal="sig2")[0] ) self._insert_rows(rows) @@ -74,6 +82,7 @@ def test_covidcast(self): self.expected_from_row(rows[-1]) ] + self.maxDiff = None # check result self.assertEqual(response, { 'result': 1, @@ -223,10 +232,10 @@ def test_geo_value(self): # insert placeholder data: three counties, three MSAs N = 3 rows = [ - self._make_placeholder_row(geo_type="county", geo_value=str(i)*5, value=i)[0] + self._make_placeholder_row(geo_type="fips", geo_value=fips[i], value=i)[0] for i in range(N) ] + [ - self._make_placeholder_row(geo_type="msa", geo_value=str(i)*5, value=i*10)[0] + self._make_placeholder_row(geo_type="msa", geo_value=msa[i], value=i*10)[0] for i in range(N) ] self._insert_rows(rows) @@ -240,32 +249,32 @@ def fetch(geo): **self.params_from_row(rows[0], geo_value=geo) ) + self.maxDiff = None # test fetch all r = fetch('*') self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], counties) # test fetch a specific region - r = fetch('11111') + r = fetch('{}'.format(fips[0])) self.assertEqual(r['message'], 'success') - self.assertEqual(r['epidata'], [counties[1]]) + self.assertEqual(r['epidata'], [counties[0]]) # test fetch a specific yet not existing region r = fetch('55555') - self.assertEqual(r['message'], 'no results') + self.assertEqual(r['message'], 'invalid geo_value for the requested geo_type') # test fetch a multiple regions - r = fetch(['11111', '22222']) + r = fetch(['{}'.format(fips[0]), '{}'.format(fips[1])]) self.assertEqual(r['message'], 'success') - self.assertEqual(r['epidata'], [counties[1], counties[2]]) + self.assertEqual(r['epidata'], [counties[0], counties[1]]) # test fetch a multiple regions in another variant - r = fetch(['00000', '22222']) + r = fetch(['{}'.format(fips[0]), '{}'.format(fips[2])]) self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], [counties[0], counties[2]]) # test fetch a multiple regions but one is not existing - r = fetch(['11111', '55555']) - self.assertEqual(r['message'], 'success') - self.assertEqual(r['epidata'], [counties[1]]) + r = fetch(['{}'.format(fips[0]), '55555']) + self.assertEqual(r['message'], 'invalid geo_value for the requested geo_type') # test fetch a multiple regions but specify no region r = fetch([]) - self.assertEqual(r['message'], 'no results') + self.assertEqual(r['message'], 'invalid geo_value for the requested geo_type') def test_covidcast_meta(self): """Test that the covidcast_meta endpoint returns expected data.""" @@ -322,10 +331,10 @@ def test_async_epidata(self): # insert placeholder data: three counties, three MSAs N = 3 rows = [ - self._make_placeholder_row(geo_type="county", geo_value=str(i)*5, value=i)[0] + self._make_placeholder_row(geo_type="fips", geo_value=fips[i-1], value=i)[0] for i in range(N) ] + [ - self._make_placeholder_row(geo_type="msa", geo_value=str(i)*5, value=i*10)[0] + self._make_placeholder_row(geo_type="msa", geo_value=msa[i-1], value=i*10)[0] for i in range(N) ] self._insert_rows(rows) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index bcca3b199..3af32c00c 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -3,6 +3,8 @@ # standard library import json import unittest +# from unittest.mock import MagicMock +# from unittest.mock import patch # third party import mysql.connector @@ -15,6 +17,13 @@ # use the local instance of the Epidata API BASE_URL = 'http://delphi_web_epidata/epidata/api.php' +# TODO replace these real geo_values with fake values, and use patch and mock to mock the return values of +# delphi_utils.geomap.GeoMapper().get_geo_values(geo_type) in parse_geo_sets() of _params.py + +global fips, msa # add two global lists of valid geo_values of these types to pass the validation in parse_geo_sets() of _params.py + +fips = ['04019', '19143', '29063'] # Example list of valid FIPS codes as strings +msa = ['40660', '44180', '48620'] # Example list of valid MSAs as strings class CovidcastTests(CovidcastBase): @@ -35,17 +44,16 @@ def request_based_on_row(self, row, extract_response=lambda x: x.json(), **kwarg return response, expected def _insert_placeholder_set_one(self): - row, settings = self._make_placeholder_row() + row, settings = self._make_placeholder_row(geo_type='msa', geo_value=msa[0]) self._insert_rows([row]) return row def _insert_placeholder_set_two(self): rows = [ - self._make_placeholder_row(geo_type='county', geo_value=str(i)*5, value=i*1., stderr=i*10., sample_size=i*100.)[0] + self._make_placeholder_row(geo_type='msa', geo_value=msa[i-1], value=i*1., stderr=i*10., sample_size=i*100.)[0] for i in [1, 2, 3] ] + [ - # geo value intended to overlap with counties above - self._make_placeholder_row(geo_type='msa', geo_value=str(i-3)*5, value=i*1., stderr=i*10., sample_size=i*100.)[0] + self._make_placeholder_row(geo_type='fips', geo_value=fips[i-4], value=i*1., stderr=i*10., sample_size=i*100.)[0] for i in [4, 5, 6] ] self._insert_rows(rows) @@ -53,11 +61,11 @@ def _insert_placeholder_set_two(self): def _insert_placeholder_set_three(self): rows = [ - self._make_placeholder_row(geo_type='county', geo_value='11111', time_value=2000_01_01+i, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=2-i)[0] + self._make_placeholder_row(geo_type='msa', geo_value=msa[0], time_value=2000_01_01+i, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=2-i)[0] for i in [1, 2, 3] ] + [ # time value intended to overlap with 11111 above, with disjoint geo values - self._make_placeholder_row(geo_type='county', geo_value=str(i)*5, time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=5-i)[0] + self._make_placeholder_row(geo_type='msa', geo_value=str(i)*5, time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=5-i)[0] for i in [4, 5, 6] ] self._insert_rows(rows) @@ -65,11 +73,11 @@ def _insert_placeholder_set_three(self): def _insert_placeholder_set_four(self): rows = [ - self._make_placeholder_row(source='src1', signal=str(i)*5, value=i*1., stderr=i*10., sample_size=i*100.)[0] + self._make_placeholder_row(geo_type='msa', geo_value=msa[0], source='src1', signal=str(i)*5, value=i*1., stderr=i*10., sample_size=i*100.)[0] for i in [1, 2, 3] ] + [ # signal intended to overlap with the signal above - self._make_placeholder_row(source='src2', signal=str(i-3)*5, value=i*1., stderr=i*10., sample_size=i*100.)[0] + self._make_placeholder_row(geo_type='msa', geo_value=msa[0], source='src2', signal=str(i-3)*5, value=i*1., stderr=i*10., sample_size=i*100.)[0] for i in [4, 5, 6] ] self._insert_rows(rows) @@ -77,11 +85,11 @@ def _insert_placeholder_set_four(self): def _insert_placeholder_set_five(self): rows = [ - self._make_placeholder_row(time_value=2000_01_01, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03+i)[0] + self._make_placeholder_row(geo_type='msa', geo_value=msa[0], time_value=2000_01_01, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03+i)[0] for i in [1, 2, 3] ] + [ # different time_values, same issues - self._make_placeholder_row(time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03+i-3)[0] + self._make_placeholder_row(geo_type='msa', geo_value=msa[0], time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03+i-3)[0] for i in [4, 5, 6] ] self._insert_rows(rows) @@ -310,7 +318,7 @@ def test_signal_wildcard(self): }) def test_geo_value(self): - """test different variants of geo types: single, *, multi.""" + """test whether geo values are valid for specific geo types""" # insert placeholder data rows = self._insert_placeholder_set_two() @@ -324,28 +332,33 @@ def fetch(geo_value): return response + self.maxDiff = None # test fetch a specific region - r = fetch('11111') + r = fetch(msa[0]) self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], [expected_counties[0]]) + # test fetch a specific yet not existing region - r = fetch('55555') - self.assertEqual(r['message'], 'no results') + r = fetch('11111') + self.assertEqual(r['message'], 'invalid geo_value for the requested geo_type') + # test fetch multiple regions - r = fetch('11111,22222') + r = fetch('{},{}'.format(msa[0], msa[1])) self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], [expected_counties[0], expected_counties[1]]) + # test fetch multiple noncontiguous regions - r = fetch('11111,33333') + r = fetch('{},{}'.format(msa[0], msa[2])) self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], [expected_counties[0], expected_counties[2]]) + # test fetch multiple regions but one is not existing - r = fetch('11111,55555') - self.assertEqual(r['message'], 'success') - self.assertEqual(r['epidata'], [expected_counties[0]]) + r = fetch('{},11111'.format(msa[0])) + self.assertEqual(r['message'], 'invalid geo_value for the requested geo_type') + # test fetch empty region r = fetch('') - self.assertEqual(r['message'], 'no results') + self.assertEqual(r['message'], 'invalid geo_value for the requested geo_type') def test_location_timeline(self): """Select a timeline for a particular location.""" @@ -384,7 +397,7 @@ def test_nullable_columns(self): """Missing values should be surfaced as null.""" row, _ = self._make_placeholder_row( - stderr=None, sample_size=None, + geo_type='msa', geo_value=msa[0], stderr=None, sample_size=None, missing_stderr=Nans.OTHER.value, missing_sample_size=Nans.OTHER.value ) self._insert_rows([row]) @@ -405,7 +418,7 @@ def test_temporal_partitioning(self): # insert placeholder data rows = [ - self._make_placeholder_row(time_type=tt)[0] + self._make_placeholder_row(geo_type='msa', geo_value=msa[0], time_type=tt)[0] for tt in "hour day week month year".split() ] self._insert_rows(rows) diff --git a/requirements.api.txt b/requirements.api.txt index d5cc0e63b..36f18a752 100644 --- a/requirements.api.txt +++ b/requirements.api.txt @@ -1,3 +1,4 @@ +delphi_utils==0.3.6 epiweeks==2.1.2 Flask==2.2.2 itsdangerous<2.1 diff --git a/src/server/_params.py b/src/server/_params.py index d0b1cda6d..28d56da7e 100644 --- a/src/server/_params.py +++ b/src/server/_params.py @@ -2,6 +2,7 @@ import re from dataclasses import dataclass from typing import List, Optional, Sequence, Tuple, Union +import delphi_utils from flask import request @@ -460,14 +461,21 @@ def parse_source_signal_sets() -> List[SourceSignalSet]: def parse_geo_sets() -> List[GeoSet]: geo_type = request.values.get("geo_type") + if geo_type: # old version require_any(request, "geo_value", "geo_values", empty=True) geo_values = extract_strings(("geo_values", "geo_value")) if len(geo_values) == 1 and geo_values[0] == "*": return [GeoSet(geo_type, True)] + + for geo_value in geo_values: + if geo_value not in delphi_utils.geomap.GeoMapper().get_geo_values(geo_type): + raise ValidationFailedException("invalid geo_value for the requested geo_type") + return [GeoSet(geo_type, geo_values)] + if ":" not in request.values.get("geo", ""): raise ValidationFailedException("missing parameter: geo or (geo_type and geo_value[s])") From d024995153435a54ecac4c740dc3dc22a8e948b0 Mon Sep 17 00:00:00 2001 From: LeonLu2 Date: Thu, 23 Feb 2023 14:04:33 -0500 Subject: [PATCH 02/26] 1. minor comment change --- integrations/server/test_covidcast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index 3af32c00c..156056323 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -64,7 +64,7 @@ def _insert_placeholder_set_three(self): self._make_placeholder_row(geo_type='msa', geo_value=msa[0], time_value=2000_01_01+i, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=2-i)[0] for i in [1, 2, 3] ] + [ - # time value intended to overlap with 11111 above, with disjoint geo values + # time value intended to overlap with the time values above, with disjoint geo values self._make_placeholder_row(geo_type='msa', geo_value=str(i)*5, time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=5-i)[0] for i in [4, 5, 6] ] From 6ed27d92e963e31f1e30ea5fe0fa4bdb3ce5b1f6 Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Thu, 23 Feb 2023 19:18:32 -0500 Subject: [PATCH 03/26] Update integrations/server/test_covidcast.py Co-authored-by: melange396 --- integrations/server/test_covidcast.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index fdcf66689..e4412f3b0 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -3,8 +3,6 @@ # standard library from typing import Callable import unittest -# from unittest.mock import MagicMock -# from unittest.mock import patch # third party import mysql.connector From e89692e408aa6e161c9bc62d20f5400bc5ff035f Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Thu, 23 Feb 2023 19:20:19 -0500 Subject: [PATCH 04/26] Update integrations/server/test_covidcast.py Co-authored-by: melange396 --- integrations/server/test_covidcast.py | 1 - 1 file changed, 1 deletion(-) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index e4412f3b0..9e20e6bf9 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -315,7 +315,6 @@ def fetch(geo_value): return response - self.maxDiff = None # test fetch a specific region r = fetch(msa[0]) self.assertEqual(r['message'], 'success') From 14463c862f9c8f4d741567e9b9cb2e8288929027 Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Wed, 1 Mar 2023 23:46:31 -0500 Subject: [PATCH 05/26] Update integrations/client/test_delphi_epidata.py Co-authored-by: melange396 --- integrations/client/test_delphi_epidata.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/integrations/client/test_delphi_epidata.py b/integrations/client/test_delphi_epidata.py index 1b4aafa0b..2e9722940 100644 --- a/integrations/client/test_delphi_epidata.py +++ b/integrations/client/test_delphi_epidata.py @@ -20,8 +20,6 @@ # TODO replace these real geo_values with fake values, and use patch and mock to mock the return values of # delphi_utils.geomap.GeoMapper().get_geo_values(geo_type) in parse_geo_sets() of _params.py -global fips, msa # add two global lists of valid geo_values of these types to pass the validation in parse_geo_sets() of _params.py - fips = ['04019', '19143', '29063'] # Example list of valid FIPS codes as strings msa = ['40660', '44180', '48620'] # Example list of valid MSAs as strings From 3648a74d5fe18f3bf01ed97635f13580e6cddc5c Mon Sep 17 00:00:00 2001 From: LeonLu2 Date: Thu, 2 Mar 2023 21:13:31 -0500 Subject: [PATCH 06/26] 1. put the geo validation in GeoSet class constructor, and show which geo_value is invalid in the message 2. move the valid FIPS and MSA codes to test_utils.py, and import them when needed. 3. fix other failed places related to this change --- integrations/client/test_delphi_epidata.py | 40 ++++++------- integrations/server/test_covidcast.py | 55 +++++++----------- src/acquisition/covidcast/test_utils.py | 9 ++- src/server/_params.py | 17 +++++- .../covidcast/test_covidcast_row.py | 4 +- tests/server/test_params.py | 57 ++++++++++--------- tests/server/test_query.py | 13 +++-- 7 files changed, 98 insertions(+), 97 deletions(-) diff --git a/integrations/client/test_delphi_epidata.py b/integrations/client/test_delphi_epidata.py index 1b4aafa0b..fc2e16401 100644 --- a/integrations/client/test_delphi_epidata.py +++ b/integrations/client/test_delphi_epidata.py @@ -12,19 +12,10 @@ # third party import delphi.operations.secrets as secrets from delphi.epidata.acquisition.covidcast.covidcast_meta_cache_updater import main as update_covidcast_meta_cache -from delphi.epidata.acquisition.covidcast.test_utils import CovidcastBase, CovidcastTestRow +from delphi.epidata.acquisition.covidcast.test_utils import CovidcastBase, CovidcastTestRow, FIPS, MSA from delphi.epidata.client.delphi_epidata import Epidata from delphi_utils import Nans - -# TODO replace these real geo_values with fake values, and use patch and mock to mock the return values of -# delphi_utils.geomap.GeoMapper().get_geo_values(geo_type) in parse_geo_sets() of _params.py - -global fips, msa # add two global lists of valid geo_values of these types to pass the validation in parse_geo_sets() of _params.py - -fips = ['04019', '19143', '29063'] # Example list of valid FIPS codes as strings -msa = ['40660', '44180', '48620'] # Example list of valid MSAs as strings - # py3tester coverage target __test_target__ = 'delphi.epidata.client.delphi_epidata' # all the Nans we use here are just one value, so this is a shortcut to it: @@ -59,11 +50,11 @@ def test_covidcast(self): # insert placeholder data: three issues of one signal, one issue of another rows = [ - CovidcastTestRow.make_default_row(geo_type='msa', geo_value=msa[0], issue=2020_02_02 + i, value=i, lag=i) + CovidcastTestRow.make_default_row(issue=2020_02_02 + i, value=i, lag=i) for i in range(3) ] row_latest_issue = rows[-1] - rows.append(CovidcastTestRow.make_default_row(geo_type='msa', geo_value=msa[0], signal="sig2")) + rows.append(CovidcastTestRow.make_default_row(signal="sig2")) self._insert_rows(rows) with self.subTest(name='request two signals'): @@ -227,10 +218,10 @@ def test_geo_value(self): # insert placeholder data: three counties, three MSAs N = 3 rows = [ - CovidcastTestRow.make_default_row(geo_type="fips", geo_value=fips[i], value=i) + CovidcastTestRow.make_default_row(geo_type="fips", geo_value=FIPS[i], value=i) for i in range(N) ] + [ - CovidcastTestRow.make_default_row(geo_type="msa", geo_value=msa[i], value=i*10) + CovidcastTestRow.make_default_row(geo_type="msa", geo_value=MSA[i], value=i*10) for i in range(N) ] self._insert_rows(rows) @@ -250,26 +241,29 @@ def fetch(geo): self.assertEqual(request['message'], 'success') self.assertEqual(request['epidata'], counties) # test fetch a specific region - request = fetch('{}'.format(fips[0])) + request = fetch([FIPS[0]]) self.assertEqual(request['message'], 'success') self.assertEqual(request['epidata'], [counties[0]]) # test fetch a specific yet not existing region request = fetch('55555') - self.assertEqual(request['message'], 'invalid geo_value for the requested geo_type') + self.assertEqual(request['message'], 'Invalid geo_value(s) 55555 for the requested geo_type fips') # test fetch a multiple regions - request = fetch(['{}'.format(fips[0]), '{}'.format(fips[1])]) + request = fetch([FIPS[0], FIPS[1]]) self.assertEqual(request['message'], 'success') self.assertEqual(request['epidata'], [counties[0], counties[1]]) # test fetch a multiple regions in another variant - request = fetch(['{}'.format(fips[0]), '{}'.format(fips[2])]) + request = fetch([FIPS[0], FIPS[2]]) self.assertEqual(request['message'], 'success') self.assertEqual(request['epidata'], [counties[0], counties[2]]) # test fetch a multiple regions but one is not existing - request = fetch(['{}'.format(fips[0]), '55555']) - self.assertEqual(request['message'], 'invalid geo_value for the requested geo_type') + request = fetch([FIPS[0], '55555']) + self.assertEqual(request['message'], 'Invalid geo_value(s) 55555 for the requested geo_type fips') # test fetch a multiple regions but specify no region request = fetch([]) - self.assertEqual(request['message'], 'invalid geo_value for the requested geo_type') + self.assertEqual(request['message'], 'geo_value is empty for the requested geo_type fips!') + # test fetch a region with no results + request = fetch([FIPS[3]]) + self.assertEqual(request['message'], 'no results') def test_covidcast_meta(self): """Test that the covidcast_meta endpoint returns expected data.""" @@ -333,10 +327,10 @@ def test_async_epidata(self): # insert placeholder data: three counties, three MSAs N = 3 rows = [ - CovidcastTestRow.make_default_row(geo_type="fips", geo_value=fips[i-1], value=i) + CovidcastTestRow.make_default_row(geo_type="fips", geo_value=FIPS[i-1], value=i) for i in range(N) ] + [ - CovidcastTestRow.make_default_row(geo_type="msa", geo_value=msa[i-1], value=i*10) + CovidcastTestRow.make_default_row(geo_type="msa", geo_value=MSA[i-1], value=i*10) for i in range(N) ] self._insert_rows(rows) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index fdcf66689..89f8853d3 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -3,8 +3,6 @@ # standard library from typing import Callable import unittest -# from unittest.mock import MagicMock -# from unittest.mock import patch # third party import mysql.connector @@ -12,21 +10,12 @@ # first party from delphi_utils import Nans -from delphi.epidata.acquisition.covidcast.test_utils import CovidcastBase, CovidcastTestRow +from delphi.epidata.acquisition.covidcast.test_utils import CovidcastBase, CovidcastTestRow, FIPS, MSA from delphi.epidata.client.delphi_epidata import Epidata # use the local instance of the Epidata API BASE_URL = 'http://delphi_web_epidata/epidata/api.php' -# TODO replace these real geo_values with fake values, and use patch and mock to mock the return values of -# delphi_utils.geomap.GeoMapper().get_geo_values(geo_type) in parse_geo_sets() of _params.py - -global fips, msa # add two global lists of valid geo_values of these types to pass the validation in parse_geo_sets() of _params.py - -fips = ['04019', '19143', '29063'] # Example list of valid FIPS codes as strings -msa = ['40660', '44180', '48620'] # Example list of valid MSAs as strings - - class CovidcastTests(CovidcastBase): """Tests the `covidcast` endpoint.""" @@ -42,16 +31,16 @@ def request_based_on_row(self, row: CovidcastTestRow, **kwargs): return response def _insert_placeholder_set_one(self): - row = CovidcastTestRow.make_default_row(geo_type='msa', geo_value=msa[0]) + row = CovidcastTestRow.make_default_row() self._insert_rows([row]) return row def _insert_placeholder_set_two(self): rows = [ - CovidcastTestRow.make_default_row(geo_type='msa', geo_value=msa[i-1], value=i*1., stderr=i*10., sample_size=i*100.) + CovidcastTestRow.make_default_row(geo_type='msa', geo_value=MSA[i-1], value=i*1., stderr=i*10., sample_size=i*100.) for i in [1, 2, 3] ] + [ - CovidcastTestRow.make_default_row(geo_type='fips', geo_value=fips[i-4], value=i*1., stderr=i*10., sample_size=i*100.) + CovidcastTestRow.make_default_row(geo_type='fips', geo_value=FIPS[i-4], value=i*1., stderr=i*10., sample_size=i*100.) for i in [4, 5, 6] ] self._insert_rows(rows) @@ -59,11 +48,11 @@ def _insert_placeholder_set_two(self): def _insert_placeholder_set_three(self): rows = [ - CovidcastTestRow.make_default_row(geo_type='msa', geo_value=msa[0], time_value=2000_01_01+i, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=2-i) + CovidcastTestRow.make_default_row(geo_value=MSA[0], time_value=2000_01_01+i, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=2-i) for i in [1, 2, 3] ] + [ # time value intended to overlap with the time values above, with disjoint geo values - CovidcastTestRow.make_default_row(geo_type='msa', geo_value=str(i)*5, time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=5-i) + CovidcastTestRow.make_default_row(geo_value=str(i)*5, time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=5-i) for i in [4, 5, 6] ] self._insert_rows(rows) @@ -71,11 +60,11 @@ def _insert_placeholder_set_three(self): def _insert_placeholder_set_four(self): rows = [ - CovidcastTestRow.make_default_row(geo_type='msa', geo_value=msa[0], source='src1', signal=str(i)*5, value=i*1., stderr=i*10., sample_size=i*100.) + CovidcastTestRow.make_default_row(source='src1', signal=str(i)*5, value=i*1., stderr=i*10., sample_size=i*100.) for i in [1, 2, 3] ] + [ # signal intended to overlap with the signal above - CovidcastTestRow.make_default_row(geo_type='msa', geo_value=msa[0], source='src2', signal=str(i-3)*5, value=i*1., stderr=i*10., sample_size=i*100.) + CovidcastTestRow.make_default_row(source='src2', signal=str(i-3)*5, value=i*1., stderr=i*10., sample_size=i*100.) for i in [4, 5, 6] ] self._insert_rows(rows) @@ -83,11 +72,11 @@ def _insert_placeholder_set_four(self): def _insert_placeholder_set_five(self): rows = [ - CovidcastTestRow.make_default_row(geo_type='msa', geo_value=msa[0], time_value=2000_01_01, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03+i) + CovidcastTestRow.make_default_row(time_value=2000_01_01, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03+i) for i in [1, 2, 3] ] + [ # different time_values, same issues - CovidcastTestRow.make_default_row(geo_type='msa', geo_value=msa[0], time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03+i-3) + CovidcastTestRow.make_default_row(time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03+i-3) for i in [4, 5, 6] ] self._insert_rows(rows) @@ -317,30 +306,30 @@ def fetch(geo_value): return response - self.maxDiff = None # test fetch a specific region - r = fetch(msa[0]) + r = fetch(MSA[0]) self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], expected[0:1]) # test fetch a specific yet not existing region r = fetch('11111') - self.assertEqual(r['message'], 'invalid geo_value for the requested geo_type') - + self.assertEqual(r['message'], 'Invalid geo_value(s) 11111 for the requested geo_type msa') # test fetch multiple regions - r = fetch('{},{}'.format(msa[0], msa[1])) + r = fetch('{},{}'.format(MSA[0], MSA[1])) self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], expected[0:2]) # test fetch multiple noncontiguous regions - r = fetch('{},{}'.format(msa[0], msa[2])) + r = fetch('{},{}'.format(MSA[0], MSA[2])) self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], [expected[0], expected[2]]) # test fetch multiple regions but one is not existing - r = fetch('{},11111'.format(msa[0])) - self.assertEqual(r['message'], 'invalid geo_value for the requested geo_type') - + r = fetch('{},11111'.format(MSA[0])) + self.assertEqual(r['message'], 'Invalid geo_value(s) 11111 for the requested geo_type msa') # test fetch empty region r = fetch('') - self.assertEqual(r['message'], 'invalid geo_value for the requested geo_type') + self.assertEqual(r['message'], 'geo_value is empty for the requested geo_type msa!') + # test a region that has no results + r = fetch(MSA[3]) + self.assertEqual(r['message'], 'no results') def test_location_timeline(self): """Select a timeline for a particular location.""" @@ -377,7 +366,7 @@ def test_nullable_columns(self): """Missing values should be surfaced as null.""" row = CovidcastTestRow.make_default_row( - geo_type='msa', geo_value=msa[0], stderr=None, sample_size=None, + stderr=None, sample_size=None, missing_stderr=Nans.OTHER.value, missing_sample_size=Nans.OTHER.value ) self._insert_rows([row]) @@ -398,7 +387,7 @@ def test_temporal_partitioning(self): # insert placeholder data rows = [ - CovidcastTestRow.make_default_row(geo_type='msa', geo_value=msa[0], time_type=tt) + CovidcastTestRow.make_default_row(time_type=tt) for tt in "hour day week month year".split() ] self._insert_rows(rows) diff --git a/src/acquisition/covidcast/test_utils.py b/src/acquisition/covidcast/test_utils.py index 96db2c164..7d3613079 100644 --- a/src/acquisition/covidcast/test_utils.py +++ b/src/acquisition/covidcast/test_utils.py @@ -14,6 +14,11 @@ # all the Nans we use here are just one value, so this is a shortcut to it: nmv = Nans.NOT_MISSING.value +# TODO replace these real geo_values with fake values, and use patch and mock to mock the return values of +# delphi_utils.geomap.GeoMapper().get_geo_values(geo_type) in parse_geo_sets() of _params.py + +FIPS = ['04019', '19143', '29063', '36083'] # Example list of valid FIPS codes as strings +MSA = ['40660', '44180', '48620', '49420'] # Example list of valid MSA codes as strings class CovidcastTestRow(CovidcastRow): @staticmethod @@ -22,9 +27,9 @@ def make_default_row(**kwargs) -> "CovidcastTestRow": "source": "src", "signal": "sig", "time_type": "day", - "geo_type": "county", + "geo_type": "msa", "time_value": 2020_02_02, - "geo_value": "01234", + "geo_value": "40660", # a valid geo_value for msa "value": 10.0, "stderr": 10.0, "sample_size": 10.0, diff --git a/src/server/_params.py b/src/server/_params.py index 28d56da7e..4e9a941eb 100644 --- a/src/server/_params.py +++ b/src/server/_params.py @@ -54,6 +54,17 @@ class GeoSet: geo_type: str geo_values: Union[bool, Sequence[str]] + def __init__(self, geo_type: str, geo_values: Union[bool, Sequence[str]]): + if not isinstance(geo_values, bool): + if geo_values == ['']: + raise ValidationFailedException(f"geo_value is empty for the requested geo_type {geo_type}!") + allowed_values = delphi_utils.geomap.GeoMapper().get_geo_values(geo_type) + invalid_values = set(geo_values) - set(allowed_values) + if invalid_values: + raise ValidationFailedException(f"Invalid geo_value(s) {', '.join(invalid_values)} for the requested geo_type {geo_type}") + self.geo_type = geo_type + self.geo_values = geo_values + def matches(self, geo_type: str, geo_value: str) -> bool: return self.geo_type == geo_type and (self.geo_values is True or (not isinstance(self.geo_values, bool) and geo_value in self.geo_values)) @@ -469,9 +480,9 @@ def parse_geo_sets() -> List[GeoSet]: if len(geo_values) == 1 and geo_values[0] == "*": return [GeoSet(geo_type, True)] - for geo_value in geo_values: - if geo_value not in delphi_utils.geomap.GeoMapper().get_geo_values(geo_type): - raise ValidationFailedException("invalid geo_value for the requested geo_type") + # for geo_value in geo_values: + # if geo_value not in delphi_utils.geomap.GeoMapper().get_geo_values(geo_type): + # raise ValidationFailedException("invalid geo_value for the requested geo_type") return [GeoSet(geo_type, geo_values)] diff --git a/tests/acquisition/covidcast/test_covidcast_row.py b/tests/acquisition/covidcast/test_covidcast_row.py index 9462fd4ed..35e7d62ee 100644 --- a/tests/acquisition/covidcast/test_covidcast_row.py +++ b/tests/acquisition/covidcast/test_covidcast_row.py @@ -22,9 +22,9 @@ class TestCovidcastRows(unittest.TestCase): "source": ["src"] * 10, "signal": ["sig_base"] * 5 + ["sig_other"] * 5, "time_type": ["day"] * 10, - "geo_type": ["county"] * 10, + "geo_type": ["msa"] * 10, "time_value": [2021_05_01 + i for i in range(5)] * 2, - "geo_value": ["01234"] * 10, + "geo_value": ["40660"] * 10, "value": range(10), "stderr": [10.0] * 10, "sample_size": [10.0] * 10, diff --git a/tests/server/test_params.py b/tests/server/test_params.py index 177ff5cba..4ec3796df 100644 --- a/tests/server/test_params.py +++ b/tests/server/test_params.py @@ -28,6 +28,7 @@ from delphi.epidata.server._exceptions import ( ValidationFailedException, ) +from delphi.epidata.acquisition.covidcast.test_utils import FIPS, MSA # py3tester coverage target __test_target__ = "delphi.epidata.server._params" @@ -45,19 +46,19 @@ def setUp(self): def test_geo_set(self): with self.subTest("*"): - p = GeoSet("hrr", True) - self.assertTrue(p.matches("hrr", "any")) + p = GeoSet("fips", True) + self.assertTrue(p.matches("fips", "any")) self.assertFalse(p.matches("msa", "any")) with self.subTest("subset"): - p = GeoSet("hrr", ["a", "b"]) - self.assertTrue(p.matches("hrr", "a")) - self.assertTrue(p.matches("hrr", "b")) - self.assertFalse(p.matches("hrr", "c")) + p = GeoSet("fips", [FIPS[0], FIPS[1]]) + self.assertTrue(p.matches("fips", FIPS[0])) + self.assertTrue(p.matches("fips", FIPS[1])) + self.assertFalse(p.matches("fips", "c")) self.assertFalse(p.matches("msa", "any")) with self.subTest("count"): self.assertEqual(GeoSet("a", True).count(), inf) self.assertEqual(GeoSet("a", False).count(), 0) - self.assertEqual(GeoSet("a", ["a", "b"]).count(), 2) + self.assertEqual(GeoSet("fips", [FIPS[0], FIPS[1]]).count(), 2) def test_source_signal_set(self): with self.subTest("*"): @@ -89,43 +90,43 @@ def test_parse_geo_arg(self): with app.test_request_context("/"): self.assertEqual(parse_geo_arg(), []) with self.subTest("single"): - with app.test_request_context("/?geo=state:*"): - self.assertEqual(parse_geo_arg(), [GeoSet("state", True)]) - with app.test_request_context("/?geo=state:AK"): - self.assertEqual(parse_geo_arg(), [GeoSet("state", ["ak"])]) + with app.test_request_context("/?geo=fips:*"): + self.assertEqual(parse_geo_arg(), [GeoSet("fips", True)]) + with app.test_request_context("/?geo=fips:{}".format(FIPS[0])): + self.assertEqual(parse_geo_arg(), [GeoSet("fips", [FIPS[0]])]) with self.subTest("single list"): - with app.test_request_context("/?geo=state:AK,TK"): - self.assertEqual(parse_geo_arg(), [GeoSet("state", ["ak", "tk"])]) + with app.test_request_context("/?geo=fips:{},{}".format(FIPS[0], FIPS[1])): + self.assertEqual(parse_geo_arg(), [GeoSet("fips", [FIPS[0], FIPS[1]])]) with self.subTest("multi"): - with app.test_request_context("/?geo=state:*;nation:*"): - self.assertEqual(parse_geo_arg(), [GeoSet("state", True), GeoSet("nation", True)]) - with app.test_request_context("/?geo=state:AK;nation:US"): + with app.test_request_context("/?geo=fips:*;msa:*"): + self.assertEqual(parse_geo_arg(), [GeoSet("fips", True), GeoSet("msa", True)]) + with app.test_request_context("/?geo=fips:{};msa:{}".format(FIPS[0], MSA[0])): self.assertEqual( parse_geo_arg(), - [GeoSet("state", ["ak"]), GeoSet("nation", ["us"])], + [GeoSet("fips", [FIPS[0]]), GeoSet("msa", [MSA[0]])], ) - with app.test_request_context("/?geo=state:AK;state:KY"): + with app.test_request_context("/?geo=fips:{};fips:{}".format(FIPS[0], FIPS[1])): self.assertEqual( parse_geo_arg(), - [GeoSet("state", ["ak"]), GeoSet("state", ["ky"])], + [GeoSet("fips", [FIPS[0]]), GeoSet("fips", [FIPS[1]])], ) with self.subTest("multi list"): - with app.test_request_context("/?geo=state:AK,TK;county:42003,40556"): + with app.test_request_context("/?geo=fips:{},{};msa:{},{}".format(FIPS[0], FIPS[1], MSA[0], MSA[1])): self.assertEqual( parse_geo_arg(), [ - GeoSet("state", ["ak", "tk"]), - GeoSet("county", ["42003", "40556"]), + GeoSet("fips", [FIPS[0], FIPS[1]]), + GeoSet("msa", [MSA[0], MSA[1]]), ], ) with self.subTest("hybrid"): - with app.test_request_context("/?geo=nation:*;state:PA;county:42003,42002"): + with app.test_request_context("/?geo=nation:*;fips:{};msa:{},{}".format(FIPS[0], MSA[0], MSA[1])): self.assertEqual( parse_geo_arg(), [ GeoSet("nation", True), - GeoSet("state", ["pa"]), - GeoSet("county", ["42003", "42002"]), + GeoSet("fips", [FIPS[0]]), + GeoSet("msa", [MSA[0], MSA[1]]), ], ) @@ -140,10 +141,10 @@ def test_single_parse_geo_arg(self): with app.test_request_context("/"): self.assertRaises(ValidationFailedException, parse_single_geo_arg, "geo") with self.subTest("single"): - with app.test_request_context("/?geo=state:AK"): - self.assertEqual(parse_single_geo_arg("geo"), GeoSet("state", ["ak"])) + with app.test_request_context("/?geo=fips:{}".format(FIPS[0])): + self.assertEqual(parse_single_geo_arg("geo"), GeoSet("fips", [FIPS[0]])) with self.subTest("single list"): - with app.test_request_context("/?geo=state:AK,TK"): + with app.test_request_context("/?geo=fips:{},{}".format(FIPS[0], FIPS[1])): self.assertRaises(ValidationFailedException, parse_single_geo_arg, "geo") with self.subTest("multi"): with app.test_request_context("/?geo=state:*;nation:*"): diff --git a/tests/server/test_query.py b/tests/server/test_query.py index 53aca5621..ec07d3e8b 100644 --- a/tests/server/test_query.py +++ b/tests/server/test_query.py @@ -21,6 +21,7 @@ TimeSet, SourceSignalSet, ) +from delphi.epidata.acquisition.covidcast.test_utils import FIPS, MSA # py3tester coverage target __test_target__ = "delphi.epidata.server._query" @@ -145,17 +146,17 @@ def test_filter_geo_sets(self): with self.subTest("single"): params = {} self.assertEqual( - filter_geo_sets("t", "v", [GeoSet("state", ["KY"])], "p", params), + filter_geo_sets("t", "v", [GeoSet("fips", [FIPS[0]])], "p", params), "((t = :p_0t AND (v = :p_0t_0)))", ) - self.assertEqual(params, {"p_0t": "state", "p_0t_0": "KY"}) + self.assertEqual(params, {"p_0t": "fips", "p_0t_0": FIPS[0]}) with self.subTest("multi"): params = {} self.assertEqual( - filter_geo_sets("t", "v", [GeoSet("state", ["KY", "AK"])], "p", params), + filter_geo_sets("t", "v", [GeoSet("fips", [FIPS[0], FIPS[1]])], "p", params), "((t = :p_0t AND (v = :p_0t_0 OR v = :p_0t_1)))", ) - self.assertEqual(params, {"p_0t": "state", "p_0t_0": "KY", "p_0t_1": "AK"}) + self.assertEqual(params, {"p_0t": "fips", "p_0t_0": FIPS[0], "p_0t_1": FIPS[1]}) with self.subTest("multiple pairs"): params = {} self.assertEqual( @@ -175,7 +176,7 @@ def test_filter_geo_sets(self): filter_geo_sets( "t", "v", - [GeoSet("state", ["AK"]), GeoSet("nation", ["US"])], + [GeoSet("fips", [FIPS[0]]), GeoSet("msa", [MSA[0]])], "p", params, ), @@ -183,7 +184,7 @@ def test_filter_geo_sets(self): ) self.assertEqual( params, - {"p_0t": "state", "p_0t_0": "AK", "p_1t": "nation", "p_1t_0": "US"}, + {"p_0t": "fips", "p_0t_0": FIPS[0], "p_1t": "msa", "p_1t_0": MSA[0]}, ) def test_filter_source_signal_sets(self): From 9fe61962785a8072dd13b7cdc1b73f7827bce184 Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Sun, 19 Mar 2023 22:31:28 -0400 Subject: [PATCH 07/26] Update src/server/_params.py Co-authored-by: melange396 --- src/server/_params.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/server/_params.py b/src/server/_params.py index 4e9a941eb..bad572172 100644 --- a/src/server/_params.py +++ b/src/server/_params.py @@ -479,11 +479,6 @@ def parse_geo_sets() -> List[GeoSet]: geo_values = extract_strings(("geo_values", "geo_value")) if len(geo_values) == 1 and geo_values[0] == "*": return [GeoSet(geo_type, True)] - - # for geo_value in geo_values: - # if geo_value not in delphi_utils.geomap.GeoMapper().get_geo_values(geo_type): - # raise ValidationFailedException("invalid geo_value for the requested geo_type") - return [GeoSet(geo_type, geo_values)] From 6dac20429bc46207492706a58d60bd60aeb7f70d Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Sun, 19 Mar 2023 22:31:50 -0400 Subject: [PATCH 08/26] Update src/server/_params.py Co-authored-by: melange396 --- src/server/_params.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server/_params.py b/src/server/_params.py index bad572172..41f5ce494 100644 --- a/src/server/_params.py +++ b/src/server/_params.py @@ -481,7 +481,6 @@ def parse_geo_sets() -> List[GeoSet]: return [GeoSet(geo_type, True)] return [GeoSet(geo_type, geo_values)] - if ":" not in request.values.get("geo", ""): raise ValidationFailedException("missing parameter: geo or (geo_type and geo_value[s])") From 7b7b5e7d35d361fa9c961e062d59a50d2b57cc5a Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Sun, 19 Mar 2023 22:33:24 -0400 Subject: [PATCH 09/26] Update src/acquisition/covidcast/test_utils.py Co-authored-by: melange396 --- src/acquisition/covidcast/test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/acquisition/covidcast/test_utils.py b/src/acquisition/covidcast/test_utils.py index 7d3613079..551f145fe 100644 --- a/src/acquisition/covidcast/test_utils.py +++ b/src/acquisition/covidcast/test_utils.py @@ -29,7 +29,7 @@ def make_default_row(**kwargs) -> "CovidcastTestRow": "time_type": "day", "geo_type": "msa", "time_value": 2020_02_02, - "geo_value": "40660", # a valid geo_value for msa + "geo_value": MSA[0], "value": 10.0, "stderr": 10.0, "sample_size": 10.0, From 0a2bdf948c25c59402640aaca946c46da0839a63 Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Sun, 19 Mar 2023 22:33:40 -0400 Subject: [PATCH 10/26] Update integrations/client/test_delphi_epidata.py Co-authored-by: melange396 --- integrations/client/test_delphi_epidata.py | 1 - 1 file changed, 1 deletion(-) diff --git a/integrations/client/test_delphi_epidata.py b/integrations/client/test_delphi_epidata.py index fc2e16401..0c8c3e35d 100644 --- a/integrations/client/test_delphi_epidata.py +++ b/integrations/client/test_delphi_epidata.py @@ -235,7 +235,6 @@ def fetch(geo): **self.params_from_row(rows[0], geo_value=geo) ) - self.maxDiff = None # test fetch all request = fetch('*') self.assertEqual(request['message'], 'success') From ef362d8dae2f5c9c1717cb4554e22fe01ea84e58 Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Sun, 19 Mar 2023 22:35:46 -0400 Subject: [PATCH 11/26] Update integrations/server/test_covidcast.py Co-authored-by: melange396 --- integrations/server/test_covidcast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index 89f8853d3..88593adcd 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -318,7 +318,7 @@ def fetch(geo_value): self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], expected[0:2]) # test fetch multiple noncontiguous regions - r = fetch('{},{}'.format(MSA[0], MSA[2])) + r = fetch(f'{MSA[0]},{MSA[2]}' self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], [expected[0], expected[2]]) # test fetch multiple regions but one is not existing From 6e29946bc5bfb7100d29e383a3c36927431b1976 Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Sun, 19 Mar 2023 22:36:01 -0400 Subject: [PATCH 12/26] Update integrations/server/test_covidcast.py Co-authored-by: melange396 --- integrations/server/test_covidcast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index 88593adcd..0a199e016 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -322,7 +322,7 @@ def fetch(geo_value): self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], [expected[0], expected[2]]) # test fetch multiple regions but one is not existing - r = fetch('{},11111'.format(MSA[0])) + r = fetch(f'{MSA[0]},11111') self.assertEqual(r['message'], 'Invalid geo_value(s) 11111 for the requested geo_type msa') # test fetch empty region r = fetch('') From e3fe68bcecdd69df4d3909c1e7f1ed9702f26bfb Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Sun, 19 Mar 2023 22:36:23 -0400 Subject: [PATCH 13/26] Update tests/server/test_params.py Co-authored-by: melange396 --- tests/server/test_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server/test_params.py b/tests/server/test_params.py index 4ec3796df..a769d23cf 100644 --- a/tests/server/test_params.py +++ b/tests/server/test_params.py @@ -92,7 +92,7 @@ def test_parse_geo_arg(self): with self.subTest("single"): with app.test_request_context("/?geo=fips:*"): self.assertEqual(parse_geo_arg(), [GeoSet("fips", True)]) - with app.test_request_context("/?geo=fips:{}".format(FIPS[0])): + with app.test_request_context(f"/?geo=fips:{FIPS[0]}"): self.assertEqual(parse_geo_arg(), [GeoSet("fips", [FIPS[0]])]) with self.subTest("single list"): with app.test_request_context("/?geo=fips:{},{}".format(FIPS[0], FIPS[1])): From 43a232ec64df927a53a16d8c4b4a128354766d94 Mon Sep 17 00:00:00 2001 From: LeonLu2 Date: Sun, 19 Mar 2023 22:48:03 -0400 Subject: [PATCH 14/26] 1. minor changes --- integrations/server/test_covidcast.py | 2 +- tests/acquisition/covidcast/test_covidcast_row.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index 0a199e016..c1a42529b 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -318,7 +318,7 @@ def fetch(geo_value): self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], expected[0:2]) # test fetch multiple noncontiguous regions - r = fetch(f'{MSA[0]},{MSA[2]}' + r = fetch(f'{MSA[0]},{MSA[2]}') self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], [expected[0], expected[2]]) # test fetch multiple regions but one is not existing diff --git a/tests/acquisition/covidcast/test_covidcast_row.py b/tests/acquisition/covidcast/test_covidcast_row.py index 35e7d62ee..3bcf26970 100644 --- a/tests/acquisition/covidcast/test_covidcast_row.py +++ b/tests/acquisition/covidcast/test_covidcast_row.py @@ -12,6 +12,7 @@ covidcast_rows_from_args, transpose_dict, ) +from delphi.epidata.acquisition.covidcast.test_utils import MSA # py3tester coverage target (equivalent to `import *`) __test_target__ = 'delphi.epidata.acquisition.covidcast.covidcast_row' @@ -24,7 +25,7 @@ class TestCovidcastRows(unittest.TestCase): "time_type": ["day"] * 10, "geo_type": ["msa"] * 10, "time_value": [2021_05_01 + i for i in range(5)] * 2, - "geo_value": ["40660"] * 10, + "geo_value": [MSA[0]] * 10, "value": range(10), "stderr": [10.0] * 10, "sample_size": [10.0] * 10, From 1e75209b3ba36f751dee45c1f29eb0caa7ef1285 Mon Sep 17 00:00:00 2001 From: LeonLu2 Date: Sun, 19 Mar 2023 23:43:03 -0400 Subject: [PATCH 15/26] 1. edit geo_type to match with what we have in make_default_row --- integrations/acquisition/covidcast/delete_batch.csv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integrations/acquisition/covidcast/delete_batch.csv b/integrations/acquisition/covidcast/delete_batch.csv index 5c1602218..14cf71e16 100644 --- a/integrations/acquisition/covidcast/delete_batch.csv +++ b/integrations/acquisition/covidcast/delete_batch.csv @@ -1,4 +1,4 @@ geo_id,value,stderr,sample_size,issue,time_value,geo_type,signal,source -d_nonlatest,0,0,0,1,0,county,sig,src -d_latest, 0,0,0,3,0,county,sig,src -d_justone, 0,0,0,1,0,county,sig,src \ No newline at end of file +d_nonlatest,0,0,0,1,0,msa,sig,src +d_latest, 0,0,0,3,0,msa,sig,src +d_justone, 0,0,0,1,0,msa,sig,src \ No newline at end of file From 79cdc2698490c064919ee22d1a94f3d258570a1e Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:24:57 -0400 Subject: [PATCH 16/26] Update integrations/server/test_covidcast.py Co-authored-by: melange396 --- integrations/server/test_covidcast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index c1a42529b..ecf7e65ea 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -48,7 +48,7 @@ def _insert_placeholder_set_two(self): def _insert_placeholder_set_three(self): rows = [ - CovidcastTestRow.make_default_row(geo_value=MSA[0], time_value=2000_01_01+i, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=2-i) + CovidcastTestRow.make_default_row(time_value=2000_01_01+i, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=2-i) for i in [1, 2, 3] ] + [ # time value intended to overlap with the time values above, with disjoint geo values From bec56219d15281c61e8193493e014d24d38e86ce Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:25:53 -0400 Subject: [PATCH 17/26] Update integrations/server/test_covidcast.py Co-authored-by: melange396 --- integrations/server/test_covidcast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index ecf7e65ea..a54f845ed 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -314,7 +314,7 @@ def fetch(geo_value): r = fetch('11111') self.assertEqual(r['message'], 'Invalid geo_value(s) 11111 for the requested geo_type msa') # test fetch multiple regions - r = fetch('{},{}'.format(MSA[0], MSA[1])) + r = fetch(f'{MSA[0]},{MSA[1]}') self.assertEqual(r['message'], 'success') self.assertEqual(r['epidata'], expected[0:2]) # test fetch multiple noncontiguous regions From 4578420264814f3d63040352168aae945c8f50b2 Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:31:05 -0400 Subject: [PATCH 18/26] Update tests/server/test_params.py Co-authored-by: melange396 --- tests/server/test_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server/test_params.py b/tests/server/test_params.py index a769d23cf..e756ddb24 100644 --- a/tests/server/test_params.py +++ b/tests/server/test_params.py @@ -95,7 +95,7 @@ def test_parse_geo_arg(self): with app.test_request_context(f"/?geo=fips:{FIPS[0]}"): self.assertEqual(parse_geo_arg(), [GeoSet("fips", [FIPS[0]])]) with self.subTest("single list"): - with app.test_request_context("/?geo=fips:{},{}".format(FIPS[0], FIPS[1])): + with app.test_request_context(f"/?geo=fips:{FIPS[0]},{FIPS[1]}"): self.assertEqual(parse_geo_arg(), [GeoSet("fips", [FIPS[0], FIPS[1]])]) with self.subTest("multi"): with app.test_request_context("/?geo=fips:*;msa:*"): From 4a59ead2e9c09af5e99d62625f2e3eba41d46443 Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:33:35 -0400 Subject: [PATCH 19/26] Update tests/server/test_params.py Co-authored-by: melange396 --- tests/server/test_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server/test_params.py b/tests/server/test_params.py index e756ddb24..614a55aa6 100644 --- a/tests/server/test_params.py +++ b/tests/server/test_params.py @@ -100,7 +100,7 @@ def test_parse_geo_arg(self): with self.subTest("multi"): with app.test_request_context("/?geo=fips:*;msa:*"): self.assertEqual(parse_geo_arg(), [GeoSet("fips", True), GeoSet("msa", True)]) - with app.test_request_context("/?geo=fips:{};msa:{}".format(FIPS[0], MSA[0])): + with app.test_request_context(f"/?geo=fips:{FIPS[0]};msa:{MSA[0]}"): self.assertEqual( parse_geo_arg(), [GeoSet("fips", [FIPS[0]]), GeoSet("msa", [MSA[0]])], From 00b4ff22c402531deaf4cc92c6e663581eafe72b Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:34:05 -0400 Subject: [PATCH 20/26] Update tests/server/test_params.py Co-authored-by: melange396 --- tests/server/test_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server/test_params.py b/tests/server/test_params.py index 614a55aa6..ed97fdbb0 100644 --- a/tests/server/test_params.py +++ b/tests/server/test_params.py @@ -105,7 +105,7 @@ def test_parse_geo_arg(self): parse_geo_arg(), [GeoSet("fips", [FIPS[0]]), GeoSet("msa", [MSA[0]])], ) - with app.test_request_context("/?geo=fips:{};fips:{}".format(FIPS[0], FIPS[1])): + with app.test_request_context(f"/?geo=fips:{FIPS[0]};fips:{FIPS[1]}"): self.assertEqual( parse_geo_arg(), [GeoSet("fips", [FIPS[0]]), GeoSet("fips", [FIPS[1]])], From 58fcc7f7c9182b53113419bec3fc88aceeb17fbc Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:34:17 -0400 Subject: [PATCH 21/26] Update tests/server/test_params.py Co-authored-by: melange396 --- tests/server/test_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server/test_params.py b/tests/server/test_params.py index ed97fdbb0..c5f142757 100644 --- a/tests/server/test_params.py +++ b/tests/server/test_params.py @@ -144,7 +144,7 @@ def test_single_parse_geo_arg(self): with app.test_request_context("/?geo=fips:{}".format(FIPS[0])): self.assertEqual(parse_single_geo_arg("geo"), GeoSet("fips", [FIPS[0]])) with self.subTest("single list"): - with app.test_request_context("/?geo=fips:{},{}".format(FIPS[0], FIPS[1])): + with app.test_request_context(f"/?geo=fips:{FIPS[0]},{FIPS[1]}"): self.assertRaises(ValidationFailedException, parse_single_geo_arg, "geo") with self.subTest("multi"): with app.test_request_context("/?geo=state:*;nation:*"): From 94e8b5f5d036cd7b5aad918463faed6f72e0842f Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:34:41 -0400 Subject: [PATCH 22/26] Update tests/server/test_params.py Co-authored-by: melange396 --- tests/server/test_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server/test_params.py b/tests/server/test_params.py index c5f142757..b9bdde313 100644 --- a/tests/server/test_params.py +++ b/tests/server/test_params.py @@ -111,7 +111,7 @@ def test_parse_geo_arg(self): [GeoSet("fips", [FIPS[0]]), GeoSet("fips", [FIPS[1]])], ) with self.subTest("multi list"): - with app.test_request_context("/?geo=fips:{},{};msa:{},{}".format(FIPS[0], FIPS[1], MSA[0], MSA[1])): + with app.test_request_context(f"/?geo=fips:{FIPS[0]},{FIPS[1]};msa:{MSA[0]},{MSA[1]}"): self.assertEqual( parse_geo_arg(), [ From 59ce3c97f8dc1600d0fd6169aba5ae247e635aad Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:35:05 -0400 Subject: [PATCH 23/26] Update tests/server/test_params.py Co-authored-by: melange396 --- tests/server/test_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server/test_params.py b/tests/server/test_params.py index b9bdde313..a021ca80f 100644 --- a/tests/server/test_params.py +++ b/tests/server/test_params.py @@ -120,7 +120,7 @@ def test_parse_geo_arg(self): ], ) with self.subTest("hybrid"): - with app.test_request_context("/?geo=nation:*;fips:{};msa:{},{}".format(FIPS[0], MSA[0], MSA[1])): + with app.test_request_context(f"/?geo=nation:*;fips:{FIPS[0]};msa:{MSA[0]},{MSA[1]}"): self.assertEqual( parse_geo_arg(), [ From d41eeaa014b256857a3c864c8959e63a8aac5480 Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Tue, 21 Mar 2023 13:35:18 -0400 Subject: [PATCH 24/26] Update tests/server/test_params.py Co-authored-by: melange396 --- tests/server/test_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server/test_params.py b/tests/server/test_params.py index a021ca80f..1a401efe2 100644 --- a/tests/server/test_params.py +++ b/tests/server/test_params.py @@ -141,7 +141,7 @@ def test_single_parse_geo_arg(self): with app.test_request_context("/"): self.assertRaises(ValidationFailedException, parse_single_geo_arg, "geo") with self.subTest("single"): - with app.test_request_context("/?geo=fips:{}".format(FIPS[0])): + with app.test_request_context(f"/?geo=fips:{FIPS[0]}"): self.assertEqual(parse_single_geo_arg("geo"), GeoSet("fips", [FIPS[0]])) with self.subTest("single list"): with app.test_request_context(f"/?geo=fips:{FIPS[0]},{FIPS[1]}"): From b01bb820f06d32c4899fae0e0b55629f6be3bb6d Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Tue, 21 Mar 2023 14:07:23 -0400 Subject: [PATCH 25/26] Update test_covidcast.py --- integrations/server/test_covidcast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index a54f845ed..e0d8c5d7a 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -52,7 +52,7 @@ def _insert_placeholder_set_three(self): for i in [1, 2, 3] ] + [ # time value intended to overlap with the time values above, with disjoint geo values - CovidcastTestRow.make_default_row(geo_value=str(i)*5, time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=5-i) + CovidcastTestRow.make_default_row(geo_value=FIPS[i-4], time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=5-i) for i in [4, 5, 6] ] self._insert_rows(rows) From e2d12ee62277fee504dff0f0888b21e93204a06e Mon Sep 17 00:00:00 2001 From: Suhan Lu <78125134+LeonLu2@users.noreply.github.com> Date: Wed, 22 Mar 2023 16:33:56 -0400 Subject: [PATCH 26/26] Update integrations/server/test_covidcast.py Co-authored-by: Katie Mazaitis --- integrations/server/test_covidcast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/server/test_covidcast.py b/integrations/server/test_covidcast.py index e0d8c5d7a..01d81bf29 100644 --- a/integrations/server/test_covidcast.py +++ b/integrations/server/test_covidcast.py @@ -52,7 +52,7 @@ def _insert_placeholder_set_three(self): for i in [1, 2, 3] ] + [ # time value intended to overlap with the time values above, with disjoint geo values - CovidcastTestRow.make_default_row(geo_value=FIPS[i-4], time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=5-i) + CovidcastTestRow.make_default_row(geo_value=MSA[i-3], time_value=2000_01_01+i-3, value=i*1., stderr=i*10., sample_size=i*100., issue=2000_01_03, lag=5-i) for i in [4, 5, 6] ] self._insert_rows(rows)