X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/0192a7af96d32faf5dd319469d376bf4140dfcbb..690f9ec06fd7a08b41de027427d8a1d3d0e3ff2e:/nominatim/tokenizer/token_analysis/generic.py diff --git a/nominatim/tokenizer/token_analysis/generic.py b/nominatim/tokenizer/token_analysis/generic.py index b9bd9bdf..d4eae312 100644 --- a/nominatim/tokenizer/token_analysis/generic.py +++ b/nominatim/tokenizer/token_analysis/generic.py @@ -11,7 +11,9 @@ import itertools import datrie +from nominatim.errors import UsageError from nominatim.tokenizer.token_analysis.config_variants import get_variant_config +from nominatim.tokenizer.token_analysis.generic_mutation import MutationVariantGenerator ### Configuration section @@ -24,6 +26,22 @@ def configure(rules, normalization_rules): normalization_rules) config['variant_only'] = rules.get('mode', '') == 'variant-only' + # parse mutation rules + config['mutations'] = [] + for rule in rules.get('mutations', []): + if 'pattern' not in rule: + raise UsageError("Missing field 'pattern' in mutation configuration.") + if not isinstance(rule['pattern'], str): + raise UsageError("Field 'pattern' in mutation configuration " + "must be a simple text field.") + if 'replacements' not in rule: + raise UsageError("Missing field 'replacements' in mutation configuration.") + if not isinstance(rule['replacements'], list): + raise UsageError("Field 'replacements' in mutation configuration " + "must be a list of texts.") + + config['mutations'].append((rule['pattern'], rule['replacements'])) + return config @@ -52,19 +70,31 @@ class GenericTokenAnalysis: else: self.replacements = None + # set up mutation rules + self.mutations = [MutationVariantGenerator(*cfg) for cfg in config['mutations']] + def get_variants_ascii(self, norm_name): """ Compute the spelling variants for the given normalized name and transliterate the result. """ - results = set() - for variant in self._generate_word_variants(norm_name): - if not self.variant_only or variant.strip() != norm_name: - trans_name = self.to_ascii.transliterate(variant).strip() - if trans_name: - results.add(trans_name) - - return list(results) + variants = self._generate_word_variants(norm_name) + + for mutation in self.mutations: + variants = mutation.generate(variants) + + return [name for name in self._transliterate_unique_list(norm_name, variants) if name] + + + def _transliterate_unique_list(self, norm_name, iterable): + seen = set() + if self.variant_only: + seen.add(norm_name) + + for variant in map(str.strip, iterable): + if variant not in seen: + seen.add(variant) + yield self.to_ascii.transliterate(variant).strip() def _generate_word_variants(self, norm_name):