]> git.openstreetmap.org Git - nominatim.git/blob - nominatim/config.py
Merge pull request #2429 from lonvia/place-name-to-admin-boundary
[nominatim.git] / nominatim / config.py
1 """
2 Nominatim configuration accessor.
3 """
4 import logging
5 import os
6 from pathlib import Path
7
8 from dotenv import dotenv_values
9
10 from nominatim.errors import UsageError
11
12 LOG = logging.getLogger()
13
14 class Configuration:
15     """ Load and manage the project configuration.
16
17         Nominatim uses dotenv to configure the software. Configuration options
18         are resolved in the following order:
19
20          * from the OS environment (or the dirctionary given in `environ`
21          * from the .env file in the project directory of the installation
22          * from the default installation in the configuration directory
23
24         All Nominatim configuration options are prefixed with 'NOMINATIM_' to
25         avoid conflicts with other environment variables.
26     """
27
28     def __init__(self, project_dir, config_dir, environ=None):
29         self.environ = environ or os.environ
30         self.project_dir = project_dir
31         self.config_dir = config_dir
32         self._config = dotenv_values(str((config_dir / 'env.defaults').resolve()))
33         if project_dir is not None and (project_dir / '.env').is_file():
34             self._config.update(dotenv_values(str((project_dir / '.env').resolve())))
35
36         # Add defaults for variables that are left empty to set the default.
37         # They may still be overwritten by environment variables.
38         if not self._config['NOMINATIM_ADDRESS_LEVEL_CONFIG']:
39             self._config['NOMINATIM_ADDRESS_LEVEL_CONFIG'] = \
40                 str(config_dir / 'address-levels.json')
41
42         class _LibDirs:
43             pass
44
45         self.lib_dir = _LibDirs()
46
47     def set_libdirs(self, **kwargs):
48         """ Set paths to library functions and data.
49         """
50         for key, value in kwargs.items():
51             setattr(self.lib_dir, key, Path(value).resolve())
52
53     def __getattr__(self, name):
54         name = 'NOMINATIM_' + name
55
56         return self.environ.get(name) or self._config[name]
57
58     def get_bool(self, name):
59         """ Return the given configuration parameter as a boolean.
60             Values of '1', 'yes' and 'true' are accepted as truthy values,
61             everything else is interpreted as false.
62         """
63         return self.__getattr__(name).lower() in ('1', 'yes', 'true')
64
65
66     def get_int(self, name):
67         """ Return the given configuration parameter as an int.
68         """
69         try:
70             return int(self.__getattr__(name))
71         except ValueError as exp:
72             LOG.fatal("Invalid setting NOMINATIM_%s. Needs to be a number.", name)
73             raise UsageError("Configuration error.") from exp
74
75
76     def get_libpq_dsn(self):
77         """ Get configured database DSN converted into the key/value format
78             understood by libpq and psycopg.
79         """
80         dsn = self.DATABASE_DSN
81
82         def quote_param(param):
83             key, val = param.split('=')
84             val = val.replace('\\', '\\\\').replace("'", "\\'")
85             if ' ' in val:
86                 val = "'" + val + "'"
87             return key + '=' + val
88
89         if dsn.startswith('pgsql:'):
90             # Old PHP DSN format. Convert before returning.
91             return ' '.join([quote_param(p) for p in dsn[6:].split(';')])
92
93         return dsn
94
95
96     def get_import_style_file(self):
97         """ Return the import style file as a path object. Translates the
98             name of the standard styles automatically into a file in the
99             config style.
100         """
101         style = self.__getattr__('IMPORT_STYLE')
102
103         if style in ('admin', 'street', 'address', 'full', 'extratags'):
104             return self.config_dir / 'import-{}.style'.format(style)
105
106         return Path(style)
107
108
109     def get_os_env(self):
110         """ Return a copy of the OS environment with the Nominatim configuration
111             merged in.
112         """
113         env = dict(self._config)
114         env.update(self.environ)
115
116         return env