From fddecceecb44dcb6b336c1877677c6ec33510b91 Mon Sep 17 00:00:00 2001 From: Azhan Date: Sat, 20 Mar 2021 17:39:59 -0400 Subject: [PATCH 1/4] Applied Aggregation --- .idea/.gitignore | 3 + .idea/COVID19Py.iml | 8 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/vcs.xml | 6 + COVID19Py/covid19.py | 492 +++++++++++++++--- 6 files changed, 440 insertions(+), 79 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/COVID19Py.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/COVID19Py.iml b/.idea/COVID19Py.iml new file mode 100644 index 0000000..8388dbc --- /dev/null +++ b/.idea/COVID19Py.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d56657a --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/COVID19Py/covid19.py b/COVID19Py/covid19.py index a68faa7..30174b1 100644 --- a/COVID19Py/covid19.py +++ b/COVID19Py/covid19.py @@ -2,52 +2,14 @@ import requests import json -class COVID19(object): - default_url = "https://covid-tracker-us.herokuapp.com" - url = "" - data_source = "" - previousData = None - latestData = None - _valid_data_sources = [] - - mirrors_source = "https://raw.github.com/Kamaropoulos/COVID19Py/master/mirrors.json" - mirrors = None - - def __init__(self, url="https://covid-tracker-us.herokuapp.com", data_source='jhu'): - # Skip mirror checking if custom url was passed - if url == self.default_url: - # Load mirrors - response = requests.get(self.mirrors_source) - response.raise_for_status() - self.mirrors = response.json() - # Try to get sources as a test - for mirror in self.mirrors: - # Set URL of mirror - self.url = mirror["url"] - result = None - try: - result = self._getSources() - except Exception as e: - # URL did not work, reset it and move on - self.url = "" - continue - - # TODO: Should have a better health-check, this is way too hacky... - if "jhu" in result: - # We found a mirror that worked just fine, let's stick with it - break - - # None of the mirrors worked. Raise an error to inform the user. - raise RuntimeError("No available API mirror was found.") - - else: - self.url = url - - self._valid_data_sources = self._getSources() - if data_source not in self._valid_data_sources: - raise ValueError("Invalid data source. Expected one of: %s" % self._valid_data_sources) - self.data_source = data_source +class COVID19(object): + sourced=None + def __init__(self,sourced=None): + if sourced is not None: + self.sourced = sourced + + def _update(self, timelines): latest = self.getLatest() @@ -59,15 +21,12 @@ def _update(self, timelines): "locations": locations } - def _getSources(self): - response = requests.get(self.url + "/v2/sources") - response.raise_for_status() - return response.json()["sources"] + def _request(self, endpoint, params=None): if params is None: params = {} - response = requests.get(self.url + endpoint, {**params, "source":self.data_source}) + response = requests.get(self.sourced.url + endpoint, {**params, "source":self.sourced.data_source}) response.raise_for_status() return response.json() @@ -122,37 +81,412 @@ def getLocations(self, timelines=False, rank_by: str = None) -> List[Dict]: data = ranked return data + + + + + def getCountInfo(self,count,timelines=False) -> List[Dict]: - def getLocationByCountryCode(self, country_code, timelines=False) -> List[Dict]: - """ - :param country_code: String denoting the ISO 3166-1 alpha-2 code (https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) of the country - :param timelines: Whether timeline information should be returned as well. - :return: A list of areas that correspond to the country_code. If the country_code is invalid, it returns an empty list. - """ data = None - if timelines: - data = self._request("/v2/locations", {"country_code": country_code, "timelines": str(timelines).lower()}) + + if count.nameOfCount is not None: + if timelines: + data = self._request("/v2/locations", {"country": count.nameOfCount, "timelines": str(timelines).lower()}) + + else: + data = self._request("/v2/locations", {"country": count.nameOfCount}) + + return data["locations"] + + if count.Count_Code is not None: + if timelines: + data = self._request("/v2/locations", {"country_code": count.Count_Code, "timelines": str(timelines).lower()}) + + else: + data = self._request("/v2/locations", {"country_code": count.Count_Code}) + return data["locations"] + + if count.Count_num is not None: + if timelines: + data = self._request("/v2/locations", {"country_code": count.Count_num, "timelines": str(timelines).lower()}) + + else: + data = self._request("/v2/locations", {"country_code": count.Count_num}) + return data["locations"] + + + + + + + + +################################################### + + + + +class fetchData(object): + + default_url = "https://covid-tracker-us.herokuapp.com" + url = "" + data_source = "" + previousData = None + latestData = None + _valid_data_sources = [] + + mirrors_source = "https://raw.github.com/Kamaropoulos/COVID19Py/master/mirrors.json" + mirrors = None + + def __init__(self, url="https://covid-tracker-us.herokuapp.com", data_source='jhu'): + # Skip mirror checking if custom url was passed + if url == self.default_url: + # Load mirrors + response = requests.get(self.mirrors_source) + response.raise_for_status() + self.mirrors = response.json() + + # Try to get sources as a test + for mirror in self.mirrors: + # Set URL of mirror + self.url = mirror["url"] + result = None + try: + result = self._getSources() + except Exception as e: + # URL did not work, reset it and move on + self.url = "" + continue + + # TODO: Should have a better health-check, this is way too hacky... + if "jhu" in result: + # We found a mirror that worked just fine, let's stick with it + break + + # None of the mirrors worked. Raise an error to inform the user. + raise RuntimeError("No available API mirror was found.") + else: - data = self._request("/v2/locations", {"country_code": country_code}) - return data["locations"] + self.url = url + + self._valid_data_sources = self._getSources() + if data_source not in self._valid_data_sources: + raise ValueError("Invalid data source. Expected one of: %s" % self._valid_data_sources) + self.data_source = data_source + + def _getSources(self): + response = requests.get(self.url + "/v2/sources") + response.raise_for_status() + return response.json()["sources"] + + ################################################################################## + +########################################################################################################### +class CaseByCountry(): + + nameOfCount = '' + Count_Code = '' + Count_num = '' + nameOfCount_check = False + Count_Code_check = False + Count_num_check = False + + + def __init__(self,nameOfCount=None,Count_Code=None,Count_num=None): + + + + + if nameOfCount is not None: + self.nameOfCount = nameOfCount + self.nameOfCount_check = True + + if Count_Code is not None: + self.Count_Code = Count_Code + self.Count_Code_check = True + + + if Count_num is not None: + self.Count_num = Count_num + self.Count_num_check = True + + country_dict = {'Afghanistan': 'AF', + 'Albania': 'AL', + 'Algeria': 'DZ', + 'American Samoa': 'AS', + 'Andorra': 'AD', + 'Angola': 'AO', + 'Anguilla': 'AI', + 'Antarctica': 'AQ', + 'Antigua and Barbuda': 'AG', + 'Argentina': 'AR', + 'Armenia': 'AM', + 'Aruba': 'AW', + 'Australia': 'AU', + 'Austria': 'AT', + 'Azerbaijan': 'AZ', + 'Bahamas': 'BS', + 'Bahrain': 'BH', + 'Bangladesh': 'BD', + 'Barbados': 'BB', + 'Belarus': 'BY', + 'Belgium': 'BE', + 'Belize': 'BZ', + 'Benin': 'BJ', + 'Bermuda': 'BM', + 'Bhutan': 'BT', + 'Bolivia, Plurinational State of': 'BO', + 'Bonaire, Sint Eustatius and Saba': 'BQ', + 'Bosnia and Herzegovina': 'BA', + 'Botswana': 'BW', + 'Bouvet Island': 'BV', + 'Brazil': 'BR', + 'British Indian Ocean Territory': 'IO', + 'Brunei Darussalam': 'BN', + 'Bulgaria': 'BG', + 'Burkina Faso': 'BF', + 'Burundi': 'BI', + 'Cambodia': 'KH', + 'Cameroon': 'CM', + 'Canada': 'CA', + 'Cape Verde': 'CV', + 'Cayman Islands': 'KY', + 'Central African Republic': 'CF', + 'Chad': 'TD', + 'Chile': 'CL', + 'China': 'CN', + 'Christmas Island': 'CX', + 'Cocos (Keeling) Islands': 'CC', + 'Colombia': 'CO', + 'Comoros': 'KM', + 'Congo': 'CG', + 'Congo, the Democratic Republic of the': 'CD', + 'Cook Islands': 'CK', + 'Costa Rica': 'CR', + 'Country name': 'Code', + 'Croatia': 'HR', + 'Cuba': 'CU', + 'Curaçao': 'CW', + 'Cyprus': 'CY', + 'Czech Republic': 'CZ', + "Côte d'Ivoire": 'CI', + 'Denmark': 'DK', + 'Djibouti': 'DJ', + 'Dominica': 'DM', + 'Dominican Republic': 'DO', + 'Ecuador': 'EC', + 'Egypt': 'EG', + 'El Salvador': 'SV', + 'Equatorial Guinea': 'GQ', + 'Eritrea': 'ER', + 'Estonia': 'EE', + 'Ethiopia': 'ET', + 'Falkland Islands (Malvinas)': 'FK', + 'Faroe Islands': 'FO', + 'Fiji': 'FJ', + 'Finland': 'FI', + 'France': 'FR', + 'French Guiana': 'GF', + 'French Polynesia': 'PF', + 'French Southern Territories': 'TF', + 'Gabon': 'GA', + 'Gambia': 'GM', + 'Georgia': 'GE', + 'Germany': 'DE', + 'Ghana': 'GH', + 'Gibraltar': 'GI', + 'Greece': 'GR', + 'Greenland': 'GL', + 'Grenada': 'GD', + 'Guadeloupe': 'GP', + 'Guam': 'GU', + 'Guatemala': 'GT', + 'Guernsey': 'GG', + 'Guinea': 'GN', + 'Guinea-Bissau': 'GW', + 'Guyana': 'GY', + 'Haiti': 'HT', + 'Heard Island and McDonald Islands': 'HM', + 'Holy See (Vatican City State)': 'VA', + 'Honduras': 'HN', + 'Hong Kong': 'HK', + 'Hungary': 'HU', + 'ISO 3166-2:GB': '(.uk)', + 'Iceland': 'IS', + 'India': 'IN', + 'Indonesia': 'ID', + 'Iran, Islamic Republic of': 'IR', + 'Iraq': 'IQ', + 'Ireland': 'IE', + 'Isle of Man': 'IM', + 'Israel': 'IL', + 'Italy': 'IT', + 'Jamaica': 'JM', + 'Japan': 'JP', + 'Jersey': 'JE', + 'Jordan': 'JO', + 'Kazakhstan': 'KZ', + 'Kenya': 'KE', + 'Kiribati': 'KI', + "Korea, Democratic People's Republic of": 'KP', + 'Korea, Republic of': 'KR', + 'Kuwait': 'KW', + 'Kyrgyzstan': 'KG', + "Lao People's Democratic Republic": 'LA', + 'Latvia': 'LV', + 'Lebanon': 'LB', + 'Lesotho': 'LS', + 'Liberia': 'LR', + 'Libya': 'LY', + 'Liechtenstein': 'LI', + 'Lithuania': 'LT', + 'Luxembourg': 'LU', + 'Macao': 'MO', + 'Macedonia, the former Yugoslav Republic of': 'MK', + 'Madagascar': 'MG', + 'Malawi': 'MW', + 'Malaysia': 'MY', + 'Maldives': 'MV', + 'Mali': 'ML', + 'Malta': 'MT', + 'Marshall Islands': 'MH', + 'Martinique': 'MQ', + 'Mauritania': 'MR', + 'Mauritius': 'MU', + 'Mayotte': 'YT', + 'Mexico': 'MX', + 'Micronesia, Federated States of': 'FM', + 'Moldova, Republic of': 'MD', + 'Monaco': 'MC', + 'Mongolia': 'MN', + 'Montenegro': 'ME', + 'Montserrat': 'MS', + 'Morocco': 'MA', + 'Mozambique': 'MZ', + 'Myanmar': 'MM', + 'Namibia': 'NA', + 'Nauru': 'NR', + 'Nepal': 'NP', + 'Netherlands': 'NL', + 'New Caledonia': 'NC', + 'New Zealand': 'NZ', + 'Nicaragua': 'NI', + 'Niger': 'NE', + 'Nigeria': 'NG', + 'Niue': 'NU', + 'Norfolk Island': 'NF', + 'Northern Mariana Islands': 'MP', + 'Norway': 'NO', + 'Oman': 'OM', + 'Pakistan': 'PK', + 'Palau': 'PW', + 'Palestine, State of': 'PS', + 'Panama': 'PA', + 'Papua New Guinea': 'PG', + 'Paraguay': 'PY', + 'Peru': 'PE', + 'Philippines': 'PH', + 'Pitcairn': 'PN', + 'Poland': 'PL', + 'Portugal': 'PT', + 'Puerto Rico': 'PR', + 'Qatar': 'QA', + 'Romania': 'RO', + 'Russian Federation': 'RU', + 'Rwanda': 'RW', + 'Réunion': 'RE', + 'Saint Barthélemy': 'BL', + 'Saint Helena, Ascension and Tristan da Cunha': 'SH', + 'Saint Kitts and Nevis': 'KN', + 'Saint Lucia': 'LC', + 'Saint Martin (French part)': 'MF', + 'Saint Pierre and Miquelon': 'PM', + 'Saint Vincent and the Grenadines': 'VC', + 'Samoa': 'WS', + 'San Marino': 'SM', + 'Sao Tome and Principe': 'ST', + 'Saudi Arabia': 'SA', + 'Senegal': 'SN', + 'Serbia': 'RS', + 'Seychelles': 'SC', + 'Sierra Leone': 'SL', + 'Singapore': 'SG', + 'Sint Maarten (Dutch part)': 'SX', + 'Slovakia': 'SK', + 'Slovenia': 'SI', + 'Solomon Islands': 'SB', + 'Somalia': 'SO', + 'South Africa': 'ZA', + 'South Georgia and the South Sandwich Islands': 'GS', + 'South Sudan': 'SS', + 'Spain': 'ES', + 'Sri Lanka': 'LK', + 'Sudan': 'SD', + 'Suriname': 'SR', + 'Svalbard and Jan Mayen': 'SJ', + 'Swaziland': 'SZ', + 'Sweden': 'SE', + 'Switzerland': 'CH', + 'Syrian Arab Republic': 'SY', + 'Taiwan, Province of China': 'TW', + 'Tajikistan': 'TJ', + 'Tanzania, United Republic of': 'TZ', + 'Thailand': 'TH', + 'Timor-Leste': 'TL', + 'Togo': 'TG', + 'Tokelau': 'TK', + 'Tonga': 'TO', + 'Trinidad and Tobago': 'TT', + 'Tunisia': 'TN', + 'Turkey': 'TR', + 'Turkmenistan': 'TM', + 'Turks and Caicos Islands': 'TC', + 'Tuvalu': 'TV', + 'Uganda': 'UG', + 'Ukraine': 'UA', + 'United Arab Emirates': 'AE', + 'United Kingdom': 'GB', + 'United States': 'US', + 'United States Minor Outlying Islands': 'UM', + 'Uruguay': 'UY', + 'Uzbekistan': 'UZ', + 'Vanuatu': 'VU', + 'Venezuela, Bolivarian Republic of': 'VE', + 'Viet Nam': 'VN', + 'Virgin Islands, British': 'VG', + 'Virgin Islands, U.S.': 'VI', + 'Wallis and Futuna': 'WF', + 'Western Sahara': 'EH', + 'Yemen': 'YE', + 'Zambia': 'ZM', + 'Zimbabwe': 'ZW', + 'Åland Islands': 'AX'} + + + + def __str__(self): + if (self.nameOfCount_check or self.Count_Code_check or self.Count_num_check ) == False : + return("No input received") + + if (self.nameOfCount).capitalize() not in country_dict: + return("Country does not exists") + + + return ( "{: <15} ({}) num={}".format(self.nameOfCount,self.Count_Code,self.Count_num)) +########################################################################################################### + + + + + + + + + + + + + + - def getLocationByCountry(self, country, timelines=False) -> List[Dict]: - """ - :param country: String denoting name of the country - :param timelines: Whether timeline information should be returned as well. - :return: A list of areas that correspond to the country name. If the country is invalid, it returns an empty list. - """ - data = None - if timelines: - data = self._request("/v2/locations", {"country": country, "timelines": str(timelines).lower()}) - else: - data = self._request("/v2/locations", {"country": country}) - return data["locations"] - def getLocationById(self, country_id: int): - """ - :param country_id: Country Id, an int - :return: A dictionary with case information for the specified location. - """ - data = self._request("/v2/locations/" + str(country_id)) - return data["location"] From 5ad6ce0e46a4fcdb071940f8885678c43c2eea86 Mon Sep 17 00:00:00 2001 From: Azhan Date: Sat, 20 Mar 2021 18:00:48 -0400 Subject: [PATCH 2/4] Minor fixes --- COVID19Py/covid19.py | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/COVID19Py/covid19.py b/COVID19Py/covid19.py index 30174b1..fb2c38c 100644 --- a/COVID19Py/covid19.py +++ b/COVID19Py/covid19.py @@ -465,28 +465,11 @@ def __init__(self,nameOfCount=None,Count_Code=None,Count_num=None): def __str__(self): - if (self.nameOfCount_check or self.Count_Code_check or self.Count_num_check ) == False : - return("No input received") + if (self.nameOfCount).capitalize() not in country_dict: return("Country does not exists") return ( "{: <15} ({}) num={}".format(self.nameOfCount,self.Count_Code,self.Count_num)) -########################################################################################################### - - - - - - - - - - - - - - - - + ########################################################################################################### From 9ca841c378f9e984615923a95b5691560d0d55f1 Mon Sep 17 00:00:00 2001 From: Azhan Date: Sat, 20 Mar 2021 18:33:35 -0400 Subject: [PATCH 3/4] Added sample Testing method in comments --- COVID19Py/covid19.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/COVID19Py/covid19.py b/COVID19Py/covid19.py index fb2c38c..97914cb 100644 --- a/COVID19Py/covid19.py +++ b/COVID19Py/covid19.py @@ -473,3 +473,10 @@ def __str__(self): return ( "{: <15} ({}) num={}".format(self.nameOfCount,self.Count_Code,self.Count_num)) ########################################################################################################### + +#Testing +#def main(): +# CovData = COVID19(fetchData()) +# print(CovData.getLocationData(CaseByCountry(nameOfCount=="Canada"))) +#if __name__ == '__main__': + # main() From e25c7c6d508925328f0d6835fc478cbc0fb7c216 Mon Sep 17 00:00:00 2001 From: Azhan Date: Sat, 20 Mar 2021 20:16:46 -0400 Subject: [PATCH 4/4] Fixing a spelling mistake in test section --- COVID19Py/covid19.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/COVID19Py/covid19.py b/COVID19Py/covid19.py index 97914cb..c825009 100644 --- a/COVID19Py/covid19.py +++ b/COVID19Py/covid19.py @@ -475,8 +475,8 @@ def __str__(self): ########################################################################################################### #Testing -#def main(): -# CovData = COVID19(fetchData()) -# print(CovData.getLocationData(CaseByCountry(nameOfCount=="Canada"))) -#if __name__ == '__main__': - # main() +def main(): + CovData = COVID19(fetchData()) + print(CovData.getCountInfo(CaseByCountry(nameOfCount="Canada"))) +if __name__ == '__main__': + main()