mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-14 18:37:58 +00:00
update Locales constructor:
expect output names as argument and avoid redundant configuration initialization
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
Helper functions for localizing names of results.
|
||||
"""
|
||||
from typing import Mapping, List, Optional
|
||||
from .config import Configuration
|
||||
from .results import AddressLines, BaseResultT
|
||||
|
||||
import re
|
||||
@@ -18,15 +17,15 @@ class Locales:
|
||||
""" Helper class for localization of names.
|
||||
|
||||
It takes a list of language prefixes in their order of preferred
|
||||
usage.
|
||||
usage and comma separated name keys (Configuration.OUTPUT_NAMES).
|
||||
"""
|
||||
|
||||
def __init__(self, langs: Optional[List[str]] = None):
|
||||
self.config = Configuration(None)
|
||||
def __init__(self, langs: Optional[List[str]] = None,
|
||||
names: str = 'name:XX,name') -> None:
|
||||
self.languages = langs or []
|
||||
self.name_tags: List[str] = []
|
||||
|
||||
parts = self.config.OUTPUT_NAMES.split(',')
|
||||
parts = names.split(',') if names else []
|
||||
|
||||
for part in parts:
|
||||
part = part.strip()
|
||||
@@ -68,7 +67,7 @@ class Locales:
|
||||
return next(iter(names.values()))
|
||||
|
||||
@staticmethod
|
||||
def from_accept_languages(langstr: str) -> 'Locales':
|
||||
def from_accept_languages(langstr: str, names: str = 'name:XX,name') -> 'Locales':
|
||||
""" Create a localization object from a language list in the
|
||||
format of HTTP accept-languages header.
|
||||
|
||||
@@ -96,7 +95,7 @@ class Locales:
|
||||
if len(parts) > 1 and all(c[0] != parts[0] for c in candidates):
|
||||
languages.append(parts[0])
|
||||
|
||||
return Locales(languages)
|
||||
return Locales(languages, names)
|
||||
|
||||
def localize(self, lines: AddressLines) -> None:
|
||||
""" Sets the local name of address parts according to the chosen
|
||||
|
||||
@@ -174,7 +174,8 @@ async def details_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any:
|
||||
if result is None:
|
||||
params.raise_error('No place with that OSM ID found.', status=404)
|
||||
|
||||
locales = Locales.from_accept_languages(get_accepted_languages(params))
|
||||
locales = Locales.from_accept_languages(get_accepted_languages(params),
|
||||
params.config().OUTPUT_NAMES)
|
||||
locales.localize_results([result])
|
||||
|
||||
output = params.formatting().format_result(
|
||||
@@ -215,8 +216,8 @@ async def reverse_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any:
|
||||
query = ''
|
||||
|
||||
if result:
|
||||
Locales.from_accept_languages(get_accepted_languages(params)).localize_results(
|
||||
[result])
|
||||
Locales.from_accept_languages(get_accepted_languages(params),
|
||||
params.config().OUTPUT_NAMES).localize_results([result])
|
||||
|
||||
fmt_options = {'query': query,
|
||||
'extratags': params.get_bool('extratags', False),
|
||||
@@ -255,7 +256,8 @@ async def lookup_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any:
|
||||
if debug:
|
||||
return build_response(params, loglib.get_and_disable(), num_results=len(results))
|
||||
|
||||
Locales.from_accept_languages(get_accepted_languages(params)).localize_results(results)
|
||||
Locales.from_accept_languages(get_accepted_languages(params),
|
||||
params.config().OUTPUT_NAMES).localize_results(results)
|
||||
|
||||
fmt_options = {'extratags': params.get_bool('extratags', False),
|
||||
'namedetails': params.get_bool('namedetails', False),
|
||||
@@ -348,7 +350,8 @@ async def search_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any:
|
||||
except UsageError as err:
|
||||
params.raise_error(str(err))
|
||||
|
||||
Locales.from_accept_languages(get_accepted_languages(params)).localize_results(results)
|
||||
Locales.from_accept_languages(get_accepted_languages(params),
|
||||
params.config().OUTPUT_NAMES).localize_results(results)
|
||||
|
||||
if details['dedupe'] and len(results) > 1:
|
||||
results = helpers.deduplicate_results(results, max_results)
|
||||
|
||||
@@ -19,6 +19,7 @@ import nominatim_api as napi
|
||||
from nominatim_api.v1.helpers import zoom_to_rank, deduplicate_results
|
||||
from nominatim_api.server.content_types import CONTENT_JSON
|
||||
import nominatim_api.logging as loglib
|
||||
from ..config import Configuration
|
||||
from ..errors import UsageError
|
||||
from .args import NominatimArgs
|
||||
|
||||
@@ -91,13 +92,14 @@ def _get_geometry_output(args: NominatimArgs) -> napi.GeometryFormat:
|
||||
raise UsageError(f"Unknown polygon output format '{args.polygon_output}'.") from exp
|
||||
|
||||
|
||||
def _get_locales(args: NominatimArgs, default: Optional[str]) -> napi.Locales:
|
||||
def _get_locales(args: NominatimArgs, config: Configuration) -> napi.Locales:
|
||||
""" Get the locales from the language parameter.
|
||||
"""
|
||||
if args.lang:
|
||||
return napi.Locales.from_accept_languages(args.lang)
|
||||
if default:
|
||||
return napi.Locales.from_accept_languages(default)
|
||||
language = args.lang or config.DEFAULT_LANGUAGE
|
||||
output_names = config.OUTPUT_NAMES
|
||||
|
||||
if language:
|
||||
return napi.Locales.from_accept_languages(language, output_names)
|
||||
|
||||
return napi.Locales()
|
||||
|
||||
@@ -214,7 +216,7 @@ class APISearch:
|
||||
except napi.UsageError as ex:
|
||||
raise UsageError(ex) from ex
|
||||
|
||||
locales = _get_locales(args, api.config.DEFAULT_LANGUAGE)
|
||||
locales = _get_locales(args, api.config)
|
||||
locales.localize_results(results)
|
||||
|
||||
if args.dedupe and len(results) > 1:
|
||||
@@ -287,7 +289,7 @@ class APIReverse:
|
||||
raise UsageError(ex) from ex
|
||||
|
||||
if result is not None:
|
||||
locales = _get_locales(args, api.config.DEFAULT_LANGUAGE)
|
||||
locales = _get_locales(args, api.config)
|
||||
locales.localize_results([result])
|
||||
|
||||
if args.format == 'debug':
|
||||
@@ -352,7 +354,7 @@ class APILookup:
|
||||
except napi.UsageError as ex:
|
||||
raise UsageError(ex) from ex
|
||||
|
||||
locales = _get_locales(args, api.config.DEFAULT_LANGUAGE)
|
||||
locales = _get_locales(args, api.config)
|
||||
locales.localize_results(results)
|
||||
|
||||
if args.format == 'debug':
|
||||
@@ -452,7 +454,7 @@ class APIDetails:
|
||||
raise UsageError(ex) from ex
|
||||
|
||||
if result is not None:
|
||||
locales = _get_locales(args, api.config.DEFAULT_LANGUAGE)
|
||||
locales = _get_locales(args, api.config)
|
||||
locales.localize_results([result])
|
||||
|
||||
if args.format == 'debug':
|
||||
|
||||
@@ -154,7 +154,7 @@ async def dump_results(conn: napi.SearchConnection,
|
||||
await add_result_details(conn, results,
|
||||
LookupDetails(address_details=True))
|
||||
|
||||
locale = napi.Locales([lang] if lang else None)
|
||||
locale = napi.Locales([lang] if lang else None, conn.config.OUTPUT_NAMES)
|
||||
locale.localize_results(results)
|
||||
|
||||
for result in results:
|
||||
|
||||
@@ -31,20 +31,15 @@ def test_output_names_none_localized():
|
||||
loc = Locales()
|
||||
|
||||
expected_tags = [
|
||||
'name', '_place_name', 'brand', '_place_brand', 'official_name', '_place_official_name',
|
||||
'short_name', '_place_short_name', 'ref', '_place_ref'
|
||||
'name', '_place_name'
|
||||
]
|
||||
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_none_localized_and_custom_output_names(monkeypatch):
|
||||
monkeypatch.setenv(
|
||||
'NOMINATIM_OUTPUT_NAMES',
|
||||
'name:XX,entrance:XX,name,brand,test_tag,'
|
||||
'official_name:XX,short_name:XX,alt_name:XX'
|
||||
)
|
||||
loc = Locales()
|
||||
def test_output_names_none_localized_and_custom_output_names():
|
||||
loc = Locales(names='name:XX,entrance:XX,name,brand,test_tag,'
|
||||
'official_name:XX,short_name:XX,alt_name:XX')
|
||||
|
||||
expected_tags = [
|
||||
'name', '_place_name', 'brand', '_place_brand', 'test_tag', '_place_test_tag'
|
||||
@@ -53,13 +48,9 @@ def test_output_names_none_localized_and_custom_output_names(monkeypatch):
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_none_localized_and_custom_output_names_more_than_two_changes(monkeypatch):
|
||||
monkeypatch.setenv(
|
||||
'NOMINATIM_OUTPUT_NAMES',
|
||||
'name:XX,brand,test_tag:XX,official_name,short_name:XX,'
|
||||
'alt_name,another_tag_with:XX,another_tag_withoutXX'
|
||||
)
|
||||
loc = Locales()
|
||||
def test_output_names_none_localized_and_custom_output_names_more_than_two_changes():
|
||||
loc = Locales(names='name:XX,brand,test_tag:XX,official_name,short_name:XX,'
|
||||
'alt_name,another_tag_with:XX,another_tag_withoutXX')
|
||||
|
||||
expected_tags = [
|
||||
'brand', '_place_brand', 'official_name', '_place_official_name', 'alt_name',
|
||||
@@ -69,12 +60,8 @@ def test_output_names_none_localized_and_custom_output_names_more_than_two_chang
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_none_localized_and_custom_output_names_including_space(monkeypatch):
|
||||
monkeypatch.setenv(
|
||||
'NOMINATIM_OUTPUT_NAMES',
|
||||
'name:XX,name ,short_name:XX, short_name'
|
||||
)
|
||||
loc = Locales()
|
||||
def test_output_names_none_localized_and_custom_output_names_including_space():
|
||||
loc = Locales(names='name:XX,name ,short_name:XX, short_name')
|
||||
|
||||
expected_tags = [
|
||||
'name', '_place_name', 'short_name', '_place_short_name'
|
||||
@@ -95,22 +82,32 @@ def test_output_names_localized():
|
||||
loc = Locales(['en', 'es'])
|
||||
|
||||
expected_tags = [
|
||||
'name:en', '_place_name:en', 'name:es', '_place_name:es', 'name', '_place_name', 'brand',
|
||||
'_place_brand', 'official_name:en', '_place_official_name:en', 'official_name:es',
|
||||
'_place_official_name:es', 'short_name:en', '_place_short_name:en', 'short_name:es',
|
||||
'_place_short_name:es', 'official_name', '_place_official_name', 'short_name',
|
||||
'_place_short_name', 'ref', '_place_ref'
|
||||
'name:en', '_place_name:en', 'name:es', '_place_name:es', 'name', '_place_name'
|
||||
]
|
||||
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_localized_and_custom_output_names_including_space(monkeypatch):
|
||||
monkeypatch.setenv(
|
||||
'NOMINATIM_OUTPUT_NAMES',
|
||||
'name:XX,name ,short_name:XX, short_name'
|
||||
)
|
||||
loc = Locales(['en', 'es'])
|
||||
def test_output_names_localized_and_empty_names():
|
||||
loc = Locales(['en'], "")
|
||||
expected_tags = []
|
||||
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_localized_and_custom_names_ordering_logic():
|
||||
loc = Locales(['en', 'fr'], "name:XX,ref")
|
||||
|
||||
expected = [
|
||||
'name:en', '_place_name:en',
|
||||
'name:fr', '_place_name:fr',
|
||||
'ref', '_place_ref'
|
||||
]
|
||||
assert loc.name_tags == expected
|
||||
|
||||
|
||||
def test_output_names_localized_and_custom_output_names_including_space():
|
||||
loc = Locales(['en', 'es'], names='name:XX,name ,short_name:XX, short_name')
|
||||
|
||||
expected_tags = [
|
||||
'name:en', '_place_name:en', 'name:es', '_place_name:es',
|
||||
@@ -122,12 +119,9 @@ def test_output_names_localized_and_custom_output_names_including_space(monkeypa
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_localized_and_custom_output_names(monkeypatch):
|
||||
monkeypatch.setenv(
|
||||
'NOMINATIM_OUTPUT_NAMES',
|
||||
'name:XX,entrance:XX,name,brand,test_tag,official_name:XX,short_name:XX,alt_name:XX'
|
||||
)
|
||||
loc = Locales(['en', 'es'])
|
||||
def test_output_names_localized_and_custom_output_names():
|
||||
loc = Locales(['en', 'es'], names='name:XX,entrance:XX,name,brand,test_tag,'
|
||||
'official_name:XX,short_name:XX,alt_name:XX')
|
||||
|
||||
expected_tags = [
|
||||
'name:en', '_place_name:en', 'name:es', '_place_name:es', 'entrance:en',
|
||||
@@ -141,12 +135,9 @@ def test_output_names_localized_and_custom_output_names(monkeypatch):
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_localized_and_custom_output_names_start_with_tag_that_has_no_XX(monkeypatch):
|
||||
monkeypatch.setenv(
|
||||
'NOMINATIM_OUTPUT_NAMES',
|
||||
'name,brand,test_tag,official_name:XX,short_name:XX,alt_name:XX'
|
||||
)
|
||||
loc = Locales(['en', 'es'])
|
||||
def test_output_names_localized_and_custom_output_names_start_with_tag_that_has_no_XX():
|
||||
loc = Locales(['en', 'es'],
|
||||
names='name,brand,test_tag,official_name:XX,short_name:XX,alt_name:XX')
|
||||
|
||||
expected_tags = [
|
||||
'name', '_place_name', 'brand', '_place_brand', 'test_tag', '_place_test_tag',
|
||||
@@ -159,12 +150,8 @@ def test_output_names_localized_and_custom_output_names_start_with_tag_that_has_
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_localized_and_custom_output_names_no_named_tags(monkeypatch):
|
||||
monkeypatch.setenv(
|
||||
'NOMINATIM_OUTPUT_NAMES',
|
||||
'name,brand,test_tag'
|
||||
)
|
||||
loc = Locales(['en', 'es'])
|
||||
def test_output_names_localized_and_custom_output_names_no_named_tags():
|
||||
loc = Locales(['en', 'es'], names='name,brand,test_tag')
|
||||
|
||||
expected_tags = [
|
||||
'name', '_place_name', 'brand', '_place_brand', 'test_tag', '_place_test_tag'
|
||||
@@ -173,12 +160,9 @@ def test_output_names_localized_and_custom_output_names_no_named_tags(monkeypatc
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_localized_and_custom_output_names_only_named_tags(monkeypatch):
|
||||
monkeypatch.setenv(
|
||||
'NOMINATIM_OUTPUT_NAMES',
|
||||
'name:XX,entrance:XX,official_name:XX,short_name:XX,alt_name:XX'
|
||||
)
|
||||
loc = Locales(['en', 'es'])
|
||||
def test_output_names_localized_and_custom_output_names_only_named_tags():
|
||||
loc = Locales(['en', 'es'],
|
||||
names='name:XX,entrance:XX,official_name:XX,short_name:XX,alt_name:XX')
|
||||
|
||||
expected_tags = [
|
||||
'name:en', '_place_name:en', 'name:es', '_place_name:es', 'entrance:en',
|
||||
@@ -191,13 +175,9 @@ def test_output_names_localized_and_custom_output_names_only_named_tags(monkeypa
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_localized_and_custom_output_names_more_than_two_changes(monkeypatch):
|
||||
monkeypatch.setenv(
|
||||
'NOMINATIM_OUTPUT_NAMES',
|
||||
'name:XX,brand,test_tag:XX,official_name,short_name:XX,'
|
||||
'alt_name,another_tag_with:XX,another_tag_withoutXX'
|
||||
)
|
||||
loc = Locales(['en', 'es'])
|
||||
def test_output_names_localized_and_custom_output_names_more_than_two_changes():
|
||||
loc = Locales(['en', 'es'], names='name:XX,brand,test_tag:XX,official_name,'
|
||||
'short_name:XX,alt_name,another_tag_with:XX,another_tag_withoutXX')
|
||||
|
||||
expected_tags = [
|
||||
'name:en', '_place_name:en', 'name:es', '_place_name:es', 'brand', '_place_brand',
|
||||
@@ -211,13 +191,9 @@ def test_output_names_localized_and_custom_output_names_more_than_two_changes(mo
|
||||
assert loc.name_tags == expected_tags, f'Expected {expected_tags}, but got {loc.name_tags}'
|
||||
|
||||
|
||||
def test_output_names_localized_and_custom_output_names_XX_in_the_middle(monkeypatch):
|
||||
monkeypatch.setenv(
|
||||
'NOMINATIM_OUTPUT_NAMES',
|
||||
'name:XX,br:XXand,test_tag:XX,official_name,sh:XXort_name:XX,'
|
||||
'alt_name,another_tag_with:XX,another_tag_withoutXX'
|
||||
)
|
||||
loc = Locales(['en', 'es'])
|
||||
def test_output_names_localized_and_custom_output_names_XX_in_the_middle():
|
||||
loc = Locales(['en', 'es'], names='name:XX,br:XXand,test_tag:XX,official_name,'
|
||||
'sh:XXort_name:XX,alt_name,another_tag_with:XX,another_tag_withoutXX')
|
||||
|
||||
expected_tags = [
|
||||
'name:en', '_place_name:en', 'name:es', '_place_name:es', 'br:XXand', '_place_br:XXand',
|
||||
|
||||
Reference in New Issue
Block a user