]> git.openstreetmap.org Git - nominatim.git/blobdiff - src/nominatim_db/cli.py
look up all places at once
[nominatim.git] / src / nominatim_db / cli.py
index 41684fa1dbe9e37bf9c1d3e1a2c9ded9e7767715..f5f74208d3c7ba64eb01d5ed367e17738d6d63db 100644 (file)
@@ -14,17 +14,18 @@ import logging
 import os
 import sys
 import argparse
 import os
 import sys
 import argparse
+import asyncio
 from pathlib import Path
 
 from .config import Configuration
 from .errors import UsageError
 from pathlib import Path
 
 from .config import Configuration
 from .errors import UsageError
-from .tools.exec_utils import run_php_server
 from . import clicmd
 from . import version
 from .clicmd.args import NominatimArgs, Subcommand
 
 LOG = logging.getLogger()
 
 from . import clicmd
 from . import version
 from .clicmd.args import NominatimArgs, Subcommand
 
 LOG = logging.getLogger()
 
+
 class CommandlineParser:
     """ Wraps some of the common functions for parsing the command line
         and setting up subcommands.
 class CommandlineParser:
     """ Wraps some of the common functions for parsing the command line
         and setting up subcommands.
@@ -57,7 +58,6 @@ class CommandlineParser:
         group.add_argument('-j', '--threads', metavar='NUM', type=int,
                            help='Number of parallel threads to use')
 
         group.add_argument('-j', '--threads', metavar='NUM', type=int,
                            help='Number of parallel threads to use')
 
-
     def nominatim_version_text(self) -> str:
         """ Program name and version number as string
         """
     def nominatim_version_text(self) -> str:
         """ Program name and version number as string
         """
@@ -66,7 +66,6 @@ class CommandlineParser:
             text += f' ({version.GIT_COMMIT_HASH})'
         return text
 
             text += f' ({version.GIT_COMMIT_HASH})'
         return text
 
-
     def add_subcommand(self, name: str, cmd: Subcommand) -> None:
         """ Add a subcommand to the parser. The subcommand must be a class
             with a function add_args() that adds the parameters for the
     def add_subcommand(self, name: str, cmd: Subcommand) -> None:
         """ Add a subcommand to the parser. The subcommand must be a class
             with a function add_args() that adds the parameters for the
@@ -82,7 +81,6 @@ class CommandlineParser:
         parser.set_defaults(command=cmd)
         cmd.add_args(parser)
 
         parser.set_defaults(command=cmd)
         cmd.add_args(parser)
 
-
     def run(self, **kwargs: Any) -> int:
         """ Parse the command line arguments of the program and execute the
             appropriate subcommand.
     def run(self, **kwargs: Any) -> int:
         """ Parse the command line arguments of the program and execute the
             appropriate subcommand.
@@ -111,17 +109,18 @@ class CommandlineParser:
 
         args.config = Configuration(args.project_dir,
                                     environ=kwargs.get('environ', os.environ))
 
         args.config = Configuration(args.project_dir,
                                     environ=kwargs.get('environ', os.environ))
-        args.config.set_libdirs(module=kwargs['module_dir'],
-                                osm2pgsql=kwargs['osm2pgsql_path'])
+        args.config.set_libdirs(osm2pgsql=kwargs['osm2pgsql_path'])
 
         log = logging.getLogger()
         log.warning('Using project directory: %s', str(args.project_dir))
 
         try:
 
         log = logging.getLogger()
         log.warning('Using project directory: %s', str(args.project_dir))
 
         try:
-            return args.command.run(args)
+            ret = args.command.run(args)
+
+            return ret
         except UsageError as exception:
             if log.isEnabledFor(logging.DEBUG):
         except UsageError as exception:
             if log.isEnabledFor(logging.DEBUG):
-                raise # use Python's exception printing
+                raise  # use Python's exception printing
             log.fatal('FATAL: %s', exception)
 
         # If we get here, then execution has failed in some way.
             log.fatal('FATAL: %s', exception)
 
         # If we get here, then execution has failed in some way.
@@ -138,7 +137,6 @@ class CommandlineParser:
 # a subcommand.
 #
 # No need to document the functions each time.
 # a subcommand.
 #
 # No need to document the functions each time.
-# pylint: disable=C0111
 class AdminServe:
     """\
     Start a simple web server for serving the API.
 class AdminServe:
     """\
     Start a simple web server for serving the API.
@@ -147,10 +145,10 @@ class AdminServe:
     from the current project directory. This webserver is only suitable
     for testing and development. Do not use it in production setups!
 
     from the current project directory. This webserver is only suitable
     for testing and development. Do not use it in production setups!
 
-    There are different webservers available. The default 'php' engine
-    runs the classic PHP frontend. The other engines are Python servers
-    which run the new Python frontend code. This is highly experimental
-    at the moment and may not include the full API.
+    There are two different webserver implementations for Python available:
+    falcon (the default) and starlette. You need to make sure the
+    appropriate Python packages as well as the uvicorn package are
+    installed to use this function.
 
     By the default, the webserver can be accessed at: http://127.0.0.1:8088
     """
 
     By the default, the webserver can be accessed at: http://127.0.0.1:8088
     """
@@ -160,32 +158,33 @@ class AdminServe:
         group.add_argument('--server', default='127.0.0.1:8088',
                            help='The address the server will listen to.')
         group.add_argument('--engine', default='falcon',
         group.add_argument('--server', default='127.0.0.1:8088',
                            help='The address the server will listen to.')
         group.add_argument('--engine', default='falcon',
-                           choices=('php', 'falcon', 'starlette'),
+                           choices=('falcon', 'starlette'),
                            help='Webserver framework to run. (default: falcon)')
 
                            help='Webserver framework to run. (default: falcon)')
 
-
     def run(self, args: NominatimArgs) -> int:
     def run(self, args: NominatimArgs) -> int:
-        if args.engine == 'php':
-            if args.config.lib_dir.php is None:
-                raise UsageError("PHP frontend not configured.")
-            run_php_server(args.server, args.project_dir / 'website')
+        asyncio.run(self.run_uvicorn(args))
+
+        return 0
+
+    async def run_uvicorn(self, args: NominatimArgs) -> None:
+        import uvicorn
+
+        server_info = args.server.split(':', 1)
+        host = server_info[0]
+        if len(server_info) > 1:
+            if not server_info[1].isdigit():
+                raise UsageError('Invalid format for --server parameter. Use <host>:<port>')
+            port = int(server_info[1])
         else:
         else:
-            import uvicorn # pylint: disable=import-outside-toplevel
-            server_info = args.server.split(':', 1)
-            host = server_info[0]
-            if len(server_info) > 1:
-                if not server_info[1].isdigit():
-                    raise UsageError('Invalid format for --server parameter. Use <host>:<port>')
-                port = int(server_info[1])
-            else:
-                port = 8088
+            port = 8088
 
 
-            server_module = importlib.import_module(f'nominatim_api.server.{args.engine}.server')
+        server_module = importlib.import_module(f'nominatim_api.server.{args.engine}.server')
 
 
-            app = server_module.get_application(args.project_dir)
-            uvicorn.run(app, host=host, port=port)
+        app = server_module.get_application(args.project_dir)
 
 
-        return 0
+        config = uvicorn.Config(app, host=host, port=port)
+        server = uvicorn.Server(config)
+        await server.serve()
 
 
 def get_set_parser() -> CommandlineParser:
 
 
 def get_set_parser() -> CommandlineParser:
@@ -222,15 +221,15 @@ def get_set_parser() -> CommandlineParser:
         parser.add_subcommand('details', apicmd.APIDetails())
         parser.add_subcommand('status', apicmd.APIStatus())
     except ModuleNotFoundError as ex:
         parser.add_subcommand('details', apicmd.APIDetails())
         parser.add_subcommand('status', apicmd.APIStatus())
     except ModuleNotFoundError as ex:
-        if not ex.name or 'nominatim_api' not in ex.name: # pylint: disable=E1135
+        if not ex.name or 'nominatim_api' not in ex.name:
             raise ex
 
         parser.parser.epilog = \
             raise ex
 
         parser.parser.epilog = \
-            '\n\nNominatim API package not found. The following commands are not available:'\
+            f'\n\nNominatim API package not found (was looking for module: {ex.name}).'\
+            '\nThe following commands are not available:'\
             '\n    export, convert, serve, search, reverse, lookup, details, status'\
             "\n\nRun 'pip install nominatim-api' to install the package."
 
             '\n    export, convert, serve, search, reverse, lookup, details, status'\
             "\n\nRun 'pip install nominatim-api' to install the package."
 
-
     return parser
 
 
     return parser