make formatting module non-static

This commit is contained in:
Sarah Hoffmann
2024-08-13 22:39:43 +02:00
parent 4e0602919c
commit 0c25e80be0
5 changed files with 37 additions and 14 deletions

View File

@@ -14,6 +14,7 @@ import math
from ..config import Configuration from ..config import Configuration
from .. import logging as loglib from .. import logging as loglib
from ..core import NominatimAPIAsync from ..core import NominatimAPIAsync
from ..result_formatting import FormatDispatcher
CONTENT_TEXT = 'text/plain; charset=utf-8' CONTENT_TEXT = 'text/plain; charset=utf-8'
CONTENT_XML = 'text/xml; charset=utf-8' CONTENT_XML = 'text/xml; charset=utf-8'
@@ -28,6 +29,7 @@ class ASGIAdaptor(abc.ABC):
""" """
content_type: str = CONTENT_TEXT content_type: str = CONTENT_TEXT
@abc.abstractmethod @abc.abstractmethod
def get(self, name: str, default: Optional[str] = None) -> Optional[str]: def get(self, name: str, default: Optional[str] = None) -> Optional[str]:
""" Return an input parameter as a string. If the parameter was """ 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'. body of the response to 'output'.
""" """
@abc.abstractmethod @abc.abstractmethod
def base_uri(self) -> str: def base_uri(self) -> str:
""" Return the URI of the original request. """ 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: def get_int(self, name: str, default: Optional[int] = None) -> int:
""" Return an input parameter as an int. Raises an exception if """ Return an input parameter as an int. Raises an exception if
the parameter is given but not in an integer format. the parameter is given but not in an integer format.

View File

@@ -17,6 +17,8 @@ from falcon.asgi import App, Request, Response
from ...config import Configuration from ...config import Configuration
from ...core import NominatimAPIAsync from ...core import NominatimAPIAsync
from ... import v1 as api_impl from ... import v1 as api_impl
from ...result_formatting import FormatDispatcher
from ...v1.format import dispatch as formatting
from ... import logging as loglib from ... import logging as loglib
from ..asgi_adaptor import ASGIAdaptor, EndpointFunc from ..asgi_adaptor import ASGIAdaptor, EndpointFunc
@@ -62,8 +64,7 @@ class ParamWrapper(ASGIAdaptor):
""" Adaptor class for server glue to Falcon framework. """ Adaptor class for server glue to Falcon framework.
""" """
def __init__(self, req: Request, resp: Response, def __init__(self, req: Request, resp: Response, config: Configuration) -> None:
config: Configuration) -> None:
self.request = req self.request = req
self.response = resp self.response = resp
self._config = config self._config = config
@@ -94,6 +95,9 @@ class ParamWrapper(ASGIAdaptor):
def config(self) -> Configuration: def config(self) -> Configuration:
return self._config return self._config
def formatting(self) -> FormatDispatcher:
return formatting
class EndpointWrapper: class EndpointWrapper:
""" Converter for server glue endpoint functions to Falcon request handlers. """ Converter for server glue endpoint functions to Falcon request handlers.

View File

@@ -24,6 +24,8 @@ from starlette.middleware.cors import CORSMiddleware
from ...config import Configuration from ...config import Configuration
from ...core import NominatimAPIAsync from ...core import NominatimAPIAsync
from ... import v1 as api_impl 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 ..asgi_adaptor import ASGIAdaptor, EndpointFunc
from ... import logging as loglib from ... import logging as loglib
@@ -70,6 +72,10 @@ class ParamWrapper(ASGIAdaptor):
return cast(Configuration, self.request.app.state.API.config) return cast(Configuration, self.request.app.state.API.config)
def formatting(self) -> FormatDispatcher:
return formatting
def _wrap_endpoint(func: EndpointFunc)\ def _wrap_endpoint(func: EndpointFunc)\
-> Callable[[Request], Coroutine[Any, Any, Response]]: -> Callable[[Request], Coroutine[Any, Any, Response]]:
async def _callback(request: Request) -> Response: async def _callback(request: Request) -> Response:

View File

@@ -18,7 +18,6 @@ import sqlalchemy as sa
from ..errors import UsageError from ..errors import UsageError
from .. import logging as loglib from .. import logging as loglib
from ..core import NominatimAPIAsync from ..core import NominatimAPIAsync
from .format import dispatch as formatting
from .format import RawDataList from .format import RawDataList
from ..types import DataLayer, GeometryFormat, PlaceRef, PlaceID, OsmID, Point from ..types import DataLayer, GeometryFormat, PlaceRef, PlaceID, OsmID, Point
from ..status import StatusResult 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) fmt = adaptor.get('format', default=default)
assert fmt is not None 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: " + 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) adaptor.content_type = CONTENT_TYPE.get(fmt, CONTENT_JSON)
return fmt return fmt
@@ -132,7 +131,7 @@ async def status_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any:
else: else:
status_code = 200 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) status=status_code)
@@ -171,7 +170,7 @@ async def details_endpoint(api: NominatimAPIAsync, params: ASGIAdaptor) -> Any:
if result is None: if result is None:
params.raise_error('No place with that OSM ID found.', status=404) 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, {'locales': locales,
'group_hierarchy': params.get_bool('group_hierarchy', False), 'group_hierarchy': params.get_bool('group_hierarchy', False),
'icon_base_url': params.config().MAPICON_URL}) '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), 'namedetails': params.get_bool('namedetails', False),
'addressdetails': params.get_bool('addressdetails', True)} 'addressdetails': params.get_bool('addressdetails', True)}
output = formatting.format_result(ReverseResults([result] if result else []), output = params.formatting().format_result(ReverseResults([result] if result else []),
fmt, fmt_options) fmt, fmt_options)
return build_response(params, output, num_results=1 if result else 0) 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), 'namedetails': params.get_bool('namedetails', False),
'addressdetails': params.get_bool('addressdetails', True)} '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)) 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), 'namedetails': params.get_bool('namedetails', False),
'addressdetails': params.get_bool('addressdetails', 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)) 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)) 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: 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)) 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 = [ ROUTES = [

View File

@@ -10,6 +10,7 @@ Provides dummy implementations of ASGIAdaptor for testing.
from collections import namedtuple from collections import namedtuple
import nominatim_api.v1.server_glue as glue import nominatim_api.v1.server_glue as glue
from nominatim_api.v1.format import dispatch as formatting
from nominatim_api.config import Configuration from nominatim_api.config import Configuration
class FakeError(BaseException): class FakeError(BaseException):
@@ -47,9 +48,13 @@ class FakeAdaptor(glue.ASGIAdaptor):
return FakeResponse(status, output, self.content_type) return FakeResponse(status, output, self.content_type)
def base_uri(self) -> str: def base_uri(self):
return 'http://test' return 'http://test'
def config(self): def config(self):
return self._config return self._config
def formatting(self):
return formatting