]> git.openstreetmap.org Git - nominatim.git/blob - nominatim/tokenizer/factory.py
Merge pull request #2427 from lonvia/remove-us-states-special-casing
[nominatim.git] / nominatim / tokenizer / factory.py
1 """
2 Functions for creating a tokenizer or initialising the right one for an
3 existing database.
4
5 A tokenizer is something that is bound to the lifetime of a database. It
6 can be choosen and configured before the intial import but then needs to
7 be used consistently when querying and updating the database.
8
9 This module provides the functions to create and configure a new tokenizer
10 as well as instanciating the appropriate tokenizer for updating an existing
11 database.
12
13 A tokenizer usually also includes PHP code for querying. The appropriate PHP
14 normalizer module is installed, when the tokenizer is created.
15 """
16 import logging
17 import importlib
18 from pathlib import Path
19
20 from ..errors import UsageError
21 from ..db import properties
22 from ..db.connection import connect
23
24 LOG = logging.getLogger()
25
26 def _import_tokenizer(name):
27     """ Load the tokenizer.py module from project directory.
28     """
29     src_file = Path(__file__).parent / (name + '_tokenizer.py')
30     if not src_file.is_file():
31         LOG.fatal("No tokenizer named '%s' available. "
32                   "Check the setting of NOMINATIM_TOKENIZER.", name)
33         raise UsageError('Tokenizer not found')
34
35     return importlib.import_module('nominatim.tokenizer.' + name + '_tokenizer')
36
37
38 def create_tokenizer(config, init_db=True, module_name=None):
39     """ Create a new tokenizer as defined by the given configuration.
40
41         The tokenizer data and code is copied into the 'tokenizer' directory
42         of the project directory and the tokenizer loaded from its new location.
43     """
44     if module_name is None:
45         module_name = config.TOKENIZER
46
47     # Create the directory for the tokenizer data
48     basedir = config.project_dir / 'tokenizer'
49     if not basedir.exists():
50         basedir.mkdir()
51     elif not basedir.is_dir():
52         LOG.fatal("Tokenizer directory '%s' cannot be created.", basedir)
53         raise UsageError("Tokenizer setup failed.")
54
55     # Import and initialize the tokenizer.
56     tokenizer_module = _import_tokenizer(module_name)
57
58     tokenizer = tokenizer_module.create(config.get_libpq_dsn(), basedir)
59     tokenizer.init_new_db(config, init_db=init_db)
60
61     with connect(config.get_libpq_dsn()) as conn:
62         properties.set_property(conn, 'tokenizer', module_name)
63
64     return tokenizer
65
66
67 def get_tokenizer_for_db(config):
68     """ Instantiate a tokenizer for an existing database.
69
70         The function looks up the appropriate tokenizer in the database
71         and initialises it.
72     """
73     basedir = config.project_dir / 'tokenizer'
74     if not basedir.is_dir():
75         LOG.fatal("Cannot find tokenizer data in '%s'.", basedir)
76         raise UsageError('Cannot initialize tokenizer.')
77
78     with connect(config.get_libpq_dsn()) as conn:
79         name = properties.get_property(conn, 'tokenizer')
80
81     if name is None:
82         LOG.fatal("Tokenizer was not set up properly. Database property missing.")
83         raise UsageError('Cannot initialize tokenizer.')
84
85     tokenizer_module = _import_tokenizer(name)
86
87     tokenizer = tokenizer_module.create(config.get_libpq_dsn(), basedir)
88     tokenizer.init_from_project()
89
90     return tokenizer