]> git.openstreetmap.org Git - nominatim.git/blobdiff - nominatim/cli.py
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / nominatim / cli.py
index b3d9eee6d735742ef61941379a00ca5477930d68..f911023b9507fd99fb6115d0c6f015dd9a959088 100644 (file)
@@ -1,3 +1,9 @@
+# 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.
 """
 Command-line interface to the Nominatim functions for import, update,
 database administration and querying.
 """
 Command-line interface to the Nominatim functions for import, update,
 database administration and querying.
@@ -8,12 +14,12 @@ import sys
 import argparse
 from pathlib import Path
 
 import argparse
 from pathlib import Path
 
-from .config import Configuration
-from .tools.exec_utils import run_legacy_script, run_php_server
-from .errors import UsageError
-from . import clicmd
-from .clicmd.args import NominatimArgs
-from .tools import tiger_data
+from nominatim.config import Configuration
+from nominatim.tools.exec_utils import run_legacy_script, run_php_server
+from nominatim.errors import UsageError
+from nominatim import clicmd
+from nominatim import version
+from nominatim.clicmd.args import NominatimArgs
 
 LOG = logging.getLogger()
 
 
 LOG = logging.getLogger()
 
@@ -31,6 +37,10 @@ class CommandlineParser:
         self.subs = self.parser.add_subparsers(title='available commands',
                                                dest='subcommand')
 
         self.subs = self.parser.add_subparsers(title='available commands',
                                                dest='subcommand')
 
+        # Global arguments that only work if no sub-command given
+        self.parser.add_argument('--version', action='store_true',
+                                 help='Print Nominatim version and exit')
+
         # Arguments added to every sub-command
         self.default_args = argparse.ArgumentParser(add_help=False)
         group = self.default_args.add_argument_group('Default arguments')
         # Arguments added to every sub-command
         self.default_args = argparse.ArgumentParser(add_help=False)
         group = self.default_args.add_argument_group('Default arguments')
@@ -46,6 +56,14 @@ 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')
 
+    @staticmethod
+    def nominatim_version_text():
+        """ Program name and version number as string
+        """
+        text = f'Nominatim version {version.version_str()}'
+        if version.GIT_COMMIT_HASH is not None:
+            text += f' ({version.GIT_COMMIT_HASH})'
+        return text
 
     def add_subcommand(self, name, cmd):
         """ Add a subcommand to the parser. The subcommand must be a class
 
     def add_subcommand(self, name, cmd):
         """ Add a subcommand to the parser. The subcommand must be a class
@@ -65,7 +83,14 @@ class CommandlineParser:
             appropriate subcommand.
         """
         args = NominatimArgs()
             appropriate subcommand.
         """
         args = NominatimArgs()
-        self.parser.parse_args(args=kwargs.get('cli_args'), namespace=args)
+        try:
+            self.parser.parse_args(args=kwargs.get('cli_args'), namespace=args)
+        except SystemExit:
+            return 1
+
+        if args.version:
+            print(CommandlineParser.nominatim_version_text())
+            return 0
 
         if args.subcommand is None:
             self.parser.print_help()
 
         if args.subcommand is None:
             self.parser.print_help()
@@ -84,6 +109,11 @@ class CommandlineParser:
 
         args.config = Configuration(args.project_dir, args.config_dir,
                                     environ=kwargs.get('environ', os.environ))
 
         args.config = Configuration(args.project_dir, args.config_dir,
                                     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)
 
         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))
@@ -99,7 +129,7 @@ class CommandlineParser:
         return 1
 
 
         return 1
 
 
-##### Subcommand classes
+# Subcommand classes
 #
 # Each class needs to implement two functions: add_args() adds the CLI parameters
 # for the subfunction, run() executes the subcommand.
 #
 # Each class needs to implement two functions: add_args() adds the CLI parameters
 # for the subfunction, run() executes the subcommand.
@@ -110,85 +140,6 @@ class CommandlineParser:
 #
 # No need to document the functions each time.
 # pylint: disable=C0111
 #
 # No need to document the functions each time.
 # pylint: disable=C0111
-# Using non-top-level imports to make pyosmium optional for replication only.
-# pylint: disable=E0012,C0415
-
-
-class SetupSpecialPhrases:
-    """\
-    Maintain special phrases.
-    """
-
-    @staticmethod
-    def add_args(parser):
-        group = parser.add_argument_group('Input arguments')
-        group.add_argument('--from-wiki', action='store_true',
-                           help='Pull special phrases from the OSM wiki.')
-        group = parser.add_argument_group('Output arguments')
-        group.add_argument('-o', '--output', default='-',
-                           help="""File to write the preprocessed phrases to.
-                                   If omitted, it will be written to stdout.""")
-
-    @staticmethod
-    def run(args):
-        if args.output != '-':
-            raise NotImplementedError('Only output to stdout is currently implemented.')
-        return run_legacy_script('specialphrases.php', '--wiki-import', nominatim_env=args)
-
-
-class UpdateAddData:
-    """\
-    Add additional data from a file or an online source.
-
-    Data is only imported, not indexed. You need to call `nominatim-update index`
-    to complete the process.
-    """
-
-    @staticmethod
-    def add_args(parser):
-        group_name = parser.add_argument_group('Source')
-        group = group_name.add_mutually_exclusive_group(required=True)
-        group.add_argument('--file', metavar='FILE',
-                           help='Import data from an OSM file')
-        group.add_argument('--diff', metavar='FILE',
-                           help='Import data from an OSM diff file')
-        group.add_argument('--node', metavar='ID', type=int,
-                           help='Import a single node from the API')
-        group.add_argument('--way', metavar='ID', type=int,
-                           help='Import a single way from the API')
-        group.add_argument('--relation', metavar='ID', type=int,
-                           help='Import a single relation from the API')
-        group.add_argument('--tiger-data', metavar='DIR',
-                           help='Add housenumbers from the US TIGER census database.')
-        group = parser.add_argument_group('Extra arguments')
-        group.add_argument('--use-main-api', action='store_true',
-                           help='Use OSM API instead of Overpass to download objects')
-
-    @staticmethod
-    def run(args):
-        if args.tiger_data:
-            return tiger_data.add_tiger_data(args.config.get_libpq_dsn(),
-                                             args.tiger_data,
-                                             args.threads or 1,
-                                             args.config,
-                                             args.sqllib_dir)
-
-        params = ['update.php']
-        if args.file:
-            params.extend(('--import-file', args.file))
-        elif args.diff:
-            params.extend(('--import-diff', args.diff))
-        elif args.node:
-            params.extend(('--import-node', args.node))
-        elif args.way:
-            params.extend(('--import-way', args.way))
-        elif args.relation:
-            params.extend(('--import-relation', args.relation))
-        if args.use_main_api:
-            params.append('--use-main-api')
-        return run_legacy_script(*params, nominatim_env=args)
-
-
 class QueryExport:
     """\
     Export addresses as CSV file from the database.
 class QueryExport:
     """\
     Export addresses as CSV file from the database.
@@ -203,16 +154,16 @@ class QueryExport:
                            help='Type of places to output (default: street)')
         group.add_argument('--output-format',
                            default='street;suburb;city;county;state;country',
                            help='Type of places to output (default: street)')
         group.add_argument('--output-format',
                            default='street;suburb;city;county;state;country',
-                           help="""Semicolon-separated list of address types
-                                   (see --output-type). Multiple ranks can be
-                                   merged into one column by simply using a
-                                   comma-separated list.""")
+                           help=("Semicolon-separated list of address types "
+                                 "(see --output-type). Multiple ranks can be "
+                                 "merged into one column by simply using a "
+                                 "comma-separated list."))
         group.add_argument('--output-all-postcodes', action='store_true',
         group.add_argument('--output-all-postcodes', action='store_true',
-                           help="""List all postcodes for address instead of
-                                   just the most likely one""")
+                           help=("List all postcodes for address instead of "
+                                 "just the most likely one"))
         group.add_argument('--language',
         group.add_argument('--language',
-                           help="""Preferred language for output
-                                   (use local name, if omitted)""")
+                           help=("Preferred language for output "
+                                 "(use local name, if omitted)"))
         group = parser.add_argument_group('Filter arguments')
         group.add_argument('--restrict-to-country', metavar='COUNTRY_CODE',
                            help='Export only objects within country')
         group = parser.add_argument_group('Filter arguments')
         group.add_argument('--restrict-to-country', metavar='COUNTRY_CODE',
                            help='Export only objects within country')
@@ -251,7 +202,7 @@ class AdminServe:
 
     This command starts the built-in PHP webserver to serve the website
     from the current project directory. This webserver is only suitable
 
     This command starts the built-in PHP webserver to serve the website
     from the current project directory. This webserver is only suitable
-    for testing and develop. Do not use it in production setups!
+    for testing and development. Do not use it in production setups!
 
     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
     """
@@ -266,11 +217,10 @@ class AdminServe:
     def run(args):
         run_php_server(args.server, args.project_dir / 'website')
 
     def run(args):
         run_php_server(args.server, args.project_dir / 'website')
 
-
-def nominatim(**kwargs):
+def get_set_parser(**kwargs):
     """\
     """\
-    Command-line tools for importing, updating, administrating and
-    querying the Nominatim database.
+    Initializes the parser and adds various subcommands for
+    nominatim cli.
     """
     parser = CommandlineParser('nominatim', nominatim.__doc__)
 
     """
     parser = CommandlineParser('nominatim', nominatim.__doc__)
 
@@ -278,11 +228,11 @@ def nominatim(**kwargs):
     parser.add_subcommand('freeze', clicmd.SetupFreeze)
     parser.add_subcommand('replication', clicmd.UpdateReplication)
 
     parser.add_subcommand('freeze', clicmd.SetupFreeze)
     parser.add_subcommand('replication', clicmd.UpdateReplication)
 
-    parser.add_subcommand('special-phrases', SetupSpecialPhrases)
+    parser.add_subcommand('special-phrases', clicmd.ImportSpecialPhrases)
 
 
-    parser.add_subcommand('add-data', UpdateAddData)
+    parser.add_subcommand('add-data', clicmd.UpdateAddData)
     parser.add_subcommand('index', clicmd.UpdateIndex)
     parser.add_subcommand('index', clicmd.UpdateIndex)
-    parser.add_subcommand('refresh', clicmd.UpdateRefresh)
+    parser.add_subcommand('refresh', clicmd.UpdateRefresh())
 
     parser.add_subcommand('admin', clicmd.AdminFuncs)
 
 
     parser.add_subcommand('admin', clicmd.AdminFuncs)
 
@@ -298,6 +248,14 @@ def nominatim(**kwargs):
     else:
         parser.parser.epilog = 'php-cgi not found. Query commands not available.'
 
     else:
         parser.parser.epilog = 'php-cgi not found. Query commands not available.'
 
-    parser.add_subcommand('transition', clicmd.AdminTransition)
+    return parser
+
+
+def nominatim(**kwargs):
+    """\
+    Command-line tools for importing, updating, administrating and
+    querying the Nominatim database.
+    """
+    parser = get_set_parser(**kwargs)
 
     return parser.run(**kwargs)
 
     return parser.run(**kwargs)