from nominatim.db import utils as db_utils
from nominatim.db.connection import connect
+from nominatim.errors import UsageError
+
+def _flatten_name_list(names):
+ if names is None:
+ return {}
+
+ if not isinstance(names, dict):
+ raise UsageError("Expected key-value list for names in country_settings.py")
+
+ flat = {}
+ for prefix, remain in names.items():
+ if isinstance(remain, str):
+ flat[prefix] = remain
+ elif not isinstance(remain, dict):
+ raise UsageError("Entries in names must be key-value lists.")
+ else:
+ for suffix, name in remain.items():
+ if suffix == 'default':
+ flat[prefix] = name
+ else:
+ flat[f'{prefix}:{suffix}'] = name
+
+ return flat
+
+
class _CountryInfo:
""" Caches country-specific properties from the configuration file.
"""
if not self._info:
self._info = config.load_sub_configuration('country_settings.yaml')
- # Convert languages into a list for simpler handling.
for prop in self._info.values():
+ # Convert languages into a list for simpler handling.
if 'languages' not in prop:
prop['languages'] = []
elif not isinstance(prop['languages'], list):
prop['languages'] = [x.strip()
for x in prop['languages'].split(',')]
+ prop['names'] = _flatten_name_list(prop.get('names'))
def items(self):
"""
return self._info.items()
+ def get(self, country_code):
+ """ Get country information for the country with the given country code.
+ """
+ return self._info.get(country_code, {})
+
+
_COUNTRY_INFO = _CountryInfo()
+
def setup_country_config(config):
""" Load country properties from the configuration file.
Needs to be called before using any other functions in this
""" Create and populate the tables with basic static data that provides
the background for geocoding. Data is assumed to not yet exist.
"""
- db_utils.execute_file(dsn, sql_dir / 'country_name.sql')
db_utils.execute_file(dsn, sql_dir / 'country_osm_grid.sql.gz')
params = []
partition = 0
else:
partition = props.get('partition')
- lang = props['languages'][0] if len(props['languages']) == 1 else None
- params.append((ccode, partition, lang))
+ lang = props['languages'][0] if len(
+ props['languages']) == 1 else None
+ params.append((ccode, props['names'], lang, partition))
with connect(dsn) as conn:
with conn.cursor() as cur:
+ psycopg2.extras.register_hstore(cur)
+ cur.execute(
+ """ CREATE TABLE public.country_name (
+ country_code character varying(2),
+ name public.hstore,
+ derived_name public.hstore,
+ country_default_language_code text,
+ partition integer
+ ); """)
cur.execute_values(
- """ UPDATE country_name
- SET partition = part, country_default_language_code = lang
- FROM (VALUES %s) AS v (cc, part, lang)
- WHERE country_code = v.cc""", params)
+ """ INSERT INTO public.country_name
+ (country_code, name, country_default_language_code, partition) VALUES %s
+ """, params)
conn.commit()
empty then only name translations for the given languages are added
to the index.
"""
- if languages:
- languages = languages.split(',')
-
def _include_key(key):
- return key == 'name' or \
- (key.startswith('name:') and (not languages or key[5:] in languages))
+ return ':' not in key or not languages or \
+ key[key.index(':') + 1:] in languages
with conn.cursor() as cur:
psycopg2.extras.register_hstore(cur)
with tokenizer.name_analyzer() as analyzer:
for code, name in cur:
names = {'countrycode': code}
- if code == 'gb':
- names['short_name'] = 'UK'
- if code == 'us':
- names['short_name'] = 'United States'
# country names (only in languages as provided)
if name:
- names.update(((k, v) for k, v in name.items() if _include_key(k)))
+ names.update({k : v for k, v in name.items() if _include_key(k)})
analyzer.add_country_names(code, names)