"""Static countries data.""" import json import pkg_resources COUNTRIES_FILE_NAME = pkg_resources.resource_filename( 'iso_standards', 'data/json/countries_and_regions.json' ) class Country: """Class that represents a country object.""" _country_list = [] _indexes = {} def __init__(self, country_code): """Get Country instance by code Args: country_code (str): either of ISO-3166 alpha2|alpha3|numeric codes Raises: KeyError if not found """ Country._init_countries_data() self._country = self._get_country_by_code(country_code) @classmethod def _init_countries_data(cls): if cls._country_list: return with open(COUNTRIES_FILE_NAME, encoding='utf-8') as countries_file: cls._country_list = json.load(countries_file) cls._build_indexes(fields=[ 'alpha-2', 'alpha-3', 'country-code', 'region']) @classmethod def _build_indexes(cls, fields): """We need to index our countries to search quicker.""" for country in cls._country_list: for key in fields: value = country[key] # e.g. _indexes['alpha-2'] = {} values_storage = cls._indexes.setdefault(key, {}) # e.g _indexes['alpha-2']['US'] = [] index_storage = values_storage.setdefault(value, []) # e.g. _indexes['alpha-2']['US'] = [Country] index_storage.append(country) @classmethod def get_countries_by_region_name(cls, region_name): """Get ISO 3166 countries of the region.""" cls._init_countries_data() if region_name not in cls._indexes['region']: raise KeyError( 'Region with name {} was not found'.format(region_name)) return [ cls(item['alpha-3']) for item in cls._indexes['region'][region_name] ] @classmethod def get_list(cls): """Get all countries list.""" cls._init_countries_data() return [ cls(item['alpha-3']) for item in cls._country_list ] def _get_country_by_code(self, code): if code in self._indexes.get('alpha-2', {}): return self._indexes['alpha-2'][code][0] if code in self._indexes.get('alpha-3', {}): return self._indexes['alpha-3'][code][0] if code in self._indexes.get('country-code', {}): return self._indexes['country-code'][code][0] raise KeyError('Country with code {} was not found'.format(code)) @property def alpha2(self): """Get ISO 3166-1 alpha-2 code.""" return self._country['alpha-2'] @property def alpha3(self): """Get ISO 3166-1 alpha-2 code.""" return self._country['alpha-3'] @property def numeric(self): """Get ISO 3166-1 numeric code.""" return self._country['country-code'] @property def name(self): """Get ISO 3166-1 country name.""" return self._country['name'] @property def region(self): """Get ISO 3166-2 region name.""" return self._country['region'] def to_dict(self): """Serialize country into a dictionary.""" return { 'alpha2': self._country['alpha-2'], 'alpha3': self._country['alpha-3'], 'numeric': self._country['country-code'], 'name': self._country['name'], 'region': self._country['region'] }