Merge pull request #2906 from lonvia/move-data-dirs-into-module

Reorganize how Nominatim finds its extra data and libraries
This commit is contained in:
Sarah Hoffmann
2022-11-28 08:44:29 +01:00
committed by GitHub
23 changed files with 132 additions and 123 deletions

View File

@@ -233,7 +233,14 @@ if (BUILD_IMPORTER)
install(DIRECTORY nominatim install(DIRECTORY nominatim
DESTINATION ${NOMINATIM_LIBDIR}/lib-python DESTINATION ${NOMINATIM_LIBDIR}/lib-python
FILES_MATCHING PATTERN "*.py" FILES_MATCHING PATTERN "*.py"
PATTERN "paths.py" EXCLUDE
PATTERN __pycache__ EXCLUDE) PATTERN __pycache__ EXCLUDE)
configure_file(${PROJECT_SOURCE_DIR}/cmake/paths-py.tmpl paths-py.installed)
install(FILES ${PROJECT_BINARY_DIR}/paths-py.installed
DESTINATION ${NOMINATIM_LIBDIR}/lib-python/nominatim
RENAME paths.py)
install(DIRECTORY lib-sql DESTINATION ${NOMINATIM_LIBDIR}) install(DIRECTORY lib-sql DESTINATION ${NOMINATIM_LIBDIR})
install(FILES ${COUNTRY_GRID_FILE} install(FILES ${COUNTRY_GRID_FILE}

15
cmake/paths-py.tmpl Normal file
View File

@@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# This file is part of Nominatim. (https://nominatim.org)
#
# Copyright (C) 2022 by the Nominatim developer community.
# For a full list of authors see the git log.
"""
Path settings for extra data used by Nominatim (installed version).
"""
from pathlib import Path
PHPLIB_DIR = (Path('@NOMINATIM_LIBDIR@') / 'lib-php').resolve()
SQLLIB_DIR = (Path('@NOMINATIM_LIBDIR@') / 'lib-sql').resolve()
DATA_DIR = Path('@NOMINATIM_DATADIR@').resolve()
CONFIG_DIR = Path('@NOMINATIM_CONFIGDIR@').resolve()

View File

@@ -11,8 +11,4 @@ version.GIT_COMMIT_HASH = '@GIT_HASH@'
exit(cli.nominatim(module_dir='@NOMINATIM_LIBDIR@/module', exit(cli.nominatim(module_dir='@NOMINATIM_LIBDIR@/module',
osm2pgsql_path='@NOMINATIM_LIBDIR@/osm2pgsql', osm2pgsql_path='@NOMINATIM_LIBDIR@/osm2pgsql',
phplib_dir='@NOMINATIM_LIBDIR@/lib-php',
sqllib_dir='@NOMINATIM_LIBDIR@/lib-sql',
data_dir='@NOMINATIM_DATADIR@',
config_dir='@NOMINATIM_CONFIGDIR@',
phpcgi_path='@PHPCGI_BIN@')) phpcgi_path='@PHPCGI_BIN@'))

View File

@@ -11,8 +11,4 @@ version.GIT_COMMIT_HASH = '@GIT_HASH@'
exit(cli.nominatim(module_dir='@CMAKE_BINARY_DIR@/module', exit(cli.nominatim(module_dir='@CMAKE_BINARY_DIR@/module',
osm2pgsql_path='@CMAKE_BINARY_DIR@/osm2pgsql/osm2pgsql', osm2pgsql_path='@CMAKE_BINARY_DIR@/osm2pgsql/osm2pgsql',
phplib_dir='@CMAKE_SOURCE_DIR@/lib-php',
sqllib_dir='@CMAKE_SOURCE_DIR@/lib-sql',
data_dir='@CMAKE_SOURCE_DIR@/data',
config_dir='@CMAKE_SOURCE_DIR@/settings',
phpcgi_path='@PHPCGI_BIN@')) phpcgi_path='@PHPCGI_BIN@'))

View File

@@ -100,9 +100,7 @@ class CommandlineParser:
self.parser.print_help() self.parser.print_help()
return 1 return 1
for arg in ('module_dir', 'osm2pgsql_path', 'phplib_dir', 'sqllib_dir', args.phpcgi_path = Path(kwargs['phpcgi_path'])
'data_dir', 'config_dir', 'phpcgi_path'):
setattr(args, arg, Path(kwargs[arg]))
args.project_dir = Path(args.project_dir).resolve() args.project_dir = Path(args.project_dir).resolve()
if 'cli_args' not in kwargs: if 'cli_args' not in kwargs:
@@ -111,13 +109,10 @@ class CommandlineParser:
datefmt='%Y-%m-%d %H:%M:%S', datefmt='%Y-%m-%d %H:%M:%S',
level=max(4 - args.verbose, 1) * 10) level=max(4 - args.verbose, 1) * 10)
args.config = Configuration(args.project_dir, args.config_dir, args.config = Configuration(args.project_dir,
environ=kwargs.get('environ', os.environ)) environ=kwargs.get('environ', os.environ))
args.config.set_libdirs(module=args.module_dir, args.config.set_libdirs(module=kwargs['module_dir'],
osm2pgsql=args.osm2pgsql_path, osm2pgsql=kwargs['osm2pgsql_path'])
php=args.phplib_dir,
sql=args.sqllib_dir,
data=args.data_dir)
log = logging.getLogger() log = logging.getLogger()
log.warning('Using project directory: %s', str(args.project_dir)) log.warning('Using project directory: %s', str(args.project_dir))
@@ -195,7 +190,7 @@ class QueryExport:
if args.restrict_to_osm_relation: if args.restrict_to_osm_relation:
params.extend(('--restrict-to-osm-relation', args.restrict_to_osm_relation)) params.extend(('--restrict-to-osm-relation', args.restrict_to_osm_relation))
return run_legacy_script('export.php', *params, nominatim_env=args) return run_legacy_script('export.php', *params, config=args.config)
class AdminServe: class AdminServe:

View File

@@ -88,4 +88,4 @@ class AdminFuncs:
params.append('--reverse-only') params.append('--reverse-only')
if args.target == 'search': if args.target == 'search':
params.append('--search-only') params.append('--search-only')
return run_legacy_script(*params, nominatim_env=args) return run_legacy_script(*params, config=args.config)

View File

@@ -42,12 +42,6 @@ class NominatimArgs:
# Basic environment set by root program. # Basic environment set by root program.
config: Configuration config: Configuration
project_dir: Path project_dir: Path
module_dir: Path
osm2pgsql_path: Path
phplib_dir: Path
sqllib_dir: Path
data_dir: Path
config_dir: Path
phpcgi_path: Path phpcgi_path: Path
# Global switches # Global switches
@@ -181,7 +175,7 @@ class NominatimArgs:
from the command line arguments. The resulting dict can be from the command line arguments. The resulting dict can be
further customized and then used in `run_osm2pgsql()`. further customized and then used in `run_osm2pgsql()`.
""" """
return dict(osm2pgsql=self.config.OSM2PGSQL_BINARY or self.osm2pgsql_path, return dict(osm2pgsql=self.config.OSM2PGSQL_BINARY or self.config.lib_dir.osm2pgsql,
osm2pgsql_cache=self.osm2pgsql_cache or default_cache, osm2pgsql_cache=self.osm2pgsql_cache or default_cache,
osm2pgsql_style=self.config.get_import_style_file(), osm2pgsql_style=self.config.get_import_style_file(),
osm2pgsql_style_path=self.config.config_dir, osm2pgsql_style_path=self.config.config_dir,

View File

@@ -87,7 +87,7 @@ class SetupAll:
LOG.warning('Setting up country tables') LOG.warning('Setting up country tables')
country_info.setup_country_tables(args.config.get_libpq_dsn(), country_info.setup_country_tables(args.config.get_libpq_dsn(),
args.data_dir, args.config.lib_dir.data,
args.no_partitions) args.no_partitions)
LOG.warning('Importing OSM data file') LOG.warning('Importing OSM data file')

View File

@@ -20,6 +20,7 @@ from dotenv import dotenv_values
from nominatim.typing import StrPath from nominatim.typing import StrPath
from nominatim.errors import UsageError from nominatim.errors import UsageError
import nominatim.paths
LOG = logging.getLogger() LOG = logging.getLogger()
CONFIG_CACHE : Dict[str, Any] = {} CONFIG_CACHE : Dict[str, Any] = {}
@@ -58,21 +59,22 @@ class Configuration:
avoid conflicts with other environment variables. avoid conflicts with other environment variables.
""" """
def __init__(self, project_dir: Path, config_dir: Path, def __init__(self, project_dir: Optional[Path],
environ: Optional[Mapping[str, str]] = None) -> None: environ: Optional[Mapping[str, str]] = None) -> None:
self.environ = environ or os.environ self.environ = environ or os.environ
self.project_dir = project_dir self.project_dir = project_dir
self.config_dir = config_dir self.config_dir = nominatim.paths.CONFIG_DIR
self._config = dotenv_values(str((config_dir / 'env.defaults').resolve())) self._config = dotenv_values(str(self.config_dir / 'env.defaults'))
if project_dir is not None and (project_dir / '.env').is_file(): if self.project_dir is not None and (self.project_dir / '.env').is_file():
self._config.update(dotenv_values(str((project_dir / '.env').resolve()))) self.project_dir = self.project_dir.resolve()
self._config.update(dotenv_values(str(self.project_dir / '.env')))
class _LibDirs: class _LibDirs:
module: Path module: Path
osm2pgsql: Path osm2pgsql: Path
php: Path php = nominatim.paths.PHPLIB_DIR
sql: Path sql = nominatim.paths.SQLLIB_DIR
data: Path data = nominatim.paths.DATA_DIR
self.lib_dir = _LibDirs() self.lib_dir = _LibDirs()
self._private_plugins: Dict[str, object] = {} self._private_plugins: Dict[str, object] = {}
@@ -82,7 +84,7 @@ class Configuration:
""" Set paths to library functions and data. """ Set paths to library functions and data.
""" """
for key, value in kwargs.items(): for key, value in kwargs.items():
setattr(self.lib_dir, key, Path(value).resolve()) setattr(self.lib_dir, key, Path(value))
def __getattr__(self, name: str) -> str: def __getattr__(self, name: str) -> str:
@@ -136,6 +138,7 @@ class Configuration:
cfgpath = Path(value) cfgpath = Path(value)
if not cfgpath.is_absolute(): if not cfgpath.is_absolute():
assert self.project_dir is not None
cfgpath = self.project_dir / cfgpath cfgpath = self.project_dir / cfgpath
return cfgpath.resolve() return cfgpath.resolve()
@@ -174,11 +177,11 @@ class Configuration:
return self.find_config_file('', 'IMPORT_STYLE') return self.find_config_file('', 'IMPORT_STYLE')
def get_os_env(self) -> Dict[str, Optional[str]]: def get_os_env(self) -> Dict[str, str]:
""" Return a copy of the OS environment with the Nominatim configuration """ Return a copy of the OS environment with the Nominatim configuration
merged in. merged in.
""" """
env = dict(self._config) env = {k: v for k, v in self._config.items() if v is not None}
env.update(self.environ) env.update(self.environ)
return env return env

15
nominatim/paths.py Normal file
View File

@@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# This file is part of Nominatim. (https://nominatim.org)
#
# Copyright (C) 2022 by the Nominatim developer community.
# For a full list of authors see the git log.
"""
Path settings for extra data used by Nominatim.
"""
from pathlib import Path
PHPLIB_DIR = (Path(__file__) / '..' / '..' / 'lib-php').resolve()
SQLLIB_DIR = (Path(__file__) / '..' / '..' / 'lib-sql').resolve()
DATA_DIR = (Path(__file__) / '..' / '..' / 'data').resolve()
CONFIG_DIR = (Path(__file__) / '..' / '..' / 'settings').resolve()

View File

@@ -55,6 +55,7 @@ def create_tokenizer(config: Configuration, init_db: bool = True,
module_name = config.TOKENIZER module_name = config.TOKENIZER
# Create the directory for the tokenizer data # Create the directory for the tokenizer data
assert config.project_dir is not None
basedir = config.project_dir / 'tokenizer' basedir = config.project_dir / 'tokenizer'
if not basedir.exists(): if not basedir.exists():
basedir.mkdir() basedir.mkdir()
@@ -80,6 +81,7 @@ def get_tokenizer_for_db(config: Configuration) -> AbstractTokenizer:
The function looks up the appropriate tokenizer in the database The function looks up the appropriate tokenizer in the database
and initialises it. and initialises it.
""" """
assert config.project_dir is not None
basedir = config.project_dir / 'tokenizer' basedir = config.project_dir / 'tokenizer'
if not basedir.is_dir(): if not basedir.is_dir():
# Directory will be repopulated by tokenizer below. # Directory will be repopulated by tokenizer below.

View File

@@ -106,6 +106,7 @@ class LegacyTokenizer(AbstractTokenizer):
This copies all necessary data in the project directory to make This copies all necessary data in the project directory to make
sure the tokenizer remains stable even over updates. sure the tokenizer remains stable even over updates.
""" """
assert config.project_dir is not None
module_dir = _install_module(config.DATABASE_MODULE_PATH, module_dir = _install_module(config.DATABASE_MODULE_PATH,
config.lib_dir.module, config.lib_dir.module,
config.project_dir / 'module') config.project_dir / 'module')
@@ -127,6 +128,8 @@ class LegacyTokenizer(AbstractTokenizer):
def init_from_project(self, config: Configuration) -> None: def init_from_project(self, config: Configuration) -> None:
""" Initialise the tokenizer from the project directory. """ Initialise the tokenizer from the project directory.
""" """
assert config.project_dir is not None
with connect(self.dsn) as conn: with connect(self.dsn) as conn:
self.normalization = properties.get_property(conn, DBCFG_NORMALIZATION) self.normalization = properties.get_property(conn, DBCFG_NORMALIZATION)
@@ -149,6 +152,8 @@ class LegacyTokenizer(AbstractTokenizer):
def update_sql_functions(self, config: Configuration) -> None: def update_sql_functions(self, config: Configuration) -> None:
""" Reimport the SQL functions for this tokenizer. """ Reimport the SQL functions for this tokenizer.
""" """
assert config.project_dir is not None
with connect(self.dsn) as conn: with connect(self.dsn) as conn:
max_word_freq = properties.get_property(conn, DBCFG_MAXWORDFREQ) max_word_freq = properties.get_property(conn, DBCFG_MAXWORDFREQ)
modulepath = config.DATABASE_MODULE_PATH or \ modulepath = config.DATABASE_MODULE_PATH or \
@@ -193,6 +198,8 @@ class LegacyTokenizer(AbstractTokenizer):
This is a special migration function for updating existing databases This is a special migration function for updating existing databases
to new software versions. to new software versions.
""" """
assert config.project_dir is not None
self.normalization = config.TERM_NORMALIZATION self.normalization = config.TERM_NORMALIZATION
module_dir = _install_module(config.DATABASE_MODULE_PATH, module_dir = _install_module(config.DATABASE_MODULE_PATH,
config.lib_dir.module, config.lib_dir.module,

View File

@@ -15,6 +15,7 @@ import subprocess
import urllib.request as urlrequest import urllib.request as urlrequest
from urllib.parse import urlencode from urllib.parse import urlencode
from nominatim.config import Configuration
from nominatim.typing import StrPath from nominatim.typing import StrPath
from nominatim.version import version_str from nominatim.version import version_str
from nominatim.db.connection import get_pg_env from nominatim.db.connection import get_pg_env
@@ -22,7 +23,7 @@ from nominatim.db.connection import get_pg_env
LOG = logging.getLogger() LOG = logging.getLogger()
def run_legacy_script(script: StrPath, *args: Union[int, str], def run_legacy_script(script: StrPath, *args: Union[int, str],
nominatim_env: Any, config: Configuration,
throw_on_fail: bool = False) -> int: throw_on_fail: bool = False) -> int:
""" Run a Nominatim PHP script with the given arguments. """ Run a Nominatim PHP script with the given arguments.
@@ -30,18 +31,18 @@ def run_legacy_script(script: StrPath, *args: Union[int, str],
then throw a `CalledProcessError` on a non-zero exit. then throw a `CalledProcessError` on a non-zero exit.
""" """
cmd = ['/usr/bin/env', 'php', '-Cq', cmd = ['/usr/bin/env', 'php', '-Cq',
str(nominatim_env.phplib_dir / 'admin' / script)] str(config.lib_dir.php / 'admin' / script)]
cmd.extend([str(a) for a in args]) cmd.extend([str(a) for a in args])
env = nominatim_env.config.get_os_env() env = config.get_os_env()
env['NOMINATIM_DATADIR'] = str(nominatim_env.data_dir) env['NOMINATIM_DATADIR'] = str(config.lib_dir.data)
env['NOMINATIM_SQLDIR'] = str(nominatim_env.sqllib_dir) env['NOMINATIM_SQLDIR'] = str(config.lib_dir.sql)
env['NOMINATIM_CONFIGDIR'] = str(nominatim_env.config_dir) env['NOMINATIM_CONFIGDIR'] = str(config.config_dir)
env['NOMINATIM_DATABASE_MODULE_SRC_PATH'] = str(nominatim_env.module_dir) env['NOMINATIM_DATABASE_MODULE_SRC_PATH'] = str(config.lib_dir.module)
if not env['NOMINATIM_OSM2PGSQL_BINARY']: if not env['NOMINATIM_OSM2PGSQL_BINARY']:
env['NOMINATIM_OSM2PGSQL_BINARY'] = str(nominatim_env.osm2pgsql_path) env['NOMINATIM_OSM2PGSQL_BINARY'] = str(config.lib_dir.osm2pgsql)
proc = subprocess.run(cmd, cwd=str(nominatim_env.project_dir), env=env, proc = subprocess.run(cmd, cwd=str(config.project_dir), env=env,
check=throw_on_fail) check=throw_on_fail)
return proc.returncode return proc.returncode

View File

@@ -216,6 +216,7 @@ def setup_website(basedir: Path, config: Configuration, conn: Connection) -> Non
LOG.info('Creating website directory.') LOG.info('Creating website directory.')
basedir.mkdir() basedir.mkdir()
assert config.project_dir is not None
template = dedent(f"""\ template = dedent(f"""\
<?php <?php

View File

@@ -43,7 +43,7 @@ class NominatimEnvironment:
self.code_coverage_path = config['PHPCOV'] self.code_coverage_path = config['PHPCOV']
self.code_coverage_id = 1 self.code_coverage_id = 1
self.default_config = Configuration(None, self.src_dir / 'settings').get_os_env() self.default_config = Configuration(None).get_os_env()
self.test_env = None self.test_env = None
self.template_db_done = False self.template_db_done = False
self.api_db_done = False self.api_db_done = False
@@ -130,13 +130,9 @@ class NominatimEnvironment:
def get_test_config(self): def get_test_config(self):
cfg = Configuration(Path(self.website_dir.name), self.src_dir / 'settings', cfg = Configuration(Path(self.website_dir.name), environ=self.test_env)
environ=self.test_env)
cfg.set_libdirs(module=self.build_dir / 'module', cfg.set_libdirs(module=self.build_dir / 'module',
osm2pgsql=self.build_dir / 'osm2pgsql' / 'osm2pgsql', osm2pgsql=self.build_dir / 'osm2pgsql' / 'osm2pgsql')
php=self.src_dir / 'lib-php',
sql=self.src_dir / 'lib-sql',
data=self.src_dir / 'data')
return cfg return cfg
def get_libpq_dsn(self): def get_libpq_dsn(self):
@@ -306,10 +302,6 @@ class NominatimEnvironment:
cli.nominatim(module_dir='', cli.nominatim(module_dir='',
osm2pgsql_path=str(self.build_dir / 'osm2pgsql' / 'osm2pgsql'), osm2pgsql_path=str(self.build_dir / 'osm2pgsql' / 'osm2pgsql'),
phplib_dir=str(self.src_dir / 'lib-php'),
sqllib_dir=str(self.src_dir / 'lib-sql'),
data_dir=str(self.src_dir / 'data'),
config_dir=str(self.src_dir / 'settings'),
cli_args=cmdline, cli_args=cmdline,
phpcgi_path='', phpcgi_path='',
environ=self.test_env) environ=self.test_env)

View File

@@ -53,11 +53,7 @@ def cli_call(src_dir):
def _call_nominatim(*args): def _call_nominatim(*args):
return nominatim.cli.nominatim(module_dir='MODULE NOT AVAILABLE', return nominatim.cli.nominatim(module_dir='MODULE NOT AVAILABLE',
osm2pgsql_path='OSM2PGSQL NOT AVAILABLE', osm2pgsql_path='OSM2PGSQL NOT AVAILABLE',
phplib_dir=str(src_dir / 'lib-php'),
data_dir=str(src_dir / 'data'),
phpcgi_path='/usr/bin/php-cgi', phpcgi_path='/usr/bin/php-cgi',
sqllib_dir=str(src_dir / 'lib-sql'),
config_dir=str(src_dir / 'settings'),
cli_args=args) cli_args=args)
return _call_nominatim return _call_nominatim

View File

@@ -82,19 +82,17 @@ def test_cli_export_command(cli_call, mock_run_legacy):
('restrict-to-osm-way', '727'), ('restrict-to-osm-way', '727'),
('restrict-to-osm-relation', '197532') ('restrict-to-osm-relation', '197532')
]) ])
def test_export_parameters(src_dir, tmp_path, param, value): def test_export_parameters(src_dir, tmp_path, param, value, monkeypatch):
(tmp_path / 'admin').mkdir() (tmp_path / 'admin').mkdir()
(tmp_path / 'admin' / 'export.php').write_text(f"""<?php (tmp_path / 'admin' / 'export.php').write_text(f"""<?php
exit(strpos(implode(' ', $_SERVER['argv']), '--{param} {value}') >= 0 ? 0 : 10); exit(strpos(implode(' ', $_SERVER['argv']), '--{param} {value}') >= 0 ? 0 : 10);
""") """)
monkeypatch.setattr(nominatim.paths, 'PHPLIB_DIR', tmp_path)
assert nominatim.cli.nominatim(module_dir='MODULE NOT AVAILABLE', assert nominatim.cli.nominatim(module_dir='MODULE NOT AVAILABLE',
osm2pgsql_path='OSM2PGSQL NOT AVAILABLE', osm2pgsql_path='OSM2PGSQL NOT AVAILABLE',
phplib_dir=str(tmp_path),
data_dir=str(src_dir / 'data'),
phpcgi_path='/usr/bin/php-cgi', phpcgi_path='/usr/bin/php-cgi',
sqllib_dir=str(src_dir / 'lib-sql'),
config_dir=str(src_dir / 'settings'),
cli_args=['export', '--' + param, value]) == 0 cli_args=['export', '--' + param, value]) == 0

View File

@@ -13,14 +13,10 @@ import nominatim.clicmd.api
@pytest.mark.parametrize("endpoint", (('search', 'reverse', 'lookup', 'details', 'status'))) @pytest.mark.parametrize("endpoint", (('search', 'reverse', 'lookup', 'details', 'status')))
def test_no_api_without_phpcgi(src_dir, endpoint): def test_no_api_without_phpcgi(endpoint):
assert nominatim.cli.nominatim(module_dir='MODULE NOT AVAILABLE', assert nominatim.cli.nominatim(module_dir='MODULE NOT AVAILABLE',
osm2pgsql_path='OSM2PGSQL NOT AVAILABLE', osm2pgsql_path='OSM2PGSQL NOT AVAILABLE',
phplib_dir=str(src_dir / 'lib-php'),
data_dir=str(src_dir / 'data'),
phpcgi_path=None, phpcgi_path=None,
sqllib_dir=str(src_dir / 'lib-sql'),
config_dir=str(src_dir / 'settings'),
cli_args=[endpoint]) == 1 cli_args=[endpoint]) == 1
@@ -36,24 +32,28 @@ def test_no_api_without_phpcgi(src_dir, endpoint):
class TestCliApiCall: class TestCliApiCall:
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup_cli_call(self, cli_call): def setup_cli_call(self, params, cli_call, mock_func_factory, tmp_path):
self.call_nominatim = cli_call self.mock_run_api = mock_func_factory(nominatim.clicmd.api, 'run_api_script')
def test_api_commands_simple(self, mock_func_factory, params, tmp_path): def _run():
return cli_call(*params, '--project-dir', str(tmp_path))
self.run_nominatim = _run
def test_api_commands_simple(self, tmp_path, params):
(tmp_path / 'website').mkdir() (tmp_path / 'website').mkdir()
(tmp_path / 'website' / (params[0] + '.php')).write_text('') (tmp_path / 'website' / (params[0] + '.php')).write_text('')
mock_run_api = mock_func_factory(nominatim.clicmd.api, 'run_api_script')
assert self.call_nominatim(*params, '--project-dir', str(tmp_path)) == 0 assert self.run_nominatim() == 0
assert mock_run_api.called == 1 assert self.mock_run_api.called == 1
assert mock_run_api.last_args[0] == params[0] assert self.mock_run_api.last_args[0] == params[0]
def test_bad_project_idr(self, mock_func_factory, params): def test_bad_project_dir(self):
mock_run_api = mock_func_factory(nominatim.clicmd.api, 'run_api_script') assert self.run_nominatim() == 1
assert self.call_nominatim(*params) == 1
QUERY_PARAMS = { QUERY_PARAMS = {
'search': ('--query', 'somewhere'), 'search': ('--query', 'somewhere'),

View File

@@ -15,6 +15,7 @@ import pytest
import nominatim.cli import nominatim.cli
import nominatim.indexer.indexer import nominatim.indexer.indexer
import nominatim.tools.replication import nominatim.tools.replication
import nominatim.tools.refresh
from nominatim.db import status from nominatim.db import status
@pytest.fixture @pytest.fixture
@@ -107,7 +108,7 @@ class TestCliReplication:
def test_replication_update_once_no_index(self, update_mock): def test_replication_update_once_no_index(self, update_mock):
assert self.call_nominatim('--once', '--no-index') == 0 assert self.call_nominatim('--once', '--no-index') == 0
assert str(update_mock.last_args[1]['osm2pgsql']) == 'OSM2PGSQL NOT AVAILABLE' assert str(update_mock.last_args[1]['osm2pgsql']).endswith('OSM2PGSQL NOT AVAILABLE')
def test_replication_update_custom_osm2pgsql(self, monkeypatch, update_mock): def test_replication_update_custom_osm2pgsql(self, monkeypatch, update_mock):

View File

@@ -14,23 +14,23 @@ from nominatim.config import Configuration, flatten_config_list
from nominatim.errors import UsageError from nominatim.errors import UsageError
@pytest.fixture @pytest.fixture
def make_config(src_dir): def make_config():
""" Create a configuration object from the given project directory. """ Create a configuration object from the given project directory.
""" """
def _mk_config(project_dir=None): def _mk_config(project_dir=None):
return Configuration(project_dir, src_dir / 'settings') return Configuration(project_dir)
return _mk_config return _mk_config
@pytest.fixture @pytest.fixture
def make_config_path(src_dir, tmp_path): def make_config_path(tmp_path):
""" Create a configuration object with project and config directories """ Create a configuration object with project and config directories
in a temporary directory. in a temporary directory.
""" """
def _mk_config(): def _mk_config():
(tmp_path / 'project').mkdir() (tmp_path / 'project').mkdir()
(tmp_path / 'config').mkdir() (tmp_path / 'config').mkdir()
conf = Configuration(tmp_path / 'project', src_dir / 'settings') conf = Configuration(tmp_path / 'project')
conf.config_dir = tmp_path / 'config' conf.config_dir = tmp_path / 'config'
return conf return conf

View File

@@ -21,7 +21,7 @@ def test_config(src_dir, tmp_path):
""" """
(tmp_path / 'project').mkdir() (tmp_path / 'project').mkdir()
(tmp_path / 'config').mkdir() (tmp_path / 'config').mkdir()
conf = Configuration(tmp_path / 'project', src_dir / 'settings') conf = Configuration(tmp_path / 'project')
conf.config_dir = tmp_path / 'config' conf.config_dir = tmp_path / 'config'
return conf return conf

View File

@@ -107,24 +107,18 @@ def table_factory(temp_db_cursor):
@pytest.fixture @pytest.fixture
def def_config(src_dir): def def_config():
cfg = Configuration(None, src_dir / 'settings') cfg = Configuration(None)
cfg.set_libdirs(module='.', osm2pgsql='.', cfg.set_libdirs(module='.', osm2pgsql='.')
php=src_dir / 'lib-php',
sql=src_dir / 'lib-sql',
data=src_dir / 'data')
return cfg return cfg
@pytest.fixture @pytest.fixture
def project_env(src_dir, tmp_path): def project_env(tmp_path):
projdir = tmp_path / 'project' projdir = tmp_path / 'project'
projdir.mkdir() projdir.mkdir()
cfg = Configuration(projdir, src_dir / 'settings') cfg = Configuration(projdir)
cfg.set_libdirs(module='.', osm2pgsql='.', cfg.set_libdirs(module='.', osm2pgsql='.')
php=src_dir / 'lib-php',
sql=src_dir / 'lib-sql',
data=src_dir / 'data')
return cfg return cfg
@@ -214,9 +208,8 @@ def osmline_table(temp_db_with_extensions, table_factory):
@pytest.fixture @pytest.fixture
def sql_preprocessor_cfg(tmp_path, table_factory, temp_db_with_extensions): def sql_preprocessor_cfg(tmp_path, table_factory, temp_db_with_extensions):
table_factory('country_name', 'partition INT', ((0, ), (1, ), (2, ))) table_factory('country_name', 'partition INT', ((0, ), (1, ), (2, )))
cfg = Configuration(None, SRC_DIR.resolve() / 'settings') cfg = Configuration(None)
cfg.set_libdirs(module='.', osm2pgsql='.', php=SRC_DIR / 'lib-php', cfg.set_libdirs(module='.', osm2pgsql='.', sql=tmp_path)
sql=tmp_path, data=SRC_DIR / 'data')
return cfg return cfg

View File

@@ -12,31 +12,28 @@ import subprocess
import pytest import pytest
from nominatim.config import Configuration
import nominatim.tools.exec_utils as exec_utils import nominatim.tools.exec_utils as exec_utils
import nominatim.paths
class TestRunLegacyScript: class TestRunLegacyScript:
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup_nominatim_env(self, tmp_path, def_config): def setup_nominatim_env(self, tmp_path, monkeypatch):
tmp_phplib_dir = tmp_path / 'phplib' tmp_phplib_dir = tmp_path / 'phplib'
tmp_phplib_dir.mkdir() tmp_phplib_dir.mkdir()
(tmp_phplib_dir / 'admin').mkdir() (tmp_phplib_dir / 'admin').mkdir()
class _NominatimEnv: monkeypatch.setattr(nominatim.paths, 'PHPLIB_DIR', tmp_phplib_dir)
config = def_config
phplib_dir = tmp_phplib_dir
data_dir = Path('data')
project_dir = Path('.')
sqllib_dir = Path('lib-sql')
config_dir = Path('settings')
module_dir = 'module'
osm2pgsql_path = 'osm2pgsql'
self.testenv = _NominatimEnv self.phplib_dir = tmp_phplib_dir
self.config = Configuration(tmp_path)
self.config.set_libdirs(module='.', osm2pgsql='default_osm2pgsql',
php=tmp_phplib_dir)
def mk_script(self, code): def mk_script(self, code):
codefile = self.testenv.phplib_dir / 'admin' / 't.php' codefile = self.phplib_dir / 'admin' / 't.php'
codefile.write_text('<?php\n' + code + '\n') codefile.write_text('<?php\n' + code + '\n')
return 't.php' return 't.php'
@@ -46,25 +43,25 @@ class TestRunLegacyScript:
def test_run_legacy_return_exit_code(self, return_code): def test_run_legacy_return_exit_code(self, return_code):
fname = self.mk_script('exit({});'.format(return_code)) fname = self.mk_script('exit({});'.format(return_code))
assert return_code == \ assert return_code == \
exec_utils.run_legacy_script(fname, nominatim_env=self.testenv) exec_utils.run_legacy_script(fname, config=self.config)
def test_run_legacy_return_throw_on_fail(self): def test_run_legacy_return_throw_on_fail(self):
fname = self.mk_script('exit(11);') fname = self.mk_script('exit(11);')
with pytest.raises(subprocess.CalledProcessError): with pytest.raises(subprocess.CalledProcessError):
exec_utils.run_legacy_script(fname, nominatim_env=self.testenv, exec_utils.run_legacy_script(fname, config=self.config,
throw_on_fail=True) throw_on_fail=True)
def test_run_legacy_return_dont_throw_on_success(self): def test_run_legacy_return_dont_throw_on_success(self):
fname = self.mk_script('exit(0);') fname = self.mk_script('exit(0);')
assert exec_utils.run_legacy_script(fname, nominatim_env=self.testenv, assert exec_utils.run_legacy_script(fname, config=self.config,
throw_on_fail=True) == 0 throw_on_fail=True) == 0
def test_run_legacy_use_given_module_path(self): def test_run_legacy_use_given_module_path(self):
fname = self.mk_script("exit($_SERVER['NOMINATIM_DATABASE_MODULE_PATH'] == '' ? 0 : 23);") fname = self.mk_script("exit($_SERVER['NOMINATIM_DATABASE_MODULE_PATH'] == '' ? 0 : 23);")
assert exec_utils.run_legacy_script(fname, nominatim_env=self.testenv) == 0 assert exec_utils.run_legacy_script(fname, config=self.config) == 0
def test_run_legacy_do_not_overwrite_module_path(self, monkeypatch): def test_run_legacy_do_not_overwrite_module_path(self, monkeypatch):
@@ -72,13 +69,13 @@ class TestRunLegacyScript:
fname = self.mk_script( fname = self.mk_script(
"exit($_SERVER['NOMINATIM_DATABASE_MODULE_PATH'] == 'other' ? 0 : 1);") "exit($_SERVER['NOMINATIM_DATABASE_MODULE_PATH'] == 'other' ? 0 : 1);")
assert exec_utils.run_legacy_script(fname, nominatim_env=self.testenv) == 0 assert exec_utils.run_legacy_script(fname, config=self.config) == 0
def test_run_legacy_default_osm2pgsql_binary(self, monkeypatch): def test_run_legacy_default_osm2pgsql_binary(self, monkeypatch):
fname = self.mk_script("exit($_SERVER['NOMINATIM_OSM2PGSQL_BINARY'] == 'osm2pgsql' ? 0 : 23);") fname = self.mk_script("exit($_SERVER['NOMINATIM_OSM2PGSQL_BINARY'] == 'default_osm2pgsql' ? 0 : 23);")
assert exec_utils.run_legacy_script(fname, nominatim_env=self.testenv) == 0 assert exec_utils.run_legacy_script(fname, config=self.config) == 0
def test_run_legacy_override_osm2pgsql_binary(self, monkeypatch): def test_run_legacy_override_osm2pgsql_binary(self, monkeypatch):
@@ -86,7 +83,7 @@ class TestRunLegacyScript:
fname = self.mk_script("exit($_SERVER['NOMINATIM_OSM2PGSQL_BINARY'] == 'somethingelse' ? 0 : 23);") fname = self.mk_script("exit($_SERVER['NOMINATIM_OSM2PGSQL_BINARY'] == 'somethingelse' ? 0 : 23);")
assert exec_utils.run_legacy_script(fname, nominatim_env=self.testenv) == 0 assert exec_utils.run_legacy_script(fname, config=self.config) == 0
class TestRunApiScript: class TestRunApiScript: