]> git.openstreetmap.org Git - nominatim.git/blobdiff - nominatim/cli.py
api: generalize error handling
[nominatim.git] / nominatim / cli.py
index 8c2136f410988d37a2d1578b63ad6a7682f02d17..d34ef118ed9a48609c455616207d36387e006802 100644 (file)
@@ -9,6 +9,7 @@ Command-line interface to the Nominatim functions for import, update,
 database administration and querying.
 """
 from typing import Optional, Any, List, Union
 database administration and querying.
 """
 from typing import Optional, Any, List, Union
+import importlib
 import logging
 import os
 import sys
 import logging
 import os
 import sys
@@ -60,7 +61,7 @@ class CommandlineParser:
     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
         """
-        text = f'Nominatim version {version.version_str()}'
+        text = f'Nominatim version {version.NOMINATIM_VERSION!s}'
         if version.GIT_COMMIT_HASH is not None:
             text += f' ({version.GIT_COMMIT_HASH})'
         return text
         if version.GIT_COMMIT_HASH is not None:
             text += f' ({version.GIT_COMMIT_HASH})'
         return text
@@ -100,9 +101,7 @@ class CommandlineParser:
             self.parser.print_help()
             return 1
 
             self.parser.print_help()
             return 1
 
-        for arg in ('module_dir', 'osm2pgsql_path', 'phplib_dir', 'sqllib_dir',
-                    'data_dir', 'config_dir', 'phpcgi_path'):
-            setattr(args, arg, Path(kwargs[arg]))
+        args.phpcgi_path = Path(kwargs['phpcgi_path'])
         args.project_dir = Path(args.project_dir).resolve()
 
         if 'cli_args' not in kwargs:
         args.project_dir = Path(args.project_dir).resolve()
 
         if 'cli_args' not in kwargs:
@@ -111,13 +110,10 @@ class CommandlineParser:
                                 datefmt='%Y-%m-%d %H:%M:%S',
                                 level=max(4 - args.verbose, 1) * 10)
 
                                 datefmt='%Y-%m-%d %H:%M:%S',
                                 level=max(4 - args.verbose, 1) * 10)
 
-        args.config = Configuration(args.project_dir, args.config_dir,
+        args.config = Configuration(args.project_dir,
                                     environ=kwargs.get('environ', os.environ))
                                     environ=kwargs.get('environ', os.environ))
-        args.config.set_libdirs(module=args.module_dir,
-                                osm2pgsql=args.osm2pgsql_path,
-                                php=args.phplib_dir,
-                                sql=args.sqllib_dir,
-                                data=args.data_dir)
+        args.config.set_libdirs(module=kwargs['module_dir'],
+                                osm2pgsql=kwargs['osm2pgsql_path'])
 
         log = logging.getLogger()
         log.warning('Using project directory: %s', str(args.project_dir))
 
         log = logging.getLogger()
         log.warning('Using project directory: %s', str(args.project_dir))
@@ -195,17 +191,22 @@ class QueryExport:
         if args.restrict_to_osm_relation:
             params.extend(('--restrict-to-osm-relation', args.restrict_to_osm_relation))
 
         if args.restrict_to_osm_relation:
             params.extend(('--restrict-to-osm-relation', args.restrict_to_osm_relation))
 
-        return run_legacy_script('export.php', *params, nominatim_env=args)
+        return run_legacy_script('export.php', *params, config=args.config)
 
 
 class AdminServe:
     """\
     Start a simple web server for serving the API.
 
 
 
 class AdminServe:
     """\
     Start a simple web server for serving the API.
 
-    This command starts the built-in PHP webserver to serve the website
+    This command starts a built-in webserver to serve the website
     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.
+
     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
     """
 
@@ -213,10 +214,40 @@ class AdminServe:
         group = parser.add_argument_group('Server arguments')
         group.add_argument('--server', default='127.0.0.1:8088',
                            help='The address the server will listen to.')
         group = parser.add_argument_group('Server arguments')
         group.add_argument('--server', default='127.0.0.1:8088',
                            help='The address the server will listen to.')
+        group.add_argument('--engine', default='php',
+                           choices=('php', 'sanic', 'falcon', 'starlette'),
+                           help='Webserver framework to run. (default: php)')
 
 
     def run(self, args: NominatimArgs) -> int:
 
 
     def run(self, args: NominatimArgs) -> int:
-        run_php_server(args.server, args.project_dir / 'website')
+        if args.engine == 'php':
+            run_php_server(args.server, args.project_dir / 'website')
+        else:
+            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
+
+            if args.engine == 'sanic':
+                server_module = importlib.import_module('nominatim.server.sanic.server')
+
+                app = server_module.get_application(args.project_dir)
+                app.run(host=host, port=port, debug=True, single_process=True)
+            else:
+                import uvicorn # pylint: disable=import-outside-toplevel
+
+                if args.engine == 'falcon':
+                    server_module = importlib.import_module('nominatim.server.falcon.server')
+                elif args.engine == 'starlette':
+                    server_module = importlib.import_module('nominatim.server.starlette.server')
+
+                app = server_module.get_application(args.project_dir)
+                uvicorn.run(app, host=host, port=port)
+
         return 0
 
 
         return 0