Compare commits

..

1 Commits

Author SHA1 Message Date
Sarah Hoffmann
212b69799c adapt docs for release 2025-10-29 11:08:42 +01:00
13 changed files with 42 additions and 171 deletions

View File

@@ -110,14 +110,17 @@ Then you can install Nominatim with:
pip install nominatim-db nominatim-api
## Downloading and building Nominatim
## Downloading and building Nominatim from source
The following instructions are only relevant, if you want to build and
install Nominatim **from source**.
### Downloading the latest release
You can download the [latest release from nominatim.org](https://nominatim.org/downloads/).
The release contains all necessary files. Just unpack it.
### Downloading the latest development version
### Downloading the source for the latest development version
If you want to install latest development version from github:
@@ -131,7 +134,7 @@ The development version does not include the country grid. Download it separatel
wget -O Nominatim/data/country_osm_grid.sql.gz https://nominatim.org/data/country_grid.sql.gz
```
### Building Nominatim
### Building Nominatim from source
Nominatim is easiest to run from its own virtual environment. To create one, run:

View File

@@ -52,15 +52,6 @@ To run the functional tests, do
pytest test/bdd
You can run a single feature file using expression matching:
pytest test/bdd -k osm2pgsql/import/entrances.feature
This even works for running single tests by adding the line number of the
scenario header like that:
pytest test/bdd -k 'osm2pgsql/import/entrances.feature and L4'
The BDD tests create databases for the tests. You can set name of the databases
through configuration variables in your `pytest.ini`:

View File

@@ -341,22 +341,6 @@ BEGIN
END IF;
END IF;
IF bnd.extratags ? 'wikidata' THEN
FOR linked_placex IN
SELECT * FROM placex
WHERE placex.class = 'place' AND placex.osm_type = 'N'
AND placex.extratags ? 'wikidata' -- needed to select right index
AND placex.extratags->'wikidata' = bnd.extratags->'wikidata'
AND (placex.linked_place_id is null or placex.linked_place_id = bnd.place_id)
AND placex.rank_search < 26
AND _st_covers(bnd.geometry, placex.geometry)
ORDER BY lower(name->'name') = bnd_name desc
LOOP
{% if debug %}RAISE WARNING 'Found wikidata-matching place node %', linked_placex.osm_id;{% endif %}
RETURN linked_placex;
END LOOP;
END IF;
-- If extratags has a place tag, look for linked nodes by their place type.
-- Area and node still have to have the same name.
IF bnd.extratags ? 'place' and bnd.extratags->'place' != 'postcode'
@@ -377,6 +361,22 @@ BEGIN
END LOOP;
END IF;
IF bnd.extratags ? 'wikidata' THEN
FOR linked_placex IN
SELECT * FROM placex
WHERE placex.class = 'place' AND placex.osm_type = 'N'
AND placex.extratags ? 'wikidata' -- needed to select right index
AND placex.extratags->'wikidata' = bnd.extratags->'wikidata'
AND (placex.linked_place_id is null or placex.linked_place_id = bnd.place_id)
AND placex.rank_search < 26
AND _st_covers(bnd.geometry, placex.geometry)
ORDER BY lower(name->'name') = bnd_name desc
LOOP
{% if debug %}RAISE WARNING 'Found wikidata-matching place node %', linked_placex.osm_id;{% endif %}
RETURN linked_placex;
END LOOP;
END IF;
-- Name searches can be done for ways as well as relations
IF bnd_name is not null THEN
{% if debug %}RAISE WARNING 'Looking for nodes with matching names';{% endif %}
@@ -874,7 +874,7 @@ BEGIN
-- Remove linkage, if we have computed a different new linkee.
UPDATE placex SET linked_place_id = null, indexed_status = 2
WHERE linked_place_id = NEW.place_id
and (linked_place is null or place_id != linked_place);
and (linked_place is null or linked_place_id != linked_place);
-- update not necessary for osmline, cause linked_place_id does not exist
-- Postcodes are just here to compute the centroids. They are not searchable

View File

@@ -1,4 +1,4 @@
site_name: Nominatim Manual
site_name: Nominatim 5.2.0 Manual
theme:
font: false
name: material

View File

@@ -7,8 +7,6 @@
"""
Server implementation using the falcon webserver framework.
"""
from __future__ import annotations
from typing import Optional, Mapping, Any, List, cast
from pathlib import Path
import asyncio
@@ -163,7 +161,7 @@ class APIMiddleware:
def __init__(self, project_dir: Path, environ: Optional[Mapping[str, str]]) -> None:
self.api = NominatimAPIAsync(project_dir, environ)
self.app: Optional[App[Request, Response]] = None
self.app: Optional[App] = None
@property
def config(self) -> Configuration:
@@ -171,7 +169,7 @@ class APIMiddleware:
"""
return self.api.config
def set_app(self, app: App[Request, Response]) -> None:
def set_app(self, app: App) -> None:
""" Set the Falcon application this middleware is connected to.
"""
self.app = app
@@ -195,7 +193,7 @@ class APIMiddleware:
def get_application(project_dir: Path,
environ: Optional[Mapping[str, str]] = None) -> App[Request, Response]:
environ: Optional[Mapping[str, str]] = None) -> App:
""" Create a Nominatim Falcon ASGI application.
"""
apimw = APIMiddleware(project_dir, environ)
@@ -217,7 +215,7 @@ def get_application(project_dir: Path,
return app
def run_wsgi() -> App[Request, Response]:
def run_wsgi() -> App:
""" Entry point for uvicorn.
Make sure uvicorn is run from the project directory.

View File

@@ -29,9 +29,6 @@ class CountryPostcodeMatcher:
self.norm_pattern = re.compile(f'\\s*(?:{country_code.upper()}[ -]?)?({pc_pattern})\\s*')
self.pattern = re.compile(pc_pattern)
# We want to exclude 0000, 00-000, 000 00 etc
self.zero_pattern = re.compile(r'^[0\- ]+$')
self.output = config.get('output', r'\g<0>')
def match(self, postcode: str) -> Optional[Match[str]]:
@@ -43,10 +40,7 @@ class CountryPostcodeMatcher:
normalized = self.norm_pattern.fullmatch(postcode.upper())
if normalized:
match = self.pattern.fullmatch(normalized.group(1))
if match and self.zero_pattern.match(match.string):
return None
return match
return self.pattern.fullmatch(normalized.group(1))
return None

View File

@@ -9,7 +9,6 @@ Fixtures for BDD test steps
"""
import sys
import json
import re
from pathlib import Path
import psycopg
@@ -21,8 +20,7 @@ sys.path.insert(0, str(SRC_DIR / 'src'))
import pytest
from pytest_bdd.parsers import re as step_parse
from pytest_bdd import given, when, then, scenario
from pytest_bdd.feature import get_features
from pytest_bdd import given, when, then
pytest.register_assert_rewrite('utils')
@@ -375,57 +373,3 @@ def check_place_missing_lines(db_conn, table, osm_type, osm_id, osm_class):
with db_conn.cursor() as cur:
assert cur.execute(sql, params).fetchone()[0] == 0
if pytest.version_tuple >= (8, 0, 0):
def pytest_pycollect_makemodule(module_path, parent):
return BddTestCollector.from_parent(parent, path=module_path)
class BddTestCollector(pytest.Module):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def collect(self):
for item in super().collect():
yield item
if hasattr(self.obj, 'PYTEST_BDD_SCENARIOS'):
for path in self.obj.PYTEST_BDD_SCENARIOS:
for feature in get_features([str(Path(self.path.parent, path).resolve())]):
yield FeatureFile.from_parent(self,
name=str(Path(path, feature.rel_filename)),
path=Path(feature.filename),
feature=feature)
# borrowed from pytest-bdd: src/pytest_bdd/scenario.py
def make_python_name(string: str) -> str:
"""Make python attribute name out of a given string."""
string = re.sub(r"\W", "", string.replace(" ", "_"))
return re.sub(r"^\d+_*", "", string).lower()
class FeatureFile(pytest.File):
class obj:
pass
def __init__(self, feature, **kwargs):
self.feature = feature
super().__init__(**kwargs)
def collect(self):
for sname, sobject in self.feature.scenarios.items():
class_name = f"L{sobject.line_number}"
test_name = "test_" + make_python_name(sname)
@scenario(self.feature.filename, sname)
def _test():
pass
tclass = type(class_name, (),
{test_name: staticmethod(_test)})
setattr(self.obj, class_name, tclass)
yield pytest.Class.from_parent(self, name=class_name, obj=tclass)

View File

@@ -15,7 +15,7 @@ import xml.etree.ElementTree as ET
import pytest
from pytest_bdd.parsers import re as step_parse
from pytest_bdd import when, given, then
from pytest_bdd import scenarios, when, given, then
from nominatim_db import cli
from nominatim_db.config import Configuration
@@ -150,8 +150,4 @@ def parse_api_json_response(api_response, fmt, num):
return result
if pytest.version_tuple >= (8, 0, 0):
PYTEST_BDD_SCENARIOS = ['features/api']
else:
from pytest_bdd import scenarios
scenarios('features/api')
scenarios('features/api')

View File

@@ -15,7 +15,7 @@ import re
import psycopg
import pytest
from pytest_bdd import when, then, given
from pytest_bdd import scenarios, when, then, given
from pytest_bdd.parsers import re as step_parse
from utils.place_inserter import PlaceColumn
@@ -276,8 +276,4 @@ def then_check_interpolation_table_negative(db_conn, oid):
assert cur.fetchone()[0] == 0
if pytest.version_tuple >= (8, 0, 0):
PYTEST_BDD_SCENARIOS = ['features/db']
else:
from pytest_bdd import scenarios
scenarios('features/db')
scenarios('features/db')

View File

@@ -11,7 +11,7 @@ import asyncio
import random
import pytest
from pytest_bdd import when, then, given
from pytest_bdd import scenarios, when, then, given
from pytest_bdd.parsers import re as step_parse
from nominatim_db import cli
@@ -106,8 +106,4 @@ def check_place_content(db_conn, datatable, node_grid, table, exact):
check_table_content(db_conn, table, datatable, grid=node_grid, exact=bool(exact))
if pytest.version_tuple >= (8, 0, 0):
PYTEST_BDD_SCENARIOS = ['features/osm2pgsql']
else:
from pytest_bdd import scenarios
scenarios('features/osm2pgsql')
scenarios('features/osm2pgsql')

View File

@@ -237,9 +237,3 @@ def test_postcode_default_pattern_pass(sanitize, postcode):
@pytest.mark.sanitizer_params(convert_to_address=False, default_pattern='[A-Z0-9- ]{3,12}')
def test_postcode_default_pattern_fail(sanitize, postcode):
assert sanitize(country='an', postcode=postcode) == []
@pytest.mark.parametrize("postcode", ('00000', '00-000', 'PL-00000', 'PL 00-000'))
@pytest.mark.sanitizer_params(convert_to_address=False)
def test_postcode_zeros(sanitize, postcode):
assert sanitize(country='pl', postcode=postcode) == []

View File

@@ -25,7 +25,7 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
libbz2-dev libpq-dev liblua5.3-dev lua5.3 lua-dkjson \
nlohmann-json3-dev postgresql-14-postgis-3 \
postgresql-contrib-14 postgresql-14-postgis-3-scripts \
libicu-dev virtualenv git
libicu-dev virtualenv
#
# System Configuration
@@ -97,23 +97,6 @@ fi #DOCS:
# Building and Configuration
# --------------------------
#
# Get the source code from Github and change into the source directory
#
if [ "x$1" == "xyes" ]; then #DOCS: :::sh
cd $USERHOME
git clone https://github.com/osm-search/Nominatim.git
cd Nominatim
else #DOCS:
cd $USERHOME/Nominatim #DOCS:
fi #DOCS:
# When installing the latest source from github, you also need to
# download the country grid:
if [ ! -f data/country_osm_grid.sql.gz ]; then #DOCS: :::sh
wget -O data/country_osm_grid.sql.gz https://nominatim.org/data/country_grid.sql.gz
fi #DOCS:
# Nominatim needs osm2pgsql >= 1.8. The version that comes with Ubuntu is
# too old. Download and compile your own:
@@ -124,7 +107,6 @@ fi #DOCS:
cmake ../osm2pgsql
make
sudo make install
cd $USERHOME/Nominatim
# Nominatim should be installed in a separate Python virtual environment.
# Create the virtual environment:
@@ -137,8 +119,7 @@ fi #DOCS:
# Now install Nominatim using pip:
cd $USERHOME/Nominatim
$USERHOME/nominatim-venv/bin/pip install packaging/nominatim-db
$USERHOME/nominatim-venv/bin/pip install nominatim-db
# Nominatim is now ready to use. You can continue with
# [importing a database from OSM data](../admin/Import.md). If you want to set up
@@ -154,9 +135,7 @@ fi #DOCS:
# To install all packages, run:
#DOCS:```sh
$USERHOME/nominatim-venv/bin/pip install falcon uvicorn gunicorn
cd $USERHOME/Nominatim
$USERHOME/nominatim-venv/bin/pip install packaging/nominatim-api
$USERHOME/nominatim-venv/bin/pip install falcon uvicorn gunicorn nominatim-api
#DOCS:```

View File

@@ -21,7 +21,7 @@ export DEBIAN_FRONTEND=noninteractive #DOCS:
# Now you can install all packages needed for Nominatim:
sudo apt-get install -y osm2pgsql postgresql-postgis postgresql-postgis-scripts \
pkg-config libicu-dev virtualenv git
pkg-config libicu-dev virtualenv
#
@@ -94,23 +94,6 @@ fi #DOCS:
# Building and Configuration
# --------------------------
#
# Get the source code from Github and change into the source directory
#
if [ "x$1" == "xyes" ]; then #DOCS: :::sh
cd $USERHOME
git clone https://github.com/osm-search/Nominatim.git
cd Nominatim
else #DOCS:
cd $USERHOME/Nominatim #DOCS:
fi #DOCS:
# When installing the latest source from github, you also need to
# download the country grid:
if [ ! -f data/country_osm_grid.sql.gz ]; then #DOCS: :::sh
wget -O data/country_osm_grid.sql.gz https://nominatim.org/data/country_grid.sql.gz
fi #DOCS:
# Nominatim should be installed in a separate Python virtual environment.
# Create the virtual environment:
@@ -122,8 +105,7 @@ fi #DOCS:
# Now install Nominatim using pip:
cd $USERHOME/Nominatim
$USERHOME/nominatim-venv/bin/pip install packaging/nominatim-db
$USERHOME/nominatim-venv/bin/pip install nominatim-db
# Nominatim is now ready to use. The nominatim binary is available at
# `$USERHOME/venv/bin/nominatim`. If you want to have 'nominatim' in your
@@ -147,9 +129,7 @@ fi #DOCS:
# To install all packages, run:
#DOCS:```sh
$USERHOME/nominatim-venv/bin/pip install falcon uvicorn gunicorn
cd $USERHOME/Nominatim
$USERHOME/nominatim-venv/bin/pip install packaging/nominatim-api
$USERHOME/nominatim-venv/bin/pip install falcon uvicorn gunicorn nominatim-api
#DOCS:```
# Next you need to create a systemd job that runs Nominatim on gunicorn.