]> git.openstreetmap.org Git - nominatim.git/commitdiff
fix liniting issues and add type annotations
authorSarah Hoffmann <lonvia@denofr.de>
Mon, 5 Dec 2022 15:16:18 +0000 (16:16 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Tue, 3 Jan 2023 09:03:00 +0000 (10:03 +0100)
.mypy.ini
.pylintrc
nominatim/api.py
nominatim/cli.py
nominatim/server/falcon/server.py
nominatim/server/sanic/server.py
nominatim/server/starlette/server.py

index ee7a9ad1434e5a19594674a71a398f2dde805901..ef2057d4313cd9d3c2316253b278c97712d1da49 100644 (file)
--- a/.mypy.ini
+++ b/.mypy.ini
@@ -12,3 +12,6 @@ ignore_missing_imports = True
 
 [mypy-dotenv.*]
 ignore_missing_imports = True
 
 [mypy-dotenv.*]
 ignore_missing_imports = True
+
+[mypy-falcon.*]
+ignore_missing_imports = True
index e62371c615158f2762e3d18ae0e185ad0e54bff7..881c1e7659fbabdb709b927f2d435474026c1a4e 100644 (file)
--- a/.pylintrc
+++ b/.pylintrc
@@ -1,6 +1,6 @@
 [MASTER]
 
 [MASTER]
 
-extension-pkg-whitelist=osmium
+extension-pkg-whitelist=osmium,falcon
 ignored-modules=icu,datrie
 
 [MESSAGES CONTROL]
 ignored-modules=icu,datrie
 
 [MESSAGES CONTROL]
index 60165d33e762e4c2e6e54175736a665e91f4248d..f5e942d1f3377936de57bc9e8afc5d87a533d579 100644 (file)
@@ -7,15 +7,13 @@
 """
 Implementation of classes for API access via libraries.
 """
 """
 Implementation of classes for API access via libraries.
 """
-from typing import Mapping, Optional, TypeVar, Callable, Any
-import functools
+from typing import Mapping, Optional
 import asyncio
 from pathlib import Path
 
 from sqlalchemy.engine.url import URL
 from sqlalchemy.ext.asyncio import create_async_engine
 
 import asyncio
 from pathlib import Path
 
 from sqlalchemy.engine.url import URL
 from sqlalchemy.ext.asyncio import create_async_engine
 
-from nominatim.typing import StrPath
 from nominatim.config import Configuration
 from nominatim.apicmd.status import get_status, StatusResult
 
 from nominatim.config import Configuration
 from nominatim.apicmd.status import get_status, StatusResult
 
@@ -56,4 +54,6 @@ class NominatimAPI:
 
 
     def status(self) -> StatusResult:
 
 
     def status(self) -> StatusResult:
+        """ Return the status of the database.
+        """
         return asyncio.get_event_loop().run_until_complete(self.async_api.status())
         return asyncio.get_event_loop().run_until_complete(self.async_api.status())
index 7143b7d676c6d9aafa8c5f5aa9f7cbf71813d08c..e6214af815724d54d63c3fdcf5767e8f034ff345 100644 (file)
@@ -9,6 +9,7 @@ Command-line interface to the Nominatim functions for import, update,
 database administration and querying.
 """
 from typing import Optional, Any, List, Union
 database administration and querying.
 """
 from typing import Optional, Any, List, Union
+import importlib
 import logging
 import os
 import sys
 import logging
 import os
 import sys
@@ -232,17 +233,17 @@ class AdminServe:
                 port = 8088
 
             if args.engine == 'sanic':
                 port = 8088
 
             if args.engine == 'sanic':
-                import nominatim.server.sanic.server
+                server_module = importlib.import_module('nominatim.server.sanic.server')
 
 
-                app = nominatim.server.sanic.server.get_application(args.project_dir)
+                app = server_module.get_application(args.project_dir)
                 app.run(host=host, port=port, debug=True)
             else:
                 app.run(host=host, port=port, debug=True)
             else:
-                import uvicorn
+                import uvicorn # pylint: disable=import-outside-toplevel
 
                 if args.engine == 'falcon':
 
                 if args.engine == 'falcon':
-                    import nominatim.server.falcon.server as server_module
+                    server_module = importlib.import_module('nominatim.server.falcon.server')
                 elif args.engine == 'starlette':
                 elif args.engine == 'starlette':
-                    import nominatim.server.starlette.server as server_module
+                    server_module = importlib.import_module('nominatim.server.starlette.server')
 
                 app = server_module.get_application(args.project_dir)
                 uvicorn.run(app, host=host, port=port)
 
                 app = server_module.get_application(args.project_dir)
                 uvicorn.run(app, host=host, port=port)
index a1ae9c6df985ae57481b71287d2887d807c1d6ab..ccb0164ce668175f4e60c7ad11eb81cac8054b96 100644 (file)
@@ -7,8 +7,10 @@
 """
 Server implementation using the falcon webserver framework.
 """
 """
 Server implementation using the falcon webserver framework.
 """
+from typing import Type, Any
 from pathlib import Path
 
 from pathlib import Path
 
+import falcon
 import falcon.asgi
 
 from nominatim.api import NominatimAPIAsync
 import falcon.asgi
 
 from nominatim.api import NominatimAPIAsync
@@ -21,15 +23,22 @@ CONTENT_TYPE = {
 }
 
 class NominatimV1:
 }
 
 class NominatimV1:
+    """ Implementation of V1 version of the Nominatim API.
+    """
 
 
-    def __init__(self, project_dir: Path):
+    def __init__(self, project_dir: Path) -> None:
         self.api = NominatimAPIAsync(project_dir)
         self.formatters = {}
 
         for rtype in (StatusResult, ):
             self.formatters[rtype] = formatting.create(rtype)
 
         self.api = NominatimAPIAsync(project_dir)
         self.formatters = {}
 
         for rtype in (StatusResult, ):
             self.formatters[rtype] = formatting.create(rtype)
 
-    def parse_format(self, req, rtype, default):
+
+    def parse_format(self, req: falcon.asgi.Request, rtype: Type[Any], default: str) -> None:
+        """ Get and check the 'format' parameter and prepare the formatter.
+            `rtype` describes the expected return type and `default` the
+            format value to assume when no parameter is present.
+        """
         req.context.format = req.get_param('format', default=default)
         req.context.formatter = self.formatters[rtype]
 
         req.context.format = req.get_param('format', default=default)
         req.context.formatter = self.formatters[rtype]
 
@@ -39,12 +48,18 @@ class NominatimV1:
                             ', '.join(req.context.formatter.list_formats()))
 
 
                             ', '.join(req.context.formatter.list_formats()))
 
 
-    def format_response(self, req, resp, result):
+    def format_response(self, req: falcon.asgi.Request, resp: falcon.asgi.Response,
+                        result: Any) -> None:
+        """ Render response into a string according to the formatter
+            set in `parse_format()`.
+        """
         resp.text = req.context.formatter.format(result, req.context.format)
         resp.content_type = CONTENT_TYPE.get(req.context.format, falcon.MEDIA_JSON)
 
 
         resp.text = req.context.formatter.format(result, req.context.format)
         resp.content_type = CONTENT_TYPE.get(req.context.format, falcon.MEDIA_JSON)
 
 
-    async def on_get_status(self, req, resp):
+    async def on_get_status(self, req: falcon.asgi.Request, resp: falcon.asgi.Response) -> None:
+        """ Implementation of status endpoint.
+        """
         self.parse_format(req, StatusResult, 'text')
 
         result = await self.api.status()
         self.parse_format(req, StatusResult, 'text')
 
         result = await self.api.status()
@@ -53,6 +68,8 @@ class NominatimV1:
 
 
 def get_application(project_dir: Path) -> falcon.asgi.App:
 
 
 def get_application(project_dir: Path) -> falcon.asgi.App:
+    """ Create a Nominatim falcon ASGI application.
+    """
     app = falcon.asgi.App()
 
     api = NominatimV1(project_dir)
     app = falcon.asgi.App()
 
     api = NominatimV1(project_dir)
index 9c75327e19b12d4f6221e5854cc7efbfc4bcccf4..8329950dbabdcf77d756af2c940f65666ecb1b7e 100644 (file)
@@ -7,6 +7,7 @@
 """
 Server implementation using the sanic webserver framework.
 """
 """
 Server implementation using the sanic webserver framework.
 """
+from typing import Any, Optional
 from pathlib import Path
 
 import sanic
 from pathlib import Path
 
 import sanic
@@ -22,18 +23,30 @@ CONTENT_TYPE = {
   'xml': 'text/xml; charset=utf-8'
 }
 
   'xml': 'text/xml; charset=utf-8'
 }
 
-def usage_error(msg):
+def usage_error(msg: str) -> sanic.HTTPResponse:
+    """ Format the response for an error with the query parameters.
+    """
     return sanic.response.text(msg, status=400)
 
 
     return sanic.response.text(msg, status=400)
 
 
-def api_response(request, result):
+def api_response(request: sanic.Request, result: Any) -> sanic.HTTPResponse:
+    """ Render a response from the query results using the configured
+        formatter.
+    """
     body = request.ctx.formatter.format(result, request.ctx.format)
     return sanic.response.text(body,
     body = request.ctx.formatter.format(result, request.ctx.format)
     return sanic.response.text(body,
-                               content_type=CONTENT_TYPE.get(request.ctx.format, 'application/json'))
-
-
-@api.on_request
-async def extract_format(request):
+                               content_type=CONTENT_TYPE.get(request.ctx.format,
+                                                             'application/json'))
+
+
+@api.on_request # type: ignore[misc]
+async def extract_format(request: sanic.Request) -> Optional[sanic.HTTPResponse]:
+    """ Get and check the 'format' parameter and prepare the formatter.
+        `ctx.result_type` describes the expected return type and
+        `ctx.default_format` the format value to assume when no parameter
+        is present.
+    """
+    assert request.route is not None
     request.ctx.formatter = request.app.ctx.formatters[request.route.ctx.result_type]
 
     request.ctx.format = request.args.get('format', request.route.ctx.default_format)
     request.ctx.formatter = request.app.ctx.formatters[request.route.ctx.result_type]
 
     request.ctx.format = request.args.get('format', request.route.ctx.default_format)
@@ -41,13 +54,19 @@ async def extract_format(request):
         return usage_error("Parameter 'format' must be one of: " +
                            ', '.join(request.ctx.formatter.list_formats()))
 
         return usage_error("Parameter 'format' must be one of: " +
                            ', '.join(request.ctx.formatter.list_formats()))
 
+    return None
+
 
 @api.get('/status', ctx_result_type=StatusResult, ctx_default_format='text')
 
 @api.get('/status', ctx_result_type=StatusResult, ctx_default_format='text')
-async def status(request):
+async def status(request: sanic.Request) -> sanic.HTTPResponse:
+    """ Implementation of status endpoint.
+    """
     return api_response(request,await request.app.ctx.api.status())
 
 
 def get_application(project_dir: Path) -> sanic.Sanic:
     return api_response(request,await request.app.ctx.api.status())
 
 
 def get_application(project_dir: Path) -> sanic.Sanic:
+    """ Create a Nominatim sanic ASGI application.
+    """
     app = sanic.Sanic("NominatimInstance")
 
     app.ctx.api = NominatimAPIAsync(project_dir)
     app = sanic.Sanic("NominatimInstance")
 
     app.ctx.api = NominatimAPIAsync(project_dir)
@@ -58,5 +77,3 @@ def get_application(project_dir: Path) -> sanic.Sanic:
     app.blueprint(api)
 
     return app
     app.blueprint(api)
 
     return app
-
-
index bfc552f236b2d844855599de1c9d98d252ce5778..38eac8dce24c66089b1dcd0c8c3a14ce5864de04 100644 (file)
@@ -7,12 +7,14 @@
 """
 Server implementation using the starlette webserver framework.
 """
 """
 Server implementation using the starlette webserver framework.
 """
+from typing import Any, Type
 from pathlib import Path
 
 from starlette.applications import Starlette
 from starlette.routing import Route
 from starlette.exceptions import HTTPException
 from starlette.responses import Response
 from pathlib import Path
 
 from starlette.applications import Starlette
 from starlette.routing import Route
 from starlette.exceptions import HTTPException
 from starlette.responses import Response
+from starlette.requests import Request
 
 from nominatim.api import NominatimAPIAsync
 from nominatim.apicmd.status import StatusResult
 
 from nominatim.api import NominatimAPIAsync
 from nominatim.apicmd.status import StatusResult
@@ -28,7 +30,11 @@ FORMATTERS = {
 }
 
 
 }
 
 
-def parse_format(request, rtype, default):
+def parse_format(request: Request, rtype: Type[Any], default: str) -> None:
+    """ Get and check the 'format' parameter and prepare the formatter.
+        `rtype` describes the expected return type and `default` the
+        format value to assume when no parameter is present.
+    """
     fmt = request.query_params.get('format', default=default)
     fmtter = FORMATTERS[rtype]
 
     fmt = request.query_params.get('format', default=default)
     fmtter = FORMATTERS[rtype]
 
@@ -40,13 +46,18 @@ def parse_format(request, rtype, default):
     request.state.formatter = fmtter
 
 
     request.state.formatter = fmtter
 
 
-def format_response(request, result):
+def format_response(request: Request, result: Any) -> Response:
+    """ Render response into a string according to the formatter
+        set in `parse_format()`.
+    """
     fmt = request.state.format
     return Response(request.state.formatter.format(result, fmt),
                     media_type=CONTENT_TYPE.get(fmt, 'application/json'))
 
 
     fmt = request.state.format
     return Response(request.state.formatter.format(result, fmt),
                     media_type=CONTENT_TYPE.get(fmt, 'application/json'))
 
 
-async def on_status(request):
+async def on_status(request: Request) -> Response:
+    """ Implementation of status endpoint.
+    """
     parse_format(request, StatusResult, 'text')
     result = await request.app.state.API.status()
     return format_response(request, result)
     parse_format(request, StatusResult, 'text')
     result = await request.app.state.API.status()
     return format_response(request, result)
@@ -57,6 +68,8 @@ V1_ROUTES = [
 ]
 
 def get_application(project_dir: Path) -> Starlette:
 ]
 
 def get_application(project_dir: Path) -> Starlette:
+    """ Create a Nominatim falcon ASGI application.
+    """
     app = Starlette(debug=True, routes=V1_ROUTES)
 
     app.state.API = NominatimAPIAsync(project_dir)
     app = Starlette(debug=True, routes=V1_ROUTES)
 
     app.state.API = NominatimAPIAsync(project_dir)