2 Command-line interface to the Nominatim functions for import, update,
3 database administration and querying.
8 from pathlib import Path
10 from .config import Configuration
11 from .admin.exec_utils import run_legacy_script
13 class CommandlineParser:
14 """ Wraps some of the common functions for parsing the command line
15 and setting up subcommands.
17 def __init__(self, prog, description):
18 self.parser = argparse.ArgumentParser(
20 description=description,
21 formatter_class=argparse.RawDescriptionHelpFormatter)
23 self.subs = self.parser.add_subparsers(title='available commands',
26 # Arguments added to every sub-command
27 self.default_args = argparse.ArgumentParser(add_help=False)
28 group = self.default_args.add_argument_group('Default arguments')
29 group.add_argument('-h', '--help', action='help',
30 help='Show this help message and exit')
31 group.add_argument('-q', '--quiet', action='store_const', const=0,
32 dest='verbose', default=1,
33 help='Print only error messages')
34 group.add_argument('-v', '--verbose', action='count', default=1,
35 help='Increase verboseness of output')
36 group.add_argument('--project-dir', metavar='DIR', default='.',
37 help='Base directory of the Nominatim installation (default:.)')
38 group.add_argument('-j', '--threads', metavar='NUM', type=int,
39 help='Number of parallel threads to use')
42 def add_subcommand(self, name, cmd):
43 """ Add a subcommand to the parser. The subcommand must be a class
44 with a function add_args() that adds the parameters for the
45 subcommand and a run() function that executes the command.
47 parser = self.subs.add_parser(name, parents=[self.default_args],
48 help=cmd.__doc__.split('\n', 1)[0],
49 description=cmd.__doc__,
50 formatter_class=argparse.RawDescriptionHelpFormatter,
52 parser.set_defaults(command=cmd)
55 def run(self, **kwargs):
56 """ Parse the command line arguments of the program and execute the
57 appropriate subcommand.
59 args = self.parser.parse_args()
61 if args.subcommand is None:
62 return self.parser.print_help()
64 for arg in ('module_dir', 'osm2pgsql_path', 'phplib_dir', 'data_dir'):
65 setattr(args, arg, Path(kwargs[arg]))
66 args.project_dir = Path(args.project_dir)
68 logging.basicConfig(stream=sys.stderr,
69 format='%(asctime)s %(levelname)s: %(message)s',
70 datefmt='%Y-%m-%d %H:%M:%S',
71 level=max(4 - args.verbose, 1) * 10)
73 args.config = Configuration(args.project_dir, args.data_dir / 'settings')
75 args.command.run(args)
80 Create a new Nominatim database from an OSM file.
85 group_name = parser.add_argument_group('Required arguments')
86 group = group_name.add_mutually_exclusive_group(required=True)
87 group.add_argument('--osm-file',
88 help='OSM file to be imported.')
89 group.add_argument('--continue', nargs=1,
90 choices=['load-data', 'indexing', 'db-postprocess'],
91 help='Continue an import that was interrupted')
92 group = parser.add_argument_group('Optional arguments')
93 group.add_argument('--osm2pgsql-cache', metavar='SIZE', type=int,
94 help='Size of cache to be used by osm2pgsql (in MB)')
95 group.add_argument('--reverse-only', action='store_true',
96 help='Do not create tables and indexes for searching')
97 group.add_argument('--enable-debug-statements', action='store_true',
98 help='Include debug warning statements in SQL code')
99 group.add_argument('--no-partitions', action='store_true',
100 help="""Do not partition search indices
101 (speeds up import of single country extracts)""")
102 group.add_argument('--no-updates', action='store_true',
103 help="""Do not keep tables that are only needed for
104 updating the database later""")
105 group = parser.add_argument_group('Expert options')
106 group.add_argument('--ignore-errors', action='store_true',
107 help='Continue import even when errors in SQL are present')
108 group.add_argument('--disable-token-precalc', action='store_true',
109 help='Disable name precalculation')
110 group.add_argument('--index-noanalyse', action='store_true',
111 help='Do not perform analyse operations during index')
116 print("TODO: ./utils/setup.php", args)
121 Make database read-only.
123 About half of data in the Nominatim database is kept only to be able to
124 keep the data up-to-date with new changes made in OpenStreetMap. This
125 command drops all this data and only keeps the part needed for geocoding
128 This command has the same effect as the `--no-updates` option for imports.
132 def add_args(parser):
137 print("TODO: setup drop", args)
140 class SetupSpecialPhrases:
142 Maintain special phrases.
146 def add_args(parser):
147 group = parser.add_argument_group('Input arguments')
148 group.add_argument('--from-wiki', action='store_true',
149 help='Pull special phrases from the OSM wiki.')
150 group = parser.add_argument_group('Output arguments')
151 group.add_argument('-o', '--output', default='-',
152 type=argparse.FileType('w', encoding='UTF-8'),
153 help="""File to write the preprocessed phrases to.
154 If omitted, it will be written to stdout.""")
158 print("./utils/specialphrases.php --from-wiki", args)
161 class UpdateReplication:
163 Update the database using an online replication service.
167 def add_args(parser):
168 group = parser.add_argument_group('Arguments for initialisation')
169 group.add_argument('--init', action='store_true',
170 help='Initialise the update process')
171 group.add_argument('--no-update-functions', dest='update_functions',
172 action='store_false',
173 help="""Do not update the trigger function to
174 support differential updates.""")
175 group = parser.add_argument_group('Arguments for updates')
176 group.add_argument('--check-for-updates', action='store_true',
177 help='Check if new updates are available and exit')
178 group.add_argument('--once', action='store_true',
179 help="""Download and apply updates only once. When
180 not set, updates are continuously applied""")
181 group.add_argument('--no-index', action='store_false', dest='do_index',
182 help="""Do not index the new data. Only applicable
183 together with --once""")
188 print('./utils/update.php --init-updates', args)
190 print('./utils/update.php --import-osmosis(-all)', args)
195 Add additional data from a file or an online source.
197 Data is only imported, not indexed. You need to call `nominatim-update index`
198 to complete the process.
202 def add_args(parser):
203 group_name = parser.add_argument_group('Source')
204 group = group_name.add_mutually_exclusive_group(required=True)
205 group.add_argument('--file', metavar='FILE',
206 help='Import data from an OSM file')
207 group.add_argument('--diff', metavar='FILE',
208 help='Import data from an OSM diff file')
209 group.add_argument('--node', metavar='ID', type=int,
210 help='Import a single node from the API')
211 group.add_argument('--way', metavar='ID', type=int,
212 help='Import a single way from the API')
213 group.add_argument('--relation', metavar='ID', type=int,
214 help='Import a single relation from the API')
215 group.add_argument('--tiger-data', metavar='DIR',
216 help='Add housenumbers from the US TIGER census database.')
217 group = parser.add_argument_group('Extra arguments')
218 group.add_argument('--use-main-api', action='store_true',
219 help='Use OSM API instead of Overpass to download objects')
223 print('./utils/update.php --import-*', args)
228 Reindex all new and modified data.
232 def add_args(parser):
237 print('./utils/update.php --index', args)
242 Recompute auxillary data used by the indexing process.
244 These functions must not be run in parallel with other update commands.
248 def add_args(parser):
249 group = parser.add_argument_group('Data arguments')
250 group.add_argument('--postcodes', action='store_true',
251 help='Update postcode centroid table')
252 group.add_argument('--word-counts', action='store_true',
253 help='Compute frequency of full-word search terms')
254 group.add_argument('--address-levels', action='store_true',
255 help='Reimport address level configuration')
256 group.add_argument('--importance', action='store_true',
257 help='Recompute place importances')
258 group.add_argument('--functions', action='store_true',
259 help='Update the PL/pgSQL functions in the database')
260 group.add_argument('--wiki-data',
261 help='Update Wikipedia/data importance numbers.')
262 group.add_argument('--website', action='store_true',
263 help='Refresh the directory that serves the scripts for the web API')
264 group = parser.add_argument_group('Arguments for function refresh')
265 group.add_argument('--no-diff-updates', action='store_false', dest='diffs',
266 help='Do not enable code for propagating updates')
270 print('./utils/update.php', args)
273 class AdminCheckDatabase:
275 Check that the database is complete and operational.
279 def add_args(parser):
284 print("TODO: ./utils/check_import_finished.php", args)
289 Warm database caches for search and reverse queries.
293 def add_args(parser):
294 group = parser.add_argument_group('Target arguments')
295 group.add_argument('--search-only', action='store_const', dest='target',
297 help="Only pre-warm tables for search queries")
298 group.add_argument('--reverse-only', action='store_const', dest='target',
300 help="Only pre-warm tables for reverse queries")
304 params = ['warm.php']
305 if args.target == 'reverse':
306 params.append('--reverse-only')
307 if args.target == 'search':
308 params.append('--search-only')
309 return run_legacy_script(*params, nominatim_env=args)
314 Export addresses as CSV file from a Nominatim database.
318 def add_args(parser):
319 group = parser.add_argument_group('Output arguments')
320 group.add_argument('--output-type', default='street',
321 choices=('continent', 'country', 'state', 'county',
322 'city', 'suburb', 'street', 'path'),
323 help='Type of places to output (default: street)')
324 group.add_argument('--output-format',
325 default='street;suburb;city;county;state;country',
326 help="""Semicolon-separated list of address types
327 (see --output-type). Multiple ranks can be
328 merged into one column by simply using a
329 comma-separated list.""")
330 group.add_argument('--output-all-postcodes', action='store_true',
331 help="""List all postcodes for address instead of
332 just the most likely one""")
333 group.add_argument('--language',
334 help="""Preferred language for output
335 (use local name, if omitted)""")
336 group = parser.add_argument_group('Filter arguments')
337 group.add_argument('--restrict-to-country', metavar='COUNTRY_CODE',
338 help='Export only objects within country')
339 group.add_argument('--restrict-to-osm-node', metavar='ID', type=int,
340 help='Export only children of this OSM node')
341 group.add_argument('--restrict-to-osm-way', metavar='ID', type=int,
342 help='Export only children of this OSM way')
343 group.add_argument('--restrict-to-osm-relation', metavar='ID', type=int,
344 help='Export only children of this OSM relation')
349 print("TODO: ./utils/export.php", args)
357 def add_args(parser):
361 print("TODO: searching")
364 def nominatim(**kwargs):
366 Command-line tools for importing, updating, administrating and
367 querying the Nominatim database.
369 parser = CommandlineParser('nominatim', nominatim.__doc__)
371 parser.add_subcommand('import', SetupAll)
372 parser.add_subcommand('freeze', SetupFreeze)
373 parser.add_subcommand('replication', UpdateReplication)
375 parser.add_subcommand('check-database', AdminCheckDatabase)
376 parser.add_subcommand('warm', AdminWarm)
378 parser.add_subcommand('special-phrases', SetupSpecialPhrases)
380 parser.add_subcommand('add-data', UpdateAddData)
381 parser.add_subcommand('index', UpdateIndex)
382 parser.add_subcommand('refresh', UpdateRefresh)
384 parser.add_subcommand('export', QueryExport)
385 parser.add_subcommand('search', QueryTodo)
386 parser.add_subcommand('reverse', QueryTodo)
387 parser.add_subcommand('lookup', QueryTodo)
388 parser.add_subcommand('details', QueryTodo)
389 parser.add_subcommand('status', QueryTodo)