1 # SPDX-License-Identifier: GPL-3.0-or-later
 
   3 # This file is part of Nominatim. (https://nominatim.org)
 
   5 # Copyright (C) 2025 by the Nominatim developer community.
 
   6 # For a full list of authors see the git log.
 
   8 Provides custom functions over command-line arguments.
 
  10 from typing import Optional, List, Dict, Any, Sequence, Tuple
 
  13 from pathlib import Path
 
  15 from ..errors import UsageError
 
  16 from ..config import Configuration
 
  17 from ..typing import Protocol
 
  20 LOG = logging.getLogger()
 
  23 class Subcommand(Protocol):
 
  25     Interface to be implemented by classes implementing a CLI subcommand.
 
  28     def add_args(self, parser: argparse.ArgumentParser) -> None:
 
  30         Fill the given parser for the subcommand with the appropriate
 
  34     def run(self, args: 'NominatimArgs') -> int:
 
  36         Run the subcommand with the given parsed arguments.
 
  41     """ Customized namespace class for the nominatim command line tool
 
  42         to receive the command-line arguments.
 
  44     # Basic environment set by root program.
 
  50     subcommand: Optional[str]
 
  54     osm2pgsql_cache: Optional[int]
 
  57     # Arguments added to all subcommands.
 
  59     threads: Optional[int]
 
  61     # Arguments to 'add-data'
 
  66     relation: Optional[int]
 
  67     tiger_data: Optional[str]
 
  70     # Arguments to 'admin'
 
  76     analyse_indexing: bool
 
  79     place_id: Optional[int]
 
  81     # Arguments to 'import'
 
  83     continue_at: Optional[str]
 
  90     prepare_database: bool
 
  92     # Arguments to 'index'
 
  98     # Arguments to 'export'
 
 101     output_all_postcodes: bool
 
 102     language: Optional[str]
 
 103     restrict_to_country: Optional[str]
 
 105     # Arguments to 'convert'
 
 108     # Arguments to 'refresh'
 
 115     secondary_importance: bool
 
 119     enable_debug_statements: bool
 
 120     data_object: Sequence[Tuple[str, int]]
 
 121     data_area: Sequence[Tuple[str, int]]
 
 123     # Arguments to 'replication'
 
 125     update_functions: bool
 
 126     check_for_updates: bool
 
 131     # Arguments to 'serve'
 
 135     # Arguments to 'special-phrases
 
 136     import_from_wiki: bool
 
 137     import_from_csv: Optional[str]
 
 141     # Arguments to all query functions
 
 149     polygon_output: Optional[str]
 
 150     polygon_threshold: Optional[float]
 
 152     # Arguments to 'search'
 
 154     amenity: Optional[str]
 
 155     street: Optional[str]
 
 157     county: Optional[str]
 
 159     country: Optional[str]
 
 160     postalcode: Optional[str]
 
 161     countrycodes: Optional[str]
 
 162     exclude_place_ids: Optional[str]
 
 164     viewbox: Optional[str]
 
 168     # Arguments to 'reverse'
 
 172     layers: Optional[Sequence[str]]
 
 174     # Arguments to 'lookup'
 
 177     # Arguments to 'details'
 
 178     object_class: Optional[str]
 
 182     polygon_geojson: bool
 
 183     group_hierarchy: bool
 
 185     def osm2pgsql_options(self, default_cache: int,
 
 186                           default_threads: int) -> Dict[str, Any]:
 
 187         """ Return the standard osm2pgsql options that can be derived
 
 188             from the command line arguments. The resulting dict can be
 
 189             further customized and then used in `run_osm2pgsql()`.
 
 191         return dict(osm2pgsql=self.config.OSM2PGSQL_BINARY,
 
 192                     osm2pgsql_cache=self.osm2pgsql_cache or default_cache,
 
 193                     osm2pgsql_style=self.config.get_import_style_file(),
 
 194                     osm2pgsql_style_path=self.config.lib_dir.lua,
 
 195                     threads=self.threads or default_threads,
 
 196                     dsn=self.config.get_libpq_dsn(),
 
 197                     flatnode_file=str(self.config.get_path('FLATNODE_FILE') or ''),
 
 198                     tablespaces=dict(slim_data=self.config.TABLESPACE_OSM_DATA,
 
 199                                      slim_index=self.config.TABLESPACE_OSM_INDEX,
 
 200                                      main_data=self.config.TABLESPACE_PLACE_DATA,
 
 201                                      main_index=self.config.TABLESPACE_PLACE_INDEX
 
 205     def get_osm_file_list(self) -> Optional[List[Path]]:
 
 206         """ Return the --osm-file argument as a list of Paths or None
 
 207             if no argument was given. The function also checks if the files
 
 208             exist and raises a UsageError if one cannot be found.
 
 210         if not self.osm_file:
 
 213         files = [Path(f) for f in self.osm_file]
 
 215             if not fname.is_file():
 
 216                 LOG.fatal("OSM file '%s' does not exist.", fname)
 
 217                 raise UsageError('Cannot access file.')