+from nominatim.errors import UsageError
+from nominatim.data.place_name import PlaceName
+from nominatim.tokenizer.token_analysis.config_variants import get_variant_config
+from nominatim.tokenizer.token_analysis.generic_mutation import MutationVariantGenerator
+
+### Configuration section
+
+def configure(rules: Mapping[str, Any], normalizer: Any, _: Any) -> Dict[str, Any]:
+ """ Extract and preprocess the configuration for this module.
+ """
+ config: Dict[str, Any] = {}
+
+ config['replacements'], config['chars'] = get_variant_config(rules.get('variants'),
+ normalizer)
+ 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
+
+