From 157c3cccd1dd6b8d1e3dc3751e8324497c25c616 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Thu, 29 Aug 2024 22:23:52 +0200 Subject: [PATCH 1/4] fix permalink character --- docs/extra.css | 5 +++++ mkdocs.yml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/extra.css b/docs/extra.css index 155fa1aa71..1decc4789e 100644 --- a/docs/extra.css +++ b/docs/extra.css @@ -34,3 +34,8 @@ th { .md-footer__inner { display: none; } + +.headerlink { + filter: grayscale(100%); + font-size: 80%; +} diff --git a/mkdocs.yml b/mkdocs.yml index 3c1ff80bb6..16d62c05e6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -68,7 +68,7 @@ markdown_extensions: alternate_style: true - def_list - toc: - permalink:  + permalink: 🔗 extra_css: [extra.css, styles.css] exclude_docs: | mk_install_instructions.py From 8f30a32466c36d5a989e7f754df315cbd9314126 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Tue, 10 Sep 2024 16:08:43 +0200 Subject: [PATCH 2/4] docs: avoid loading external fonts --- mkdocs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index 16d62c05e6..aa6e1aa0f5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,8 +1,11 @@ site_name: Nominatim Manual theme: + font: false name: material features: - navigation.tabs + plugins: + - privacy copyright: Copyright © Nominatim developer community docs_dir: docs site_url: https://nominatim.org From f52212abbd21d5139e893b53d75fff5a17893010 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Thu, 29 Aug 2024 22:45:20 +0200 Subject: [PATCH 3/4] docs: rework library getting started --- docs/library/Getting-Started.md | 114 +++++++++++++++++--------------- 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/docs/library/Getting-Started.md b/docs/library/Getting-Started.md index 1f5b2baa53..6206022ff2 100644 --- a/docs/library/Getting-Started.md +++ b/docs/library/Getting-Started.md @@ -1,16 +1,21 @@ # Getting Started -The Nominatim search frontend can directly be used as a Python library in -scripts and applications. When you have imported your own Nominatim database, -then it is no longer necessary to run a full web service for it and access -the database through http requests. There are -also less constraints on the kinds of data that can be accessed. The library -allows to get access to more detailed information about the objects saved -in the database. - -!!! danger - The library interface is currently in an experimental stage. There might - be some smaller adjustments to the public interface until the next version. +The Nominatim search frontend is implemented as a Python library and can as +such directly be used in Python scripts and applications. You don't need to +set up a web frontend and access it through HTTP calls. The library gives +direct access to the Nominatim database through similar search functions as +offered by the web API. In addition, it will give you a more complete and +detailed view on the search objects stored in the database. + +!!! warning + + The Nominatim library is used for accessing a local Nominatim database. + It is not meant to be used against web services of Nominatim like the + one on https://nominatim.openstreetmap.org. If you need a Python library + to access these web services, have a look at + [GeoPy](https://geopy.readthedocs.io). Don't forget to consult the + usage policy of the service you want to use before accessing such + a web service. ## Installation @@ -19,6 +24,10 @@ Follow the [installation](../admin/Installation.md) and [import](../admin/Import.md) instructions to set up your database. The Nominatim frontend library is contained in the Python package `nominatim-api`. +You can install the latest released version directly from pip: + + pip install nominatim-api + To install the package from the source tree directly, run: pip install packaging/nominatim-api @@ -36,15 +45,13 @@ This code snippet implements a simple search for the town of 'Brugge': !!! example === "NominatimAPIAsync" ``` python - from pathlib import Path import asyncio import nominatim_api as napi async def search(query): - api = napi.NominatimAPIAsync(Path('.')) - - return await api.search(query) + async with napi.NominatimAPIAsync() as api: + return await api.search(query) results = asyncio.run(search('Brugge')) if not results: @@ -55,13 +62,10 @@ This code snippet implements a simple search for the town of 'Brugge': === "NominatimAPI" ``` python - from pathlib import Path - import nominatim_api as napi - api = napi.NominatimAPI(Path('.')) - - results = api.search('Brugge') + with napi.NominatimAPI() as api: + results = api.search('Brugge') if not results: print('Cannot find Brugge') @@ -93,25 +97,31 @@ The same configuration mechanism is used with the Nominatim API library. You should therefore be sure you are familiar with the section. -The constructor of the 'Nominatim API class' takes one mandatory parameter: -the path to the [project directory](../admin/Import.md#creating-the-project-directory). -You should have set up this directory as part of the Nominatim import. -Any configuration found in the `.env` file in this directory will automatically -used. +There are three different ways, how configuration options can be set for +a 'Nominatim API class'. When you have set up your Nominatim database, you +have normally created a [project directory](../admin/Import.md#creating-the-project-directory) +which stores the various configuration and customization files that Nominatim +needs. You may pass the location of the project directory to your +'Nominatim API class' constructor and it will read the .env file in the +directory and set the configuration accordingly. You may also configure Nominatim by setting environment variables. -Normally, Nominatim will check the operating system environment. This can be -overwritten by giving the constructor a dictionary of configuration parameters. +Normally Nominatim will check the operating system environment. Lets +say you want to look up 'Brugge' in the special database named 'belgium' instead of the +standard 'nominatim' database. You can run the example script above like this: -Let us look up 'Brugge' in the special database named 'belgium' instead of the -standard 'nominatim' database: +``` +NOMINATIM_DATABASE_DSN=pgsql:dbname=belgium python3 example.py +``` + +The third option to configure the library is to hand in the configuration +parameters into the 'Nominatim API class'. Changing the database would look +like this: !!! example === "NominatimAPIAsync" ``` python - from pathlib import Path import asyncio - import nominatim_api as napi config_params = { @@ -119,50 +129,53 @@ standard 'nominatim' database: } async def search(query): - api = napi.NominatimAPIAsync(Path('.'), environ=config_params) - - return await api.search(query) + async with napi.NominatimAPIAsync(environ=config_params) as api: + return await api.search(query) results = asyncio.run(search('Brugge')) ``` === "NominatimAPI" ``` python - from pathlib import Path - import nominatim_api as napi config_params = { 'NOMINATIM_DATABASE_DSN': 'pgsql:dbname=belgium' } - api = napi.NominatimAPI(Path('.'), environ=config_params) - - results = api.search('Brugge') + with napi.NominatimAPI(environ=config_params) as api: + results = api.search('Brugge') ``` +When the `environ` parameter is given, then only configuration variables +from this dictionary will be used. + ### Presenting results to humans -All search functions return the raw results from the database. There is no -full human-readable label. To create such a label, you need two things: +All search functions return full result objects from the database. Such a +result object contains lots of details: names, address information, OSM tags etc. +This gives you lots of flexibility what to do with the results. + +One of the most common things to get is some kind of human-readable label +that describes the result in a compact form. Usually this would be the name +of the object and some parts of the address to explain where in the world +it is. To create such a label, you need two things: * the address details of the place -* adapt the result to the language you wish to use for display +* all names for the label adapted to the language you wish to use for display Again searching for 'Brugge', this time with a nicely formatted result: !!! example === "NominatimAPIAsync" ``` python - from pathlib import Path import asyncio import nominatim_api as napi async def search(query): - api = napi.NominatimAPIAsync(Path('.')) - - return await api.search(query, address_details=True) + async with napi.NominatimAPIAsync() as api: + return await api.search(query, address_details=True) results = asyncio.run(search('Brugge')) @@ -174,13 +187,10 @@ Again searching for 'Brugge', this time with a nicely formatted result: === "NominatimAPI" ``` python - from pathlib import Path - import nominatim_api as napi - api = napi.NominatimAPI(Path('.')) - - results = api.search('Brugge', address_details=True) + with napi.NominatimAPI() as api: + results = api.search('Brugge', address_details=True) locale = napi.Locales(['fr', 'en']) for i, result in enumerate(results): @@ -236,7 +246,7 @@ Bruges, Flandre-Occidentale, Flandre, Belgique This is a fairly simple way to create a human-readable description. The place information in `address_rows` contains further information about each -place. For example, which OSM `adlin_level` was used, what category the place +place. For example, which OSM `admin_level` was used, what category the place belongs to or what rank Nominatim has assigned. Use this to adapt the output to local address formats. From fe0ade81f59ae7a77fbf4a0493171289969a8184 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Tue, 10 Sep 2024 20:36:27 +0200 Subject: [PATCH 4/4] docs: improve contents listing --- docs/api/Overview.md | 2 -- docs/library/Configuration.md | 12 ++++---- docs/library/Getting-Started.md | 45 +++++++++++++++++++++++++---- docs/library/Low-Level-DB-Access.md | 3 +- mkdocs.yml | 2 ++ 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/docs/api/Overview.md b/docs/api/Overview.md index 383eef5365..aac5771517 100644 --- a/docs/api/Overview.md +++ b/docs/api/Overview.md @@ -1,5 +1,3 @@ -### Nominatim API - !!! Attention The current version of Nominatim implements two different search frontends: the old PHP frontend and the new Python frontend. They have a very similar diff --git a/docs/library/Configuration.md b/docs/library/Configuration.md index e13470e9fc..713d1c53a0 100644 --- a/docs/library/Configuration.md +++ b/docs/library/Configuration.md @@ -1,11 +1,13 @@ # Configuration When using Nominatim through the library, it can be configured in exactly -the same way as when running as a service. This means that you should have -created a [project directory](../admin/Import.md#creating-the-project-directory) -which contains all files belonging to the Nominatim instance. It can also contain -an `.env` file with configuration options. Setting configuration parameters -via environment variables works as well. +the same way as when running as a service. You may instantiate the library +against the [project directory](../admin/Import.md#creating-the-project-directory) +of your Nominatim installation. It contains all files belonging to the +Nominatim instance. This may include an `.env` file with configuration options. +Setting configuration parameters via environment variables works as well. +Alternatively to using the operating system's environment, a set of +configuration parameters may also be passed to the Nomiantim API object. Configuration options are resolved in the following order: diff --git a/docs/library/Getting-Started.md b/docs/library/Getting-Started.md index 6206022ff2..9f81724a15 100644 --- a/docs/library/Getting-Started.md +++ b/docs/library/Getting-Started.md @@ -34,7 +34,7 @@ To install the package from the source tree directly, run: Usually you would want to run this in a virtual environment. -### A simple search example +## A simple search example To query the Nominatim database you need to first set up a connection. This is done by creating an Nominatim API object. This object exposes all the @@ -88,7 +88,7 @@ implementations. The documentation itself will usually refer only to available only for the synchronous or asynchronous version, this will be explicitly mentioned. -### Defining which database to use +## Defining which database to use The [Configuration](../admin/Import.md#configuration-setup-in-env) section explains how Nominatim is configured using the @@ -103,7 +103,41 @@ have normally created a [project directory](../admin/Import.md#creating-the-proj which stores the various configuration and customization files that Nominatim needs. You may pass the location of the project directory to your 'Nominatim API class' constructor and it will read the .env file in the -directory and set the configuration accordingly. +directory and set the configuration accordingly. Here is the simple search +example, using the configuration from a pre-defined project directory in +`/srv/nominatim-project`: + +!!! example + === "NominatimAPIAsync" + ``` python + import asyncio + + import nominatim_api as napi + + async def search(query): + async with napi.NominatimAPIAsync('/srv/nominatim-project') as api: + return await api.search(query) + + results = asyncio.run(search('Brugge')) + if not results: + print('Cannot find Brugge') + else: + print(f'Found a place at {results[0].centroid.x},{results[0].centroid.y}') + ``` + + === "NominatimAPI" + ``` python + import nominatim_api as napi + + with napi.NominatimAPI('/srv/nominatim-project') as api: + results = api.search('Brugge') + + if not results: + print('Cannot find Brugge') + else: + print(f'Found a place at {results[0].centroid.x},{results[0].centroid.y}') + ``` + You may also configure Nominatim by setting environment variables. Normally Nominatim will check the operating system environment. Lets @@ -148,9 +182,10 @@ like this: ``` When the `environ` parameter is given, then only configuration variables -from this dictionary will be used. +from this dictionary will be used. The operating system's environment +variables will be ignored. -### Presenting results to humans +## Presenting results to humans All search functions return full result objects from the database. Such a result object contains lots of details: names, address information, OSM tags etc. diff --git a/docs/library/Low-Level-DB-Access.md b/docs/library/Low-Level-DB-Access.md index 84a40b9b04..9669906122 100644 --- a/docs/library/Low-Level-DB-Access.md +++ b/docs/library/Low-Level-DB-Access.md @@ -24,12 +24,11 @@ the placex table: ``` import asyncio -from pathlib import Path import sqlalchemy as sa from nominatim_api import NominatimAPIAsync async def print_table_size(): - api = NominatimAPIAsync(Path('.')) + api = NominatimAPIAsync() async with api.begin() as conn: cnt = await conn.scalar(sa.select(sa.func.count()).select_from(conn.t.placex)) diff --git a/mkdocs.yml b/mkdocs.yml index aa6e1aa0f5..b6fd0ec7f5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,6 +4,7 @@ theme: name: material features: - navigation.tabs + - toc.integrate plugins: - privacy copyright: Copyright © Nominatim developer community @@ -71,6 +72,7 @@ markdown_extensions: alternate_style: true - def_list - toc: + toc_depth: 4 permalink: 🔗 extra_css: [extra.css, styles.css] exclude_docs: |