]> git.openstreetmap.org Git - nominatim.git/blobdiff - nominatim/clicmd/api.py
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / nominatim / clicmd / api.py
index 7185d97c14bf659f406e56d6c1b10e916467a278..ab7d16582cb5b8f8ba93800080166c4b7ecdb192 100644 (file)
@@ -1,9 +1,16 @@
+# 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.
 """
 Subcommand definitions for API calls from the command line.
 """
 import logging
 
 """
 Subcommand definitions for API calls from the command line.
 """
 import logging
 
-from ..tools.exec_utils import run_api_script
+from nominatim.tools.exec_utils import run_api_script
+from nominatim.errors import UsageError
 
 # Do not repeat documentation of subcommand classes.
 # pylint: disable=C0111
 
 # Do not repeat documentation of subcommand classes.
 # pylint: disable=C0111
@@ -20,19 +27,19 @@ STRUCTURED_QUERY = (
 )
 
 EXTRADATA_PARAMS = (
 )
 
 EXTRADATA_PARAMS = (
-    ('addressdetails', 'Include a breakdown of the address into elements.'),
-    ('extratags', """Include additional information if available
-                     (e.g. wikipedia link, opening hours)."""),
-    ('namedetails', 'Include a list of alternative names.')
+    ('addressdetails', 'Include a breakdown of the address into elements'),
+    ('extratags', ("Include additional information if available "
+                   "(e.g. wikipedia link, opening hours)")),
+    ('namedetails', 'Include a list of alternative names')
 )
 
 DETAILS_SWITCHES = (
 )
 
 DETAILS_SWITCHES = (
-    ('addressdetails', 'Include a breakdown of the address into elements.'),
-    ('keywords', 'Include a list of name keywords and address keywords.'),
-    ('linkedplaces', 'Include a details of places that are linked with this one.'),
-    ('hierarchy', 'Include details of places lower in the address hierarchy.'),
-    ('group_hierarchy', 'Group the places by type.'),
-    ('polygon_geojson', 'Include geometry of result.')
+    ('addressdetails', 'Include a breakdown of the address into elements'),
+    ('keywords', 'Include a list of name keywords and address keywords'),
+    ('linkedplaces', 'Include a details of places that are linked with this one'),
+    ('hierarchy', 'Include details of places lower in the address hierarchy'),
+    ('group_hierarchy', 'Group the places by type'),
+    ('polygon_geojson', 'Include geometry of result')
 )
 
 def _add_api_output_arguments(parser):
 )
 
 def _add_api_output_arguments(parser):
@@ -47,15 +54,32 @@ def _add_api_output_arguments(parser):
                        help='Preferred language order for presenting search results')
     group.add_argument('--polygon-output',
                        choices=['geojson', 'kml', 'svg', 'text'],
                        help='Preferred language order for presenting search results')
     group.add_argument('--polygon-output',
                        choices=['geojson', 'kml', 'svg', 'text'],
-                       help='Output geometry of results as a GeoJSON, KML, SVG or WKT.')
+                       help='Output geometry of results as a GeoJSON, KML, SVG or WKT')
     group.add_argument('--polygon-threshold', type=float, metavar='TOLERANCE',
     group.add_argument('--polygon-threshold', type=float, metavar='TOLERANCE',
-                       help="""Simplify output geometry.
-                               Parameter is difference tolerance in degrees.""")
+                       help=("Simplify output geometry."
+                             "Parameter is difference tolerance in degrees."))
 
 
 
 
+def _run_api(endpoint, args, params):
+    script_file = args.project_dir / 'website' / (endpoint + '.php')
+
+    if not script_file.exists():
+        LOG.error("Cannot find API script file.\n\n"
+                  "Make sure to run 'nominatim' from the project directory \n"
+                  "or use the option --project-dir.")
+        raise UsageError("API script not found.")
+
+    return run_api_script(endpoint, args.project_dir,
+                          phpcgi_bin=args.phpcgi_path, params=params)
+
 class APISearch:
     """\
 class APISearch:
     """\
-    Execute API search query.
+    Execute a search query.
+
+    This command works exactly the same as if calling the /search endpoint on
+    the web API. See the online documentation for more details on the
+    various parameters:
+    https://nominatim.org/release-docs/latest/api/Search/
     """
 
     @staticmethod
     """
 
     @staticmethod
@@ -70,7 +94,7 @@ class APISearch:
 
         group = parser.add_argument_group('Result limitation')
         group.add_argument('--countrycodes', metavar='CC,..',
 
         group = parser.add_argument_group('Result limitation')
         group.add_argument('--countrycodes', metavar='CC,..',
-                           help='Limit search results to one or more countries.')
+                           help='Limit search results to one or more countries')
         group.add_argument('--exclude_place_ids', metavar='ID,..',
                            help='List of search object to be excluded')
         group.add_argument('--limit', type=int,
         group.add_argument('--exclude_place_ids', metavar='ID,..',
                            help='List of search object to be excluded')
         group.add_argument('--limit', type=int,
@@ -90,7 +114,7 @@ class APISearch:
         if args.query:
             params = dict(q=args.query)
         else:
         if args.query:
             params = dict(q=args.query)
         else:
-            params = {k : getattr(args, k) for k, _ in STRUCTURED_QUERY if getattr(args, k)}
+            params = {k: getattr(args, k) for k, _ in STRUCTURED_QUERY if getattr(args, k)}
 
         for param, _ in EXTRADATA_PARAMS:
             if getattr(args, param):
 
         for param, _ in EXTRADATA_PARAMS:
             if getattr(args, param):
@@ -109,12 +133,16 @@ class APISearch:
         if not args.dedupe:
             params['dedupe'] = '0'
 
         if not args.dedupe:
             params['dedupe'] = '0'
 
-        return run_api_script('search', args.project_dir,
-                              phpcgi_bin=args.phpcgi_path, params=params)
+        return _run_api('search', args, params)
 
 class APIReverse:
     """\
     Execute API reverse query.
 
 class APIReverse:
     """\
     Execute API reverse query.
+
+    This command works exactly the same as if calling the /reverse endpoint on
+    the web API. See the online documentation for more details on the
+    various parameters:
+    https://nominatim.org/release-docs/latest/api/Reverse/
     """
 
     @staticmethod
     """
 
     @staticmethod
@@ -132,15 +160,13 @@ class APIReverse:
 
     @staticmethod
     def run(args):
 
     @staticmethod
     def run(args):
-        params = dict(lat=args.lat, lon=args.lon)
+        params = dict(lat=args.lat, lon=args.lon, format=args.format)
         if args.zoom is not None:
             params['zoom'] = args.zoom
 
         for param, _ in EXTRADATA_PARAMS:
             if getattr(args, param):
                 params[param] = '1'
         if args.zoom is not None:
             params['zoom'] = args.zoom
 
         for param, _ in EXTRADATA_PARAMS:
             if getattr(args, param):
                 params[param] = '1'
-        if args.format:
-            params['format'] = args.format
         if args.lang:
             params['accept-language'] = args.lang
         if args.polygon_output:
         if args.lang:
             params['accept-language'] = args.lang
         if args.polygon_output:
@@ -148,13 +174,17 @@ class APIReverse:
         if args.polygon_threshold:
             params['polygon_threshold'] = args.polygon_threshold
 
         if args.polygon_threshold:
             params['polygon_threshold'] = args.polygon_threshold
 
-        return run_api_script('reverse', args.project_dir,
-                              phpcgi_bin=args.phpcgi_path, params=params)
+        return _run_api('reverse', args, params)
 
 
 class APILookup:
     """\
     Execute API lookup query.
 
 
 class APILookup:
     """\
     Execute API lookup query.
+
+    This command works exactly the same as if calling the /lookup endpoint on
+    the web API. See the online documentation for more details on the
+    various parameters:
+    https://nominatim.org/release-docs/latest/api/Lookup/
     """
 
     @staticmethod
     """
 
     @staticmethod
@@ -169,13 +199,11 @@ class APILookup:
 
     @staticmethod
     def run(args):
 
     @staticmethod
     def run(args):
-        params = dict(osm_ids=','.join(args.ids))
+        params = dict(osm_ids=','.join(args.ids), format=args.format)
 
         for param, _ in EXTRADATA_PARAMS:
             if getattr(args, param):
                 params[param] = '1'
 
         for param, _ in EXTRADATA_PARAMS:
             if getattr(args, param):
                 params[param] = '1'
-        if args.format:
-            params['format'] = args.format
         if args.lang:
             params['accept-language'] = args.lang
         if args.polygon_output:
         if args.lang:
             params['accept-language'] = args.lang
         if args.polygon_output:
@@ -183,13 +211,17 @@ class APILookup:
         if args.polygon_threshold:
             params['polygon_threshold'] = args.polygon_threshold
 
         if args.polygon_threshold:
             params['polygon_threshold'] = args.polygon_threshold
 
-        return run_api_script('lookup', args.project_dir,
-                              phpcgi_bin=args.phpcgi_path, params=params)
+        return _run_api('lookup', args, params)
 
 
 class APIDetails:
     """\
     Execute API details query.
 
 
 class APIDetails:
     """\
     Execute API details query.
+
+    This command works exactly the same as if calling the /details endpoint on
+    the web API. See the online documentation for more details on the
+    various parameters:
+    https://nominatim.org/release-docs/latest/api/Details/
     """
 
     @staticmethod
     """
 
     @staticmethod
@@ -203,10 +235,10 @@ class APIDetails:
         objs.add_argument('--relation', '-r', type=int,
                           help="Look up the OSM relation with the given ID.")
         objs.add_argument('--place_id', '-p', type=int,
         objs.add_argument('--relation', '-r', type=int,
                           help="Look up the OSM relation with the given ID.")
         objs.add_argument('--place_id', '-p', type=int,
-                          help='Database internal identifier of the OSM object to look up.')
+                          help='Database internal identifier of the OSM object to look up')
         group.add_argument('--class', dest='object_class',
         group.add_argument('--class', dest='object_class',
-                           help="""Class type to disambiguated multiple entries
-                                   of the same object.""")
+                           help=("Class type to disambiguated multiple entries "
+                                 "of the same object."))
 
         group = parser.add_argument_group('Output arguments')
         for name, desc in DETAILS_SWITCHES:
 
         group = parser.add_argument_group('Output arguments')
         for name, desc in DETAILS_SWITCHES:
@@ -228,14 +260,20 @@ class APIDetails:
             params['class'] = args.object_class
         for name, _ in DETAILS_SWITCHES:
             params[name] = '1' if getattr(args, name) else '0'
             params['class'] = args.object_class
         for name, _ in DETAILS_SWITCHES:
             params[name] = '1' if getattr(args, name) else '0'
+        if args.lang:
+            params['accept-language'] = args.lang
 
 
-        return run_api_script('details', args.project_dir,
-                              phpcgi_bin=args.phpcgi_path, params=params)
+        return _run_api('details', args, params)
 
 
 class APIStatus:
     """\
     Execute API status query.
 
 
 class APIStatus:
     """\
     Execute API status query.
+
+    This command works exactly the same as if calling the /status endpoint on
+    the web API. See the online documentation for more details on the
+    various parameters:
+    https://nominatim.org/release-docs/latest/api/Status/
     """
 
     @staticmethod
     """
 
     @staticmethod
@@ -246,6 +284,4 @@ class APIStatus:
 
     @staticmethod
     def run(args):
 
     @staticmethod
     def run(args):
-        return run_api_script('status', args.project_dir,
-                              phpcgi_bin=args.phpcgi_path,
-                              params=dict(format=args.format))
+        return _run_api('status', args, dict(format=args.format))