diff --git a/app/location/__init__.py b/app/location/__init__.py index 1da5e9e5..3015f344 100644 --- a/app/location/__init__.py +++ b/app/location/__init__.py @@ -1,7 +1,7 @@ """app.location""" from ..coordinates import Coordinates from ..utils import countries -from ..utils.populations import country_population +from ..utils.populations import Population # pylint: disable=redefined-builtin,invalid-name @@ -45,7 +45,7 @@ def country_population(self): :returns: The population. :rtype: int """ - return country_population(self.country_code) + return Population.country_population(self.country_code) def serialize(self): """ diff --git a/app/utils/populations.py b/app/utils/populations.py index c02f15a9..1672e5e4 100644 --- a/app/utils/populations.py +++ b/app/utils/populations.py @@ -1,4 +1,5 @@ """app.utils.populations.py""" +from _typeshed import Self import json import logging @@ -10,51 +11,52 @@ GEONAMES_URL = "http://api.geonames.org/countryInfoJSON" GEONAMES_BACKUP_PATH = "geonames_population_mappings.json" -# Fetching of the populations. -def fetch_populations(save=False): - """ - Returns a dictionary containing the population of each country fetched from the GeoNames. - https://www.geonames.org/ - - TODO: only skip writing to the filesystem when deployed with gunicorn, or handle concurent access, or use DB. - - :returns: The mapping of populations. - :rtype: dict - """ - LOGGER.info("Fetching populations...") - - # Mapping of populations - mappings = {} - - # Fetch the countries. - try: - countries = requests.get(GEONAMES_URL, params={"username": "dperic"}, timeout=1.25).json()[ - "geonames" - ] - # Go through all the countries and perform the mapping. - for country in countries: - mappings.update({country["countryCode"]: int(country["population"]) or None}) - - if mappings and save: - LOGGER.info(f"Saving population data to {app.io.save(GEONAMES_BACKUP_PATH, mappings)}") - except (json.JSONDecodeError, KeyError, requests.exceptions.Timeout) as err: - LOGGER.warning(f"Error pulling population data. {err.__class__.__name__}: {err}") - mappings = app.io.load(GEONAMES_BACKUP_PATH) - LOGGER.info(f"Using backup data from {GEONAMES_BACKUP_PATH}") - # Finally, return the mappings. - LOGGER.info("Fetched populations") - return mappings - - -# Mapping of alpha-2 codes country codes to population. -POPULATIONS = fetch_populations() - -# Retrieving. -def country_population(country_code, default=None): - """ - Fetches the population of the country with the provided country code. - - :returns: The population. - :rtype: int - """ - return POPULATIONS.get(country_code, default) +class Population: + + def __init__(self): + self.population = fetch_populations() + + # Fetching of the populations. + def fetch_populations(save=False): + """ + Returns a dictionary containing the population of each country fetched from the GeoNames. + https://www.geonames.org/ + + TODO: only skip writing to the filesystem when deployed with gunicorn, or handle concurent access, or use DB. + + :returns: The mapping of populations. + :rtype: dict + """ + LOGGER.info("Fetching populations...") + + # Mapping of populations + mappings = {} + + # Fetch the countries. + try: + countries = requests.get(GEONAMES_URL, params={"username": "dperic"}, timeout=1.25).json()[ + "geonames" + ] + # Go through all the countries and perform the mapping. + for country in countries: + mappings.update({country["countryCode"]: int(country["population"]) or None}) + + if mappings and save: + LOGGER.info(f"Saving population data to {app.io.save(GEONAMES_BACKUP_PATH, mappings)}") + except (json.JSONDecodeError, KeyError, requests.exceptions.Timeout) as err: + LOGGER.warning(f"Error pulling population data. {err.__class__.__name__}: {err}") + mappings = app.io.load(GEONAMES_BACKUP_PATH) + LOGGER.info(f"Using backup data from {GEONAMES_BACKUP_PATH}") + # Finally, return the mappings. + LOGGER.info("Fetched populations") + return mappings + + # Retrieving. + def country_population(country_code, default=None): + """ + Fetches the population of the country with the provided country code. + + :returns: The population. + :rtype: int + """ + return self.population.get(country_code, default)