1 # SPDX-License-Identifier: GPL-2.0-only
 
   3 # This file is part of Nominatim. (https://nominatim.org)
 
   5 # Copyright (C) 2022 by the Nominatim developer community.
 
   6 # For a full list of authors see the git log.
 
   8 Creator for mutation variants for the generic token analysis.
 
  14 from nominatim.errors import UsageError
 
  16 LOG = logging.getLogger()
 
  18 def _zigzag(outer, inner):
 
  19     return itertools.chain.from_iterable(itertools.zip_longest(outer, inner, fillvalue=''))
 
  22 class MutationVariantGenerator:
 
  23     """ Generates name variants by applying a regular expression to the name
 
  24         and replacing it with one or more variants. When the regular expression
 
  25         matches more than once, each occurence is replaced with all replacement
 
  29     def __init__(self, pattern, replacements):
 
  30         self.pattern = re.compile(pattern)
 
  31         self.replacements = replacements
 
  33         if self.pattern.groups > 0:
 
  34             LOG.fatal("The mutation pattern %s contains a capturing group. "
 
  35                       "This is not allowed.", pattern)
 
  36             raise UsageError("Bad mutation pattern in configuration.")
 
  39     def generate(self, names):
 
  40         """ Generator function for the name variants. 'names' is an iterable
 
  41             over a set of names for which the variants are to be generated.
 
  44             parts = self.pattern.split(name)
 
  48                 for seps in self._fillers(len(parts)):
 
  49                     yield ''.join(_zigzag(parts, seps))
 
  52     def _fillers(self, num_parts):
 
  53         """ Returns a generator for strings to join the given number of string
 
  54             parts in all possible combinations.
 
  56         return itertools.product(self.replacements, repeat=num_parts - 1)