From 30cef4d5fdfd804616506b28d5caad8d2b2385c4 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Sat, 22 Jul 2023 17:21:24 +0200 Subject: [PATCH] add deletable endpoint --- nominatim/api/v1/format.py | 20 +++++++++++++++++++- nominatim/api/v1/server_glue.py | 28 +++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/nominatim/api/v1/format.py b/nominatim/api/v1/format.py index ad635e39..2442bb76 100644 --- a/nominatim/api/v1/format.py +++ b/nominatim/api/v1/format.py @@ -7,7 +7,7 @@ """ Output formatters for API version v1. """ -from typing import Mapping, Any +from typing import List, Dict, Mapping, Any import collections import nominatim.api as napi @@ -16,6 +16,10 @@ from nominatim.api.v1.classtypes import ICONS from nominatim.api.v1 import format_json, format_xml from nominatim.utils.json_writer import JsonWriter +class RawDataList(List[Dict[str, Any]]): + """ Data type for formatting raw data lists 'as is' in json. + """ + dispatch = FormatDispatcher() @dispatch.format_func(napi.StatusResult, 'text') @@ -232,3 +236,17 @@ def _format_search_jsonv2(results: napi.SearchResults, options: Mapping[str, Any]) -> str: return format_json.format_base_json(results, options, False, class_label='category') + +@dispatch.format_func(RawDataList, 'json') +def _format_raw_data_json(results: RawDataList, _: Mapping[str, Any]) -> str: + out = JsonWriter() + out.start_array() + for res in results: + out.start_object() + for k, v in res.items(): + out.keyval(k, v) + out.end_object().next() + + out.end_array() + + return out() diff --git a/nominatim/api/v1/server_glue.py b/nominatim/api/v1/server_glue.py index 5b6efe5f..b40d4e9a 100644 --- a/nominatim/api/v1/server_glue.py +++ b/nominatim/api/v1/server_glue.py @@ -15,11 +15,14 @@ import dataclasses import math from urllib.parse import urlencode +import sqlalchemy as sa + from nominatim.errors import UsageError from nominatim.config import Configuration import nominatim.api as napi import nominatim.api.logging as loglib from nominatim.api.v1.format import dispatch as formatting +from nominatim.api.v1.format import RawDataList from nominatim.api.v1 import helpers CONTENT_TYPE = { @@ -494,6 +497,28 @@ async def search_endpoint(api: napi.NominatimAPIAsync, params: ASGIAdaptor) -> A return params.build_response(output) +async def deletable_endpoint(api: napi.NominatimAPIAsync, params: ASGIAdaptor) -> Any: + """ Server glue for /deletable endpoint. + This is a special endpoint that shows polygons that have been + deleted or are broken in the OSM data but are kept in the + Nominatim database to minimize disruption. + """ + fmt = params.parse_format(RawDataList, 'json') + + async with api.begin() as conn: + sql = sa.text(""" SELECT p.place_id, country_code, + name->'name' as name, i.* + FROM placex p, import_polygon_delete i + WHERE p.osm_id = i.osm_id AND p.osm_type = i.osm_type + AND p.class = i.class AND p.type = i.type + """) + results = RawDataList(r._asdict() for r in await conn.execute(sql)) + + + return params.build_response(formatting.format_result(results, fmt, {})) + + + EndpointFunc = Callable[[napi.NominatimAPIAsync, ASGIAdaptor], Any] ROUTES = [ @@ -501,5 +526,6 @@ ROUTES = [ ('details', details_endpoint), ('reverse', reverse_endpoint), ('lookup', lookup_endpoint), - ('search', search_endpoint) + ('search', search_endpoint), + ('deletable', deletable_endpoint), ] -- 2.45.2