From 0c25e80be0868ff26e11f04298967af5f5e5adc3 Mon Sep 17 00:00:00 2001 From: Sarah Hoffmann Date: Tue, 13 Aug 2024 22:39:43 +0200 Subject: [PATCH] make formatting module non-static --- src/nominatim_api/server/asgi_adaptor.py | 9 +++++++++ src/nominatim_api/server/falcon/server.py | 8 ++++++-- src/nominatim_api/server/starlette/server.py | 6 ++++++ src/nominatim_api/v1/server_glue.py | 21 ++++++++++---------- test/python/api/fake_adaptor.py | 7 ++++++- 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/nominatim_api/server/asgi_adaptor.py b/src/nominatim_api/server/asgi_adaptor.py index 9558fbd3..84d73aec 100644 --- a/src/nominatim_api/server/asgi_adaptor.py +++ b/src/nominatim_api/server/asgi_adaptor.py @@ -14,6 +14,7 @@ import math from ..config import Configuration from .. import logging as loglib from ..core import NominatimAPIAsync +from ..result_formatting import FormatDispatcher CONTENT_TEXT = 'text/plain; charset=utf-8' CONTENT_XML = 'text/xml; charset=utf-8' @@ -28,6 +29,7 @@ class ASGIAdaptor(abc.ABC): """ content_type: str = CONTENT_TEXT + @abc.abstractmethod def get(self, name: str, default: Optional[str] = None) -> Optional[str]: """ Return an input parameter as a string. If the parameter was @@ -60,6 +62,7 @@ class ASGIAdaptor(abc.ABC): body of the response to 'output'. """ + @abc.abstractmethod def base_uri(self) -> str: """ Return the URI of the original request. @@ -72,6 +75,12 @@ class ASGIAdaptor(abc.ABC): """ + @abc.abstractmethod + def formatting(self) -> FormatDispatcher: + """ Return the formatting object to use. + """ + + def get_int(self, name: str, default: Optional[int] = None) -> int: """ Return an input parameter as an int. Raises an exception if the parameter is given but not in an integer format. diff --git a/src/nominatim_api/server/falcon/server.py b/src/nominatim_api/server/falcon/server.py index a81b9b07..91fc268e 100644 --- a/src/nominatim_api/server/falcon/server.py +++ b/src/nominatim_api/server/falcon/server.py @@ -17,6 +17,8 @@ from falcon.asgi import App, Request, Response from ...config import Configuration from ...core import NominatimAPIAsync from ... import v1 as api_impl +from ...result_formatting import FormatDispatcher +from ...v1.format import dispatch as formatting from ... import logging as loglib from ..asgi_adaptor import ASGIAdaptor, EndpointFunc @@ -62,8 +64,7 @@ class ParamWrapper(ASGIAdaptor): """ Adaptor class for server glue to Falcon framework. """ - def __init__(self, req: Request, resp: Response, - config: Configuration) -> None: + def __init__(self, req: Request, resp: Response, config: Configuration) -> None: self.request = req self.response = resp self._config = config @@ -94,6 +95,9 @@ class ParamWrapper(ASGIAdaptor): def config(self) -> Configuration: return self._config + def formatting(self) -> FormatDispatcher: + return formatting + class EndpointWrapper: """ Converter for server glue endpoint functions to Falcon request handlers. diff --git a/src/nominatim_api/server/starlette/server.py b/src/nominatim_api/server/starlette/server.py index 60a81321..fefedf0e 100644 --- a/src/nominatim_api/server/starlette/server.py +++ b/src/nominatim_api/server/starlette/server.py @@ -24,6 +24,8 @@ from starlette.middleware.cors import CORSMiddleware from ...config import Configuration from ...core import NominatimAPIAsync from ... import v1 as api_impl +from ...result_formatting import FormatDispatcher +from ...v1.format import dispatch as formatting from ..asgi_adaptor import ASGIAdaptor, EndpointFunc from ... import logging as loglib @@ -70,6 +72,10 @@ class ParamWrapper(ASGIAdaptor): return cast(Configuration, self.request.app.state.API.config) + def formatting(self) -> FormatDispatcher: + return formatting + + def _wrap_endpoint(func: EndpointFunc)\ -> Callable[[Request], Coroutine[Any, Any, Response]]: async def _callback(request: Request) -> Response: diff --git a/src/nominatim_api/v1/server_glue.py b/src/nominatim_api/v1/server_glue.py index 5f9212e1..925bfdd0 100644 --- a/src/nominatim_api/v1/server_glue.py +++ b/src/nominatim_api/v1/server_glue.py @@ -18,7 +18,6 @@ import sqlalchemy as sa from ..errors import UsageError from .. import logging as loglib from ..core import NominatimAPIAsync -from .format import dispatch as formatting from .format import RawDataList from ..types import DataLayer, GeometryFormat, PlaceRef, PlaceID, OsmID, Point from ..status import StatusResult @@ -84,9 +83,9 @@ def parse_format(adaptor: ASGIAdaptor, result_type: Type[Any], default: str) -> fmt = adaptor.get('format', default=default) assert fmt is not None - if not formatting.supports_format(result_type, fmt): + if not adaptor.formatting().supports_format(result_type, fmt): adaptor.raise_error("Parameter 'format' must be one of: " + - ', '.join(formatting.list_formats(result_type))) + ', '.join(adaptor.formatting().list_formats(result_type))) adaptor.content_type = CONTENT_TYPE.get(fmt, CONTENT_JSON) return fmt @@ -132,7 +131,7 @@ async def status_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any: else: status_code = 200 - return build_response(params, formatting.format_result(result, fmt, {}), + return build_response(params, params.formatting().format_result(result, fmt, {}), status=status_code) @@ -171,7 +170,7 @@ async def details_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any: if result is None: params.raise_error('No place with that OSM ID found.', status=404) - output = formatting.format_result(result, fmt, + output = params.formatting().format_result(result, fmt, {'locales': locales, 'group_hierarchy': params.get_bool('group_hierarchy', False), 'icon_base_url': params.config().MAPICON_URL}) @@ -210,8 +209,8 @@ async def reverse_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any: 'namedetails': params.get_bool('namedetails', False), 'addressdetails': params.get_bool('addressdetails', True)} - output = formatting.format_result(ReverseResults([result] if result else []), - fmt, fmt_options) + output = params.formatting().format_result(ReverseResults([result] if result else []), + fmt, fmt_options) return build_response(params, output, num_results=1 if result else 0) @@ -245,7 +244,7 @@ async def lookup_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any: 'namedetails': params.get_bool('namedetails', False), 'addressdetails': params.get_bool('addressdetails', True)} - output = formatting.format_result(results, fmt, fmt_options) + output = params.formatting().format_result(results, fmt, fmt_options) return build_response(params, output, num_results=len(results)) @@ -356,7 +355,7 @@ async def search_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any: 'namedetails': params.get_bool('namedetails', False), 'addressdetails': params.get_bool('addressdetails', False)} - output = formatting.format_result(results, fmt, fmt_options) + output = params.formatting().format_result(results, fmt, fmt_options) return build_response(params, output, num_results=len(results)) @@ -378,7 +377,7 @@ async def deletable_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any """) results = RawDataList(r._asdict() for r in await conn.execute(sql)) - return build_response(params, formatting.format_result(results, fmt, {})) + return build_response(params, params.formatting().format_result(results, fmt, {})) async def polygons_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any: @@ -410,7 +409,7 @@ async def polygons_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any: results = RawDataList(r._asdict() for r in await conn.execute(sql, sql_params)) - return build_response(params, formatting.format_result(results, fmt, {})) + return build_response(params, params.formatting().format_result(results, fmt, {})) ROUTES = [ diff --git a/test/python/api/fake_adaptor.py b/test/python/api/fake_adaptor.py index 9caa9226..4b64c17d 100644 --- a/test/python/api/fake_adaptor.py +++ b/test/python/api/fake_adaptor.py @@ -10,6 +10,7 @@ Provides dummy implementations of ASGIAdaptor for testing. from collections import namedtuple import nominatim_api.v1.server_glue as glue +from nominatim_api.v1.format import dispatch as formatting from nominatim_api.config import Configuration class FakeError(BaseException): @@ -47,9 +48,13 @@ class FakeAdaptor(glue.ASGIAdaptor): return FakeResponse(status, output, self.content_type) - def base_uri(self) -> str: + def base_uri(self): return 'http://test' def config(self): return self._config + def formatting(self): + return formatting + + -- 2.39.5