From 79bd54f610cd4f4620ce1761e7a483b6fae34d4e Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Sat, 22 Jul 2023 20:59:13 +0200 Subject: [PATCH] add /polygons endpoint to Python v1 API --- nominatim/api/v1/format.py | 6 +++++- nominatim/api/v1/server_glue.py | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/nominatim/api/v1/format.py b/nominatim/api/v1/format.py index 2442bb76..1e37b4c7 100644 --- a/nominatim/api/v1/format.py +++ b/nominatim/api/v1/format.py @@ -9,6 +9,7 @@ Output formatters for API version v1. """ from typing import List, Dict, Mapping, Any import collections +import datetime as dt import nominatim.api as napi from nominatim.api.result_formatting import FormatDispatcher @@ -244,7 +245,10 @@ def _format_raw_data_json(results: RawDataList, _: Mapping[str, Any]) -> str: for res in results: out.start_object() for k, v in res.items(): - out.keyval(k, v) + if isinstance(v, dt.datetime): + out.keyval(k, v.isoformat(sep= ' ', timespec='seconds')) + else: + out.keyval(k, v) out.end_object().next() out.end_array() diff --git a/nominatim/api/v1/server_glue.py b/nominatim/api/v1/server_glue.py index b40d4e9a..5ebdb55e 100644 --- a/nominatim/api/v1/server_glue.py +++ b/nominatim/api/v1/server_glue.py @@ -514,10 +514,40 @@ async def deletable_endpoint(api: napi.NominatimAPIAsync, params: ASGIAdaptor) - """) results = RawDataList(r._asdict() for r in await conn.execute(sql)) - return params.build_response(formatting.format_result(results, fmt, {})) +async def polygons_endpoint(api: napi.NominatimAPIAsync, params: ASGIAdaptor) -> Any: + """ Server glue for /polygons endpoint. + This is a special endpoint that shows polygons that have changed + thier size but are kept in the Nominatim database with their + old area to minimize disruption. + """ + fmt = params.parse_format(RawDataList, 'json') + sql_params: Dict[str, Any] = { + 'days': params.get_int('days', -1), + 'cls': params.get('class') + } + reduced = params.get_bool('reduced', False) + + async with api.begin() as conn: + sql = sa.select(sa.text("""osm_type, osm_id, class, type, + name->'name' as name, + country_code, errormessage, updated"""))\ + .select_from(sa.text('import_polygon_error')) + if sql_params['days'] > 0: + sql = sql.where(sa.text("updated > 'now'::timestamp - make_interval(days => :days)")) + if reduced: + sql = sql.where(sa.text("errormessage like 'Area reduced%'")) + if sql_params['cls'] is not None: + sql = sql.where(sa.text("class = :cls")) + + sql = sql.order_by(sa.literal_column('updated').desc()).limit(1000) + + results = RawDataList(r._asdict() for r in await conn.execute(sql, sql_params)) + + return params.build_response(formatting.format_result(results, fmt, {})) + EndpointFunc = Callable[[napi.NominatimAPIAsync, ASGIAdaptor], Any] @@ -528,4 +558,5 @@ ROUTES = [ ('lookup', lookup_endpoint), ('search', search_endpoint), ('deletable', deletable_endpoint), + ('polygons', polygons_endpoint), ] -- 2.39.5