]> git.openstreetmap.org Git - nominatim.git/blobdiff - src/nominatim_api/server/falcon/server.py
Merge pull request #3582 from lonvia/switch-to-flake
[nominatim.git] / src / nominatim_api / server / falcon / server.py
index 851b096437d4d5730ed2e7c4f5da9f60d1caf8c6..b58c1cfa830c5a863a8fc46445f3c62b02bdea06 100644 (file)
@@ -7,17 +7,20 @@
 """
 Server implementation using the falcon webserver framework.
 """
 """
 Server implementation using the falcon webserver framework.
 """
-from typing import Optional, Mapping, cast, Any, List
+from typing import Optional, Mapping, Any, List
 from pathlib import Path
 import datetime as dt
 import asyncio
 
 from falcon.asgi import App, Request, Response
 
 from pathlib import Path
 import datetime as dt
 import asyncio
 
 from falcon.asgi import App, Request, Response
 
-from nominatim_core.config import Configuration
+from ...config import Configuration
 from ...core import NominatimAPIAsync
 from ... import v1 as api_impl
 from ...core import NominatimAPIAsync
 from ... import v1 as api_impl
+from ...result_formatting import FormatDispatcher, load_format_dispatcher
 from ... import logging as loglib
 from ... import logging as loglib
+from ..asgi_adaptor import ASGIAdaptor, EndpointFunc
+
 
 class HTTPNominatimError(Exception):
     """ A special exception class for errors raised during processing.
 
 class HTTPNominatimError(Exception):
     """ A special exception class for errors raised during processing.
@@ -28,7 +31,7 @@ class HTTPNominatimError(Exception):
         self.content_type = content_type
 
 
         self.content_type = content_type
 
 
-async def nominatim_error_handler(req: Request, resp: Response, #pylint: disable=unused-argument
+async def nominatim_error_handler(req: Request, resp: Response,
                                   exception: HTTPNominatimError,
                                   _: Any) -> None:
     """ Special error handler that passes message and content type as
                                   exception: HTTPNominatimError,
                                   _: Any) -> None:
     """ Special error handler that passes message and content type as
@@ -39,8 +42,8 @@ async def nominatim_error_handler(req: Request, resp: Response, #pylint: disable
     resp.content_type = exception.content_type
 
 
     resp.content_type = exception.content_type
 
 
-async def timeout_error_handler(req: Request, resp: Response, #pylint: disable=unused-argument
-                                exception: TimeoutError, #pylint: disable=unused-argument
+async def timeout_error_handler(req: Request, resp: Response,
+                                exception: TimeoutError,
                                 _: Any) -> None:
     """ Special error handler that passes message and content type as
         per exception info.
                                 _: Any) -> None:
     """ Special error handler that passes message and content type as
         per exception info.
@@ -57,57 +60,58 @@ async def timeout_error_handler(req: Request, resp: Response, #pylint: disable=u
         resp.content_type = 'text/plain; charset=utf-8'
 
 
         resp.content_type = 'text/plain; charset=utf-8'
 
 
-class ParamWrapper(api_impl.ASGIAdaptor):
+class ParamWrapper(ASGIAdaptor):
     """ Adaptor class for server glue to Falcon framework.
     """
 
     def __init__(self, req: Request, resp: Response,
     """ Adaptor class for server glue to Falcon framework.
     """
 
     def __init__(self, req: Request, resp: Response,
-                 config: Configuration) -> None:
+                 config: Configuration, formatter: FormatDispatcher) -> None:
         self.request = req
         self.response = resp
         self._config = config
         self.request = req
         self.response = resp
         self._config = config
-
+        self._formatter = formatter
 
     def get(self, name: str, default: Optional[str] = None) -> Optional[str]:
 
     def get(self, name: str, default: Optional[str] = None) -> Optional[str]:
-        return cast(Optional[str], self.request.get_param(name, default=default))
-
+        return self.request.get_param(name, default=default)
 
     def get_header(self, name: str, default: Optional[str] = None) -> Optional[str]:
 
     def get_header(self, name: str, default: Optional[str] = None) -> Optional[str]:
-        return cast(Optional[str], self.request.get_header(name, default=default))
-
+        return self.request.get_header(name, default=default)
 
     def error(self, msg: str, status: int = 400) -> HTTPNominatimError:
         return HTTPNominatimError(msg, status, self.content_type)
 
 
     def error(self, msg: str, status: int = 400) -> HTTPNominatimError:
         return HTTPNominatimError(msg, status, self.content_type)
 
-
     def create_response(self, status: int, output: str, num_results: int) -> None:
         self.response.context.num_results = num_results
         self.response.status = status
         self.response.text = output
         self.response.content_type = self.content_type
 
     def create_response(self, status: int, output: str, num_results: int) -> None:
         self.response.context.num_results = num_results
         self.response.status = status
         self.response.text = output
         self.response.content_type = self.content_type
 
-
     def base_uri(self) -> str:
     def base_uri(self) -> str:
-        return cast (str, self.request.forwarded_prefix)
+        return self.request.forwarded_prefix
 
     def config(self) -> Configuration:
         return self._config
 
 
     def config(self) -> Configuration:
         return self._config
 
+    def formatting(self) -> FormatDispatcher:
+        return self._formatter
+
 
 class EndpointWrapper:
     """ Converter for server glue endpoint functions to Falcon request handlers.
     """
 
 
 class EndpointWrapper:
     """ Converter for server glue endpoint functions to Falcon request handlers.
     """
 
-    def __init__(self, name: str, func: api_impl.EndpointFunc, api: NominatimAPIAsync) -> None:
+    def __init__(self, name: str, func: EndpointFunc, api: NominatimAPIAsync,
+                 formatter: FormatDispatcher) -> None:
         self.name = name
         self.func = func
         self.api = api
         self.name = name
         self.func = func
         self.api = api
-
+        self.formatter = formatter
 
     async def on_get(self, req: Request, resp: Response) -> None:
         """ Implementation of the endpoint.
         """
 
     async def on_get(self, req: Request, resp: Response) -> None:
         """ Implementation of the endpoint.
         """
-        await self.func(self.api, ParamWrapper(req, resp, self.api.config))
+        await self.func(self.api, ParamWrapper(req, resp, self.api.config,
+                                               self.formatter))
 
 
 class FileLoggingMiddleware:
 
 
 class FileLoggingMiddleware:
@@ -115,15 +119,13 @@ class FileLoggingMiddleware:
     """
 
     def __init__(self, file_name: str):
     """
 
     def __init__(self, file_name: str):
-        self.fd = open(file_name, 'a', buffering=1, encoding='utf8') # pylint: disable=R1732
-
+        self.fd = open(file_name, 'a', buffering=1, encoding='utf8')
 
     async def process_request(self, req: Request, _: Response) -> None:
         """ Callback before the request starts timing.
         """
         req.context.start = dt.datetime.now(tz=dt.timezone.utc)
 
 
     async def process_request(self, req: Request, _: Response) -> None:
         """ Callback before the request starts timing.
         """
         req.context.start = dt.datetime.now(tz=dt.timezone.utc)
 
-
     async def process_response(self, req: Request, resp: Response,
                                resource: Optional[EndpointWrapper],
                                req_succeeded: bool) -> None:
     async def process_response(self, req: Request, resp: Response,
                                resource: Optional[EndpointWrapper],
                                req_succeeded: bool) -> None:
@@ -131,7 +133,7 @@ class FileLoggingMiddleware:
             writes logs for successful requests for search, reverse and lookup.
         """
         if not req_succeeded or resource is None or resp.status != 200\
             writes logs for successful requests for search, reverse and lookup.
         """
         if not req_succeeded or resource is None or resp.status != 200\
-            or resource.name not in ('reverse', 'search', 'lookup', 'details'):
+           or resource.name not in ('reverse', 'search', 'lookup', 'details'):
             return
 
         finish = dt.datetime.now(tz=dt.timezone.utc)
             return
 
         finish = dt.datetime.now(tz=dt.timezone.utc)
@@ -174,11 +176,12 @@ def get_application(project_dir: Path,
     app.add_error_handler(HTTPNominatimError, nominatim_error_handler)
     app.add_error_handler(TimeoutError, timeout_error_handler)
     # different from TimeoutError in Python <= 3.10
     app.add_error_handler(HTTPNominatimError, nominatim_error_handler)
     app.add_error_handler(TimeoutError, timeout_error_handler)
     # different from TimeoutError in Python <= 3.10
-    app.add_error_handler(asyncio.TimeoutError, timeout_error_handler)
+    app.add_error_handler(asyncio.TimeoutError, timeout_error_handler)  # type: ignore[arg-type]
 
     legacy_urls = api.config.get_bool('SERVE_LEGACY_URLS')
 
     legacy_urls = api.config.get_bool('SERVE_LEGACY_URLS')
+    formatter = load_format_dispatcher('v1', project_dir)
     for name, func in api_impl.ROUTES:
     for name, func in api_impl.ROUTES:
-        endpoint = EndpointWrapper(name, func, api)
+        endpoint = EndpointWrapper(name, func, api, formatter)
         app.add_route(f"/{name}", endpoint)
         if legacy_urls:
             app.add_route(f"/{name}.php", endpoint)
         app.add_route(f"/{name}", endpoint)
         if legacy_urls:
             app.add_route(f"/{name}.php", endpoint)