"""
Nominatim configuration accessor.
"""
-from typing import Dict, Any, List, Mapping, Optional
+from typing import Union, Dict, Any, List, Mapping, Optional
import importlib.util
import logging
import os
from dotenv import dotenv_values
-try:
- from psycopg2.extensions import parse_dsn
-except ModuleNotFoundError:
- from psycopg.conninfo import conninfo_to_dict as parse_dsn # type: ignore[assignment]
+from psycopg.conninfo import conninfo_to_dict
from .typing import StrPath
from .errors import UsageError
from . import paths
LOG = logging.getLogger()
-CONFIG_CACHE : Dict[str, Any] = {}
+CONFIG_CACHE: Dict[str, Any] = {}
+
def flatten_config_list(content: Any, section: str = '') -> List[Any]:
""" Flatten YAML configuration lists that contain include sections
other than string.
"""
- def __init__(self, project_dir: Optional[Path],
+ def __init__(self, project_dir: Optional[Union[Path, str]],
environ: Optional[Mapping[str, str]] = None) -> None:
- self.environ = environ or os.environ
- self.project_dir = project_dir
+ self.environ = os.environ if environ is None else environ
self.config_dir = paths.CONFIG_DIR
self._config = dotenv_values(str(self.config_dir / 'env.defaults'))
- if self.project_dir is not None and (self.project_dir / '.env').is_file():
- self.project_dir = self.project_dir.resolve()
- self._config.update(dotenv_values(str(self.project_dir / '.env')))
+ if project_dir is not None:
+ self.project_dir: Optional[Path] = Path(project_dir).resolve()
+ if (self.project_dir / '.env').is_file():
+ self._config.update(dotenv_values(str(self.project_dir / '.env')))
+ else:
+ self.project_dir = None
class _LibDirs:
- module: Path
osm2pgsql: Path
- php = paths.PHPLIB_DIR
sql = paths.SQLLIB_DIR
data = paths.DATA_DIR
self.lib_dir = _LibDirs()
self._private_plugins: Dict[str, object] = {}
-
def set_libdirs(self, **kwargs: StrPath) -> None:
""" Set paths to library functions and data.
"""
for key, value in kwargs.items():
setattr(self.lib_dir, key, None if value is None else Path(value))
-
def __getattr__(self, name: str) -> str:
name = 'NOMINATIM_' + name
return self._config[name] or ''
-
def get_bool(self, name: str) -> bool:
""" Return the given configuration parameter as a boolean.
"""
return getattr(self, name).lower() in ('1', 'yes', 'true')
-
def get_int(self, name: str) -> int:
""" Return the given configuration parameter as an int.
LOG.fatal("Invalid setting NOMINATIM_%s. Needs to be a number.", name)
raise UsageError("Configuration error.") from exp
-
def get_str_list(self, name: str) -> Optional[List[str]]:
""" Return the given configuration parameter as a list of strings.
The values are assumed to be given as a comma-sparated list and
- will be stripped before returning them.
+ will be stripped before returning them.
Parameters:
name: Name of the configuration parameter with the NOMINATIM_
return [v.strip() for v in raw.split(',')] if raw else None
-
def get_path(self, name: str) -> Optional[Path]:
""" Return the given configuration parameter as a Path.
return cfgpath.resolve()
-
def get_libpq_dsn(self) -> str:
""" Get configured database DSN converted into the key/value format
understood by libpq and psycopg.
return dsn
-
- def get_database_params(self) -> Mapping[str, str]:
+ def get_database_params(self) -> Mapping[str, Union[str, int, None]]:
""" Get the configured parameters for the database connection
as a mapping.
"""
if dsn.startswith('pgsql:'):
return dict((p.split('=', 1) for p in dsn[6:].split(';')))
- return parse_dsn(dsn)
-
+ return conninfo_to_dict(dsn)
def get_import_style_file(self) -> Path:
""" Return the import style file as a path object. Translates the
return self.find_config_file('', 'IMPORT_STYLE')
-
def get_os_env(self) -> Dict[str, str]:
""" Return a copy of the OS environment with the Nominatim configuration
merged in.
return env
-
def load_sub_configuration(self, filename: StrPath,
config: Optional[str] = None) -> Any:
""" Load additional configuration from a file. `filename` is the name
CONFIG_CACHE[str(configfile)] = result
return result
-
def load_plugin_module(self, module_name: str, internal_path: str) -> Any:
""" Load a Python module as a plugin.
return sys.modules.get(module_name) or importlib.import_module(module_name)
-
def find_config_file(self, filename: StrPath,
config: Optional[str] = None) -> Path:
""" Resolve the location of a configuration file given a filename and
filename = cfg_filename
-
search_paths = [self.project_dir, self.config_dir]
for path in search_paths:
if path is not None and (path / filename).is_file():
filename, search_paths)
raise UsageError("Config file not found.")
-
def _load_from_yaml(self, cfgfile: Path) -> Any:
""" Load a YAML configuration file. This installs a special handler that
allows to include other YAML files using the '!include' operator.
Loader=yaml.SafeLoader)
return yaml.safe_load(cfgfile.read_text(encoding='utf-8'))
-
def _yaml_include_representer(self, loader: Any, node: yaml.Node) -> Any:
""" Handler for the '!include' operator in YAML files.