Skip to content

Commit 8b41b80

Browse files
authored
Merge pull request #3517 from lonvia/improve-custom-formatter
Extend use of custom result formatters to CLI tool
2 parents fdb3fc2 + feb8cc2 commit 8b41b80

File tree

9 files changed

+273
-126
lines changed

9 files changed

+273
-126
lines changed

docs/customize/Result-Formatting.md

+88-5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ For example, let us extend the result for the status call in text format
6666
and add the server URL. Such a formatter would look like this:
6767

6868
``` python
69+
from nominatim_api import StatusResult
70+
6971
@dispatch.format_func(StatusResult, 'text')
7072
def _format_status_text(result, _):
7173
header = 'Status for server nominatim.openstreetmap.org'
@@ -86,19 +88,39 @@ as adding formatting functions for all result types using the custom
8688
format name:
8789

8890
``` python
91+
from nominatim_api import StatusResult
92+
8993
@dispatch.format_func(StatusResult, 'chatty')
9094
def _format_status_text(result, _):
9195
if result.status:
9296
return f"The server is currently not running. {result.message}"
9397

94-
return f"Good news! The server is running just fine."
98+
return "Good news! The server is running just fine."
9599
```
96100

97101
That's all. Nominatim will automatically pick up the new format name and
98-
will allow the user to use it. Make sure to really define formatters for
99-
**all** result types. If they are for endpoints that you do not intend to
100-
use, you can simply return some static string but the function needs to be
101-
there.
102+
will allow the user to use it. There is no need to implement formatter
103+
functions for all the result types, when you invent a new one. The
104+
available formats will be determined for each API endpoint separately.
105+
To find out which formats are available, you can use the `--list-formats`
106+
option of the CLI tool:
107+
108+
```
109+
me@machine:planet-project$ nominatim status --list-formats
110+
2024-08-16 19:54:00: Using project directory: /home/nominatim/planet-project
111+
text
112+
json
113+
chatty
114+
debug
115+
me@machine:planet-project$
116+
```
117+
118+
The `debug` format listed in the last line will always appear. It is a
119+
special format that enables debug output via the command line (the same
120+
as the `debug=1` parameter enables for the server API). To not clash
121+
with this built-in function, you shouldn't name your own format 'debug'.
122+
123+
### Content type of new formats
102124

103125
All responses will be returned with the content type application/json by
104126
default. If your format produces a different content type, you need
@@ -117,6 +139,67 @@ The `content_types` module used above provides constants for the most
117139
frequent content types. You set the content type to an arbitrary string,
118140
if the content type you need is not available.
119141

142+
## Formatting error messages
143+
144+
Any exception thrown during processing of a request is given to
145+
a special error formatting function. It takes the requested content type,
146+
the status code and the error message. It should return the error message
147+
in a form appropriate for the given content type.
148+
149+
You can overwrite the default formatting function with the decorator
150+
`error_format_func`:
151+
152+
``` python
153+
import nominatim_api.server.content_types as ct
154+
155+
@dispatch.error_format_func
156+
def _format_error(content_type: str, msg: str, status: int) -> str:
157+
if content_type == ct.CONTENT_XML:
158+
return f"""<?xml version="1.0" encoding="UTF-8" ?>
159+
<message>{msg}</message>
160+
"""
161+
if content_type == ct.CONTENT_JSON:
162+
return f'"{msg}"'
163+
164+
return f"ERROR: {msg}"
165+
```
166+
167+
168+
## Debugging custom formatters
169+
170+
The easiest way to try out your custom formatter is by using the Nominatim
171+
CLI commands. Custom formats can be chosen with the `--format` parameter:
172+
173+
```
174+
me@machine:planet-project$ nominatim status --format chatty
175+
2024-08-16 19:54:00: Using project directory: /home/nominatim/planet-project
176+
Good news! The server is running just fine.
177+
me@machine:planet-project$
178+
```
179+
180+
They will also emit full error messages when there is a problem with the
181+
code you need to debug.
182+
183+
!!! danger
184+
In some cases, when you make an error with your import statement, the
185+
CLI will not give you an error but instead tell you, that the API
186+
commands are no longer available:
187+
188+
me@machine: nominatim status
189+
usage: nominatim [-h] [--version] {import,freeze,replication,special-phrases,add-data,index,refresh,admin} ...
190+
nominatim: error: argument subcommand: invalid choice: 'status'
191+
192+
This happens because the CLI tool is meant to still work when the
193+
nominatim-api package is not installed. Import errors involving
194+
`nominatim_api` are interpreted as "package not installed".
195+
196+
Use the help command to find out which is the offending import that
197+
could not be found:
198+
199+
me@machine: nominatim -h
200+
... [other help text] ...
201+
Nominatim API package not found (was looking for module: nominatim_api.xxx).
202+
120203
## Reference
121204

122205
### FormatDispatcher

src/nominatim_api/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
SearchResult as SearchResult,
4040
SearchResults as SearchResults)
4141
from .localization import (Locales as Locales)
42-
from .result_formatting import (FormatDispatcher as FormatDispatcher)
42+
from .result_formatting import (FormatDispatcher as FormatDispatcher,
43+
load_format_dispatcher as load_format_dispatcher)
4344

4445
from .version import NOMINATIM_API_VERSION as __version__

src/nominatim_api/v1/__init__.py

-6
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,3 @@
1111
#pylint: disable=useless-import-alias
1212

1313
from .server_glue import ROUTES as ROUTES
14-
15-
from . import format as _format
16-
17-
list_formats = _format.dispatch.list_formats
18-
supports_format = _format.dispatch.supports_format
19-
format_result = _format.dispatch.format_result

src/nominatim_db/cli.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ def get_set_parser() -> CommandlineParser:
243243
raise ex
244244

245245
parser.parser.epilog = \
246-
'\n\nNominatim API package not found. The following commands are not available:'\
246+
f'\n\nNominatim API package not found (was looking for module: {ex.name}).'\
247+
'\nThe following commands are not available:'\
247248
'\n export, convert, serve, search, reverse, lookup, details, status'\
248249
"\n\nRun 'pip install nominatim-api' to install the package."
249250

0 commit comments

Comments
 (0)