1 # SPDX-License-Identifier: GPL-3.0-or-later
 
   3 # This file is part of Nominatim. (https://nominatim.org)
 
   5 # Copyright (C) 2024 by the Nominatim developer community.
 
   6 # For a full list of authors see the git log.
 
   8     Implementation of the 'special-phrases' command.
 
  12 from pathlib import Path
 
  14 from ..errors import UsageError
 
  15 from ..db.connection import connect
 
  16 from ..tools.special_phrases.sp_importer import SPImporter, SpecialPhraseLoader
 
  17 from ..tools.special_phrases.sp_wiki_loader import SPWikiLoader
 
  18 from ..tools.special_phrases.sp_csv_loader import SPCsvLoader
 
  19 from .args import NominatimArgs
 
  21 LOG = logging.getLogger()
 
  23 # Do not repeat documentation of subcommand classes.
 
  24 # pylint: disable=C0111
 
  25 # Using non-top-level imports to avoid eventually unused imports.
 
  26 # pylint: disable=E0012,C0415
 
  28 class ImportSpecialPhrases:
 
  30     Import special phrases.
 
  32     Special phrases are search terms that narrow down the type of object
 
  33     that should be searched. For example, you might want to search for
 
  34     'Hotels in Barcelona'. The OSM wiki has a selection of special phrases
 
  35     in many languages, which can be imported with this command.
 
  37     You can also provide your own phrases in a CSV file. The file needs to have
 
  38     the following five columns:
 
  39      * phrase - the term expected for searching
 
  40      * class - the OSM tag key of the object type
 
  41      * type - the OSM tag value of the object type
 
  42      * operator - the kind of search to be done (one of: in, near, name, -)
 
  43      * plural - whether the term is a plural or not (Y/N)
 
  45     An example file can be found in the Nominatim sources at
 
  46     'test/testdb/full_en_phrases_test.csv'.
 
  48     The import can be further configured to ignore specific key/value pairs.
 
  49     This is particularly useful when importing phrases from the wiki. The
 
  50     default configuration excludes some very common tags like building=yes.
 
  51     The configuration can be customized by putting a file `phrase-settings.json`
 
  52     with custom rules into the project directory or by using the `--config`
 
  53     option to point to another configuration file.
 
  56     def add_args(self, parser: argparse.ArgumentParser) -> None:
 
  57         group = parser.add_argument_group('Input arguments')
 
  58         group.add_argument('--import-from-wiki', action='store_true',
 
  59                            help='Import special phrases from the OSM wiki to the database')
 
  60         group.add_argument('--import-from-csv', metavar='FILE',
 
  61                            help='Import special phrases from a CSV file')
 
  62         group.add_argument('--no-replace', action='store_true',
 
  63                            help='Keep the old phrases and only add the new ones')
 
  66     def run(self, args: NominatimArgs) -> int:
 
  68         if args.import_from_wiki:
 
  69             self.start_import(args, SPWikiLoader(args.config))
 
  71         if args.import_from_csv:
 
  72             if not Path(args.import_from_csv).is_file():
 
  73                 LOG.fatal("CSV file '%s' does not exist.", args.import_from_csv)
 
  74                 raise UsageError('Cannot access file.')
 
  76             self.start_import(args, SPCsvLoader(args.import_from_csv))
 
  81     def start_import(self, args: NominatimArgs, loader: SpecialPhraseLoader) -> None:
 
  83             Create the SPImporter object containing the right
 
  84             sp loader and then start the import of special phrases.
 
  86         from ..tokenizer import factory as tokenizer_factory
 
  88         tokenizer = tokenizer_factory.get_tokenizer_for_db(args.config)
 
  89         should_replace = not args.no_replace
 
  90         with connect(args.config.get_libpq_dsn()) as db_connection:
 
  92                 args.config, db_connection, loader
 
  93             ).import_phrases(tokenizer, should_replace)