2 Nominatim configuration accessor.
 
   6 from pathlib import Path
 
   8 from dotenv import dotenv_values
 
  10 from nominatim.errors import UsageError
 
  12 LOG = logging.getLogger()
 
  15     """ Load and manage the project configuration.
 
  17         Nominatim uses dotenv to configure the software. Configuration options
 
  18         are resolved in the following order:
 
  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
 
  24         All Nominatim configuration options are prefixed with 'NOMINATIM_' to
 
  25         avoid conflicts with other environment variables.
 
  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())))
 
  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')
 
  42         class _LibDirs: # pylint: disable=too-few-public-methods
 
  45         self.lib_dir = _LibDirs()
 
  47     def set_libdirs(self, **kwargs):
 
  48         """ Set paths to library functions and data.
 
  50         for key, value in kwargs.items():
 
  51             setattr(self.lib_dir, key, Path(value).resolve())
 
  53     def __getattr__(self, name):
 
  54         name = 'NOMINATIM_' + name
 
  56         return self.environ.get(name) or self._config[name]
 
  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.
 
  63         return self.__getattr__(name).lower() in ('1', 'yes', 'true')
 
  66     def get_int(self, name):
 
  67         """ Return the given configuration parameter as an int.
 
  70             return int(self.__getattr__(name))
 
  72             LOG.fatal("Invalid setting NOMINATIM_%s. Needs to be a number.", name)
 
  73             raise UsageError("Configuration error.")
 
  76     def get_libpq_dsn(self):
 
  77         """ Get configured database DSN converted into the key/value format
 
  78             understood by libpq and psycopg.
 
  80         dsn = self.DATABASE_DSN
 
  82         def quote_param(param):
 
  83             key, val = param.split('=')
 
  84             val = val.replace('\\', '\\\\').replace("'", "\\'")
 
  87             return key + '=' + val
 
  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(';')])
 
  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
 
 101         style = self.__getattr__('IMPORT_STYLE')
 
 103         if style in ('admin', 'street', 'address', 'full', 'extratags'):
 
 104             return self.config_dir / 'import-{}.style'.format(style)
 
 109     def get_os_env(self):
 
 110         """ Return a copy of the OS environment with the Nominatim configuration
 
 113         env = dict(self._config)
 
 114         env.update(self.environ)