X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/ba13cfd9ffcbb2598c227850736abb9da720a636..87907916ff06741bd4627101d30e6e11b8ea1a1a:/nominatim/config.py?ds=sidebyside diff --git a/nominatim/config.py b/nominatim/config.py index 6395bf2a..72aaf0bd 100644 --- a/nominatim/config.py +++ b/nominatim/config.py @@ -1,17 +1,23 @@ """ Nominatim configuration accessor. """ +import logging import os +from pathlib import Path from dotenv import dotenv_values +from nominatim.errors import UsageError + +LOG = logging.getLogger() + class Configuration: """ Load and manage the project configuration. Nominatim uses dotenv to configure the software. Configuration options are resolved in the following order: - * from the OS environment + * from the OS environment (or the dirctionary given in `environ` * from the .env file in the project directory of the installation * from the default installation in the configuration directory @@ -19,20 +25,92 @@ class Configuration: avoid conflicts with other environment variables. """ - def __init__(self, project_dir, config_dir): + def __init__(self, project_dir, config_dir, environ=None): + self.environ = environ or os.environ + self.project_dir = project_dir + self.config_dir = config_dir self._config = dotenv_values(str((config_dir / 'env.defaults').resolve())) - self._config.update(dotenv_values(str((project_dir / '.env').resolve()))) + if project_dir is not None and (project_dir / '.env').is_file(): + self._config.update(dotenv_values(str((project_dir / '.env').resolve()))) + + # Add defaults for variables that are left empty to set the default. + # They may still be overwritten by environment variables. + if not self._config['NOMINATIM_ADDRESS_LEVEL_CONFIG']: + self._config['NOMINATIM_ADDRESS_LEVEL_CONFIG'] = \ + str(config_dir / 'address-levels.json') + + class _LibDirs: + pass + + self.lib_dir = _LibDirs() + + def set_libdirs(self, **kwargs): + """ Set paths to library functions and data. + """ + for key, value in kwargs.items(): + setattr(self.lib_dir, key, Path(value).resolve()) def __getattr__(self, name): name = 'NOMINATIM_' + name - return os.environ.get(name) or self._config[name] + return self.environ.get(name) or self._config[name] + + def get_bool(self, name): + """ Return the given configuration parameter as a boolean. + Values of '1', 'yes' and 'true' are accepted as truthy values, + everything else is interpreted as false. + """ + return self.__getattr__(name).lower() in ('1', 'yes', 'true') + + + def get_int(self, name): + """ Return the given configuration parameter as an int. + """ + try: + return int(self.__getattr__(name)) + except ValueError: + LOG.fatal("Invalid setting NOMINATIM_%s. Needs to be a number.", name) + raise UsageError("Configuration error.") + + + def get_libpq_dsn(self): + """ Get configured database DSN converted into the key/value format + understood by libpq and psycopg. + """ + dsn = self.DATABASE_DSN + + def quote_param(param): + key, val = param.split('=') + val = val.replace('\\', '\\\\').replace("'", "\\'") + if ' ' in val: + val = "'" + val + "'" + return key + '=' + val + + if dsn.startswith('pgsql:'): + # Old PHP DSN format. Convert before returning. + return ' '.join([quote_param(p) for p in dsn[6:].split(';')]) + + return dsn + + + def get_import_style_file(self): + """ Return the import style file as a path object. Translates the + name of the standard styles automatically into a file in the + config style. + """ + style = self.__getattr__('IMPORT_STYLE') + + if style in ('admin', 'street', 'address', 'full', 'extratags'): + return self.config_dir / 'import-{}.style'.format(style) + + return Path(style) + def get_os_env(self): """ Return a copy of the OS environment with the Nominatim configuration merged in. """ env = dict(self._config) - env.update(os.environ) + env.update(self.environ) return env