schon/geo/conf.py

730 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from collections import defaultdict
from contextlib import suppress
from importlib import import_module
import django
from django.conf import settings as django_settings
from django.core.exceptions import ImproperlyConfigured
if float(".".join(map(str, django.VERSION[:2]))) < 3:
from django.utils.translation import ugettext_lazy as _
else:
from django.utils.translation import gettext_lazy as _
__all__ = [
"ALTERNATIVE_NAME_TYPES",
"CONTINENT_DATA",
"CURRENCY_SYMBOLS",
"INCLUDE_AIRPORT_CODES",
"INCLUDE_NUMERIC_ALTERNATIVE_NAMES",
"NO_LONGER_EXISTENT_COUNTRY_CODES",
"SKIP_CITIES_WITH_EMPTY_REGIONS",
"SLUGIFY_FUNCTION",
"VALIDATE_POSTAL_CODES",
"HookError",
"city_types",
"district_types",
"import_opts",
"import_opts_all",
"settings",
]
url_bases = {
"geonames": {
"dump": "http://download.geonames.org/export/dump/",
"zip": "http://download.geonames.org/export/zip/",
},
}
files = {
"country": {
"filename": "countryInfo.txt",
"urls": [url_bases["geonames"]["dump"] + "{filename}"],
"fields": [
"code",
"code3",
"codeNum",
"fips",
"name",
"capital",
"area",
"population",
"continent",
"tld",
"currencyCode",
"currencyName",
"phone",
"postalCodeFormat",
"postalCodeRegex",
"languages",
"geonameid",
"neighbours",
"equivalentFips",
],
},
"region": {
"filename": "admin1CodesASCII.txt",
"urls": [url_bases["geonames"]["dump"] + "{filename}"],
"fields": [
"code",
"name",
"asciiName",
"geonameid",
],
},
"subregion": {
"filename": "admin2Codes.txt",
"urls": [url_bases["geonames"]["dump"] + "{filename}"],
"fields": [
"code",
"name",
"asciiName",
"geonameid",
],
},
"city": {
"filename": "cities5000.zip",
"urls": [url_bases["geonames"]["dump"] + "{filename}"],
"fields": [
"geonameid",
"name",
"asciiName",
"alternateNames",
"latitude",
"longitude",
"featureClass",
"featureCode",
"countryCode",
"cc2",
"admin1Code",
"admin2Code",
"admin3Code",
"admin4Code",
"population",
"elevation",
"gtopo30",
"timezone",
"modificationDate",
],
},
"hierarchy": {
"filename": "hierarchy.zip",
"urls": [url_bases["geonames"]["dump"] + "{filename}"],
"fields": [
"parent",
"child",
"type",
],
},
"alt_name": {
"filename": "alternateNames.zip",
"urls": [url_bases["geonames"]["dump"] + "{filename}"],
"fields": [
"nameid",
"geonameid",
"language",
"name",
"isPreferred",
"isShort",
"isColloquial",
"isHistoric",
],
},
"postal_code": {
"filename": "allCountries.zip",
"urls": [url_bases["geonames"]["zip"] + "{filename}"],
"fields": [
"countryCode",
"postalCode",
"placeName",
"admin1Name",
"admin1Code",
"admin2Name",
"admin2Code",
"admin3Name",
"admin3Code",
"latitude",
"longitude",
"accuracy",
],
},
}
country_codes = [
"AD",
"AE",
"AF",
"AG",
"AI",
"AL",
"AM",
"AO",
"AQ",
"AR",
"AS",
"AT",
"AU",
"AW",
"AX",
"AZ",
"BA",
"BB",
"BD",
"BE",
"BF",
"BG",
"BH",
"BI",
"BJ",
"BL",
"BM",
"BN",
"BO",
"BQ",
"BR",
"BS",
"BT",
"BV",
"BW",
"BY",
"BZ",
"CA",
"CC",
"CD",
"CF",
"CG",
"CH",
"CI",
"CK",
"CL",
"CM",
"CN",
"CO",
"CR",
"CU",
"CV",
"CW",
"CX",
"CY",
"CZ",
"DE",
"DJ",
"DK",
"DM",
"DO",
"DZ",
"EC",
"EE",
"EG",
"EH",
"ER",
"ES",
"ET",
"FI",
"FJ",
"FK",
"FM",
"FO",
"FR",
"GA",
"GB",
"GD",
"GE",
"GF",
"GG",
"GH",
"GI",
"GL",
"GM",
"GN",
"GP",
"GQ",
"GR",
"GS",
"GT",
"GU",
"GW",
"GY",
"HK",
"HM",
"HN",
"HR",
"HT",
"HU",
"ID",
"IE",
"IL",
"IM",
"IN",
"IO",
"IQ",
"IR",
"IS",
"IT",
"JE",
"JM",
"JO",
"JP",
"KE",
"KG",
"KH",
"KI",
"KM",
"KN",
"KP",
"KR",
"XK",
"KW",
"KY",
"KZ",
"LA",
"LB",
"LC",
"LI",
"LK",
"LR",
"LS",
"LT",
"LU",
"LV",
"LY",
"MA",
"MC",
"MD",
"ME",
"MF",
"MG",
"MH",
"MK",
"ML",
"MM",
"MN",
"MO",
"MP",
"MQ",
"MR",
"MS",
"MT",
"MU",
"MV",
"MW",
"MX",
"MY",
"MZ",
"NA",
"NC",
"NE",
"NF",
"NG",
"NI",
"NL",
"NO",
"NP",
"NR",
"NU",
"NZ",
"OM",
"PA",
"PE",
"PF",
"PG",
"PH",
"PK",
"PL",
"PM",
"PN",
"PR",
"PS",
"PT",
"PW",
"PY",
"QA",
"RE",
"RO",
"RS",
"RU",
"RW",
"SA",
"SB",
"SC",
"SD",
"SS",
"SE",
"SG",
"SH",
"SI",
"SJ",
"SK",
"SL",
"SM",
"SN",
"SO",
"SR",
"ST",
"SV",
"SX",
"SY",
"SZ",
"TC",
"TD",
"TF",
"TG",
"TH",
"TJ",
"TK",
"TL",
"TM",
"TN",
"TO",
"TR",
"TT",
"TV",
"TW",
"TZ",
"UA",
"UG",
"UM",
"US",
"UY",
"UZ",
"VA",
"VC",
"VE",
"VG",
"VI",
"VN",
"VU",
"WF",
"WS",
"YE",
"YT",
"ZA",
"ZM",
"ZW",
]
_ALTERNATIVE_NAME_TYPES = (
("name", _("Name")),
("abbr", _("Abbreviation")),
("link", _("Link")),
)
_AIRPORT_TYPES = (
("iata", _("IATA (Airport) Code")),
("icao", _("ICAO (Airport) Code")),
("faac", _("FAAC (Airport) Code")),
)
CONTINENT_DATA = {
"AF": ("Africa", 6255146),
"AS": ("Asia", 6255147),
"EU": ("Europe", 6255148),
"NA": ("North America", 6255149),
"OC": ("Oceania", 6255151),
"SA": ("South America", 6255150),
"AN": ("Antarctica", 6255152),
}
_CURRENCY_SYMBOLS = {
"AED": "د.إ",
"AFN": "؋",
"ALL": "L",
"AMD": "դր.",
"ANG": "ƒ",
"AOA": "Kz",
"ARS": "$",
"AUD": "$",
"AWG": "ƒ",
"AZN": "m",
"BAM": "KM",
"BBD": "$",
"BDT": "",
"BGN": "лв",
"BHD": "ب.د",
"BIF": "Fr",
"BMD": "$",
"BND": "$",
"BOB": "Bs.",
"BRL": "R$",
"BSD": "$",
"BTN": "Nu",
"BWP": "P",
"BYR": "Br",
"BZD": "$",
"CAD": "$",
"CDF": "Fr",
"CHF": "Fr",
"CLP": "$",
"CNY": "¥",
"COP": "$",
"CRC": "",
"CUP": "$",
"CVE": "$, Esc",
"CZK": "",
"DJF": "Fr",
"DKK": "kr",
"DOP": "$",
"DZD": "د.ج",
"EEK": "KR",
"EGP": "£,ج.م",
"ERN": "Nfk",
"ETB": "Br",
"EUR": "",
"FJD": "$",
"FKP": "£",
"GBP": "£",
"GEL": "",
"GHS": "",
"GIP": "£",
"GMD": "D",
"GNF": "Fr",
"GTQ": "Q",
"GYD": "$",
"HKD": "$",
"HNL": "L",
"HRK": "kn",
"HTG": "G",
"HUF": "Ft",
"IDR": "Rp",
"ILS": "",
"INR": "",
"IQD": "ع.د",
"IRR": "",
"ISK": "kr",
"JMD": "$",
"JOD": "د.ا",
"JPY": "¥",
"KES": "Sh",
"KGS": "лв",
"KHR": "",
"KMF": "Fr",
"KPW": "",
"KRW": "",
"KWD": "د.ك",
"KYD": "$",
"KZT": "Т",
"LAK": "",
"LBP": "ل.ل",
"LKR": "ரூ",
"LRD": "$",
"LSL": "L",
"LTL": "Lt",
"LVL": "Ls",
"LYD": "ل.د",
"MAD": "د.م.",
"MDL": "L",
"MGA": "Ar",
"MKD": "ден",
"MMK": "K",
"MNT": "",
"MOP": "P",
"MRO": "UM",
"MUR": "",
"MVR": "ރ.",
"MWK": "MK",
"MXN": "$",
"MYR": "RM",
"MZN": "MT",
"NAD": "$",
"NGN": "",
"NIO": "C$",
"NOK": "kr",
"NPR": "",
"NZD": "$",
"OMR": "ر.ع.",
"PAB": "B/.",
"PEN": "S/.",
"PGK": "K",
"PHP": "",
"PKR": "",
"PLN": "",
"PYG": "",
"QAR": "ر.ق",
"RON": "RON",
"RSD": "RSD",
"RUB": "р.",
"RWF": "Fr",
"SAR": "ر.س",
"SBD": "$",
"SCR": "",
"SDG": "S$",
"SEK": "kr",
"SGD": "$",
"SHP": "£",
"SLL": "Le",
"SOS": "Sh",
"SRD": "$",
"STD": "Db",
"SYP": "£, ل.س",
"SZL": "L",
"THB": "฿",
"TJS": "ЅМ",
"TMT": "m",
"TND": "د.ت",
"TOP": "T$",
"TRY": "",
"TTD": "$",
"TWD": "$",
"TZS": "Sh",
"UAH": "",
"UGX": "Sh",
"USD": "$",
"UYU": "$",
"UZS": "лв",
"VEF": "Bs",
"VND": "",
"VUV": "Vt",
"WST": "T",
"XAF": "Fr",
"XCD": "$",
"XOF": "Fr",
"XPF": "Fr",
"YER": "",
"ZAR": "R",
"ZMK": "ZK",
"ZWL": "$",
}
_NO_LONGER_EXISTENT_COUNTRY_CODES = ["CS", "AN"]
_SLUGIFY_FUNCTION = getattr(django_settings, "CITIES_SLUGIFY_FUNCTION", "geo.util.default_slugify")
# See http://www.geonames.org/export/codes.html
city_types = ["PPL", "PPLA", "PPLC", "PPLA2", "PPLA3", "PPLA4", "PPLG"]
district_types = ["PPLX"]
# Command-line import options
import_opts = [
"all",
"country",
"region",
"subregion",
"city",
"district",
"alt_name",
"postal_code",
]
import_opts_all = [
"country",
"region",
"subregion",
"city",
"district",
"alt_name",
"postal_code",
]
# Raise inside a hook (with an error message) to skip the current line of data.
class HookError(Exception):
pass
# Hook functions that a plugin class may define
plugin_hooks = [
"country_pre",
"country_post",
"region_pre",
"region_post",
"subregion_pre",
"subregion_postcity_pre",
"city_post",
"district_pre",
"district_post",
"alt_name_pre",
"alt_name_post",
"postal_code_pre",
"postal_code_post",
]
def create_settings():
def get_locales(self):
locales = django_settings.CITIES_LOCALES[:] if hasattr(django_settings, "CITIES_LOCALES") else ["en", "und"]
with suppress(Exception):
locales.remove("LANGUAGES")
locales += [e[0] for e in django_settings.LANGUAGES]
return {[e.lower() for e in locales]}
res = type(
"settings",
(),
{
"locales": property(get_locales),
},
)
res.files = files.copy()
if hasattr(django_settings, "CITIES_FILES"):
for key in list(django_settings.CITIES_FILES.keys()):
if "filenames" in django_settings.CITIES_FILES[key] and "filename" in django_settings.CITIES_FILES[key]:
raise ImproperlyConfigured(
f"Only one key should be specified for '{key}': 'filename' of 'filenames'. Both specified instead"
)
res.files[key].update(django_settings.CITIES_FILES[key])
if "filenames" in django_settings.CITIES_FILES[key]:
del res.files[key]["filename"]
if hasattr(django_settings, "CITIES_DATA_DIR"):
res.data_dir = django_settings.CITIES_DATA_DIR
if hasattr(django_settings, "CITIES_POSTAL_CODES"):
res.postal_codes = {e.upper() for e in django_settings.CITIES_POSTAL_CODES}
else:
res.postal_codes = {"ALL"}
return res()
def create_plugins():
settings.plugins = defaultdict(list)
for plugin in django_settings.CITIES_PLUGINS:
module_path, classname = plugin.rsplit(".", 1)
module = import_module(module_path)
class_ = getattr(module, classname)
obj = class_()
[settings.plugins[hook].append(obj) for hook in plugin_hooks if hasattr(obj, hook)]
settings = create_settings()
if hasattr(django_settings, "CITIES_PLUGINS"):
create_plugins()
if hasattr(django_settings, "CITIES_IGNORE_EMPTY_REGIONS"):
raise Exception(
"CITIES_IGNORE_EMPTY_REGIONS was ambiguous and has been moved to CITIES_SKIP_CITIES_WITH_EMPTY_REGIONS"
)
SKIP_CITIES_WITH_EMPTY_REGIONS = getattr(django_settings, "CITIES_SKIP_CITIES_WITH_EMPTY_REGIONS", False)
# Users may way to import historical countries
NO_LONGER_EXISTENT_COUNTRY_CODES = getattr(
django_settings, "CITIES_NO_LONGER_EXISTENT_COUNTRY_CODES", _NO_LONGER_EXISTENT_COUNTRY_CODES
)
# Users may not want to include airport codes as alternative city names
INCLUDE_AIRPORT_CODES = getattr(django_settings, "CITIES_INCLUDE_AIRPORT_CODES", True)
if INCLUDE_AIRPORT_CODES:
_ALTERNATIVE_NAME_TYPES += _AIRPORT_TYPES
# A `Choices` object (from `django-model-utils`)
ALTERNATIVE_NAME_TYPES = getattr(django_settings, "CITIES_ALTERNATIVE_NAME_TYPES", _ALTERNATIVE_NAME_TYPES)
INCLUDE_NUMERIC_ALTERNATIVE_NAMES = getattr(django_settings, "CITIES_INCLUDE_NUMERIC_ALTERNATIVE_NAMES", True)
# Allow users to override specified contents
CONTINENT_DATA.update(getattr(django_settings, "CITIES_CONTINENT_DATA", {}))
CURRENCY_SYMBOLS = getattr(django_settings, "CITIES_CURRENCY_SYMBOLS", _CURRENCY_SYMBOLS)
module_name, _, function_name = _SLUGIFY_FUNCTION.rpartition(".")
SLUGIFY_FUNCTION = getattr(import_module(module_name), function_name)
# Users who want better postal codes can flip this on (developers of
# django-cities itself probably will), but most probably won't want to
VALIDATE_POSTAL_CODES = getattr(django_settings, "CITIES_VALIDATE_POSTAL_CODES", False)
DJANGO_VERSION = float(".".join(map(str, django.VERSION[:2])))