mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-03-10 12:04:06 +00:00
remove support for sanic framework
There is no performance gain over falcon or starlette but the special structure of sanic makes it hard to have exchangable code
This commit is contained in:
2
.github/workflows/ci-tests.yml
vendored
2
.github/workflows/ci-tests.yml
vendored
@@ -113,7 +113,7 @@ jobs:
|
|||||||
if: matrix.flavour == 'oldstuff'
|
if: matrix.flavour == 'oldstuff'
|
||||||
|
|
||||||
- name: Install Python webservers
|
- name: Install Python webservers
|
||||||
run: pip3 install falcon sanic sanic-testing sanic-cors starlette
|
run: pip3 install falcon starlette
|
||||||
|
|
||||||
- name: Install latest pylint
|
- name: Install latest pylint
|
||||||
run: pip3 install -U pylint asgi_lifespan
|
run: pip3 install -U pylint asgi_lifespan
|
||||||
|
|||||||
@@ -67,9 +67,8 @@ For running the experimental Python frontend:
|
|||||||
|
|
||||||
* one of the following web frameworks:
|
* one of the following web frameworks:
|
||||||
* [falcon](https://falconframework.org/) (3.0+)
|
* [falcon](https://falconframework.org/) (3.0+)
|
||||||
* [sanic](https://sanic.dev) and (optionally) [sanic-cors](https://github.com/ashleysommer/sanic-cors)
|
|
||||||
* [starlette](https://www.starlette.io/)
|
* [starlette](https://www.starlette.io/)
|
||||||
* [uvicorn](https://www.uvicorn.org/) (only with falcon and starlette framworks)
|
* [uvicorn](https://www.uvicorn.org/)
|
||||||
|
|
||||||
For dependencies for running tests and building documentation, see
|
For dependencies for running tests and building documentation, see
|
||||||
the [Development section](../develop/Development-Environment.md).
|
the [Development section](../develop/Development-Environment.md).
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ It has the following additional requirements:
|
|||||||
For testing the Python search frontend, you need to install extra dependencies
|
For testing the Python search frontend, you need to install extra dependencies
|
||||||
depending on your choice of webserver framework:
|
depending on your choice of webserver framework:
|
||||||
|
|
||||||
* [sanic-testing](https://sanic.dev/en/plugins/sanic-testing/getting-started.html) (sanic only)
|
|
||||||
* [httpx](https://www.python-httpx.org/) (starlette only)
|
* [httpx](https://www.python-httpx.org/) (starlette only)
|
||||||
* [asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan) (starlette only)
|
* [asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan) (starlette only)
|
||||||
|
|
||||||
@@ -66,7 +65,7 @@ sudo apt install php-cgi phpunit php-codesniffer \
|
|||||||
pip3 install --user behave mkdocs mkdocstrings pytest pytest-asyncio pylint \
|
pip3 install --user behave mkdocs mkdocstrings pytest pytest-asyncio pylint \
|
||||||
mypy types-PyYAML types-jinja2 types-psycopg2 types-psutil \
|
mypy types-PyYAML types-jinja2 types-psycopg2 types-psutil \
|
||||||
types-ujson types-requests types-Pygments typing-extensions\
|
types-ujson types-requests types-Pygments typing-extensions\
|
||||||
sanic-testing httpx asgi-lifespan
|
httpx asgi-lifespan
|
||||||
```
|
```
|
||||||
|
|
||||||
The `mkdocs` executable will be located in `.local/bin`. You may have to add
|
The `mkdocs` executable will be located in `.local/bin`. You may have to add
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ class AdminServe:
|
|||||||
group.add_argument('--server', default='127.0.0.1:8088',
|
group.add_argument('--server', default='127.0.0.1:8088',
|
||||||
help='The address the server will listen to.')
|
help='The address the server will listen to.')
|
||||||
group.add_argument('--engine', default='php',
|
group.add_argument('--engine', default='php',
|
||||||
choices=('php', 'sanic', 'falcon', 'starlette'),
|
choices=('php', 'falcon', 'starlette'),
|
||||||
help='Webserver framework to run. (default: php)')
|
help='Webserver framework to run. (default: php)')
|
||||||
|
|
||||||
|
|
||||||
@@ -223,6 +223,7 @@ class AdminServe:
|
|||||||
if args.engine == 'php':
|
if args.engine == 'php':
|
||||||
run_php_server(args.server, args.project_dir / 'website')
|
run_php_server(args.server, args.project_dir / 'website')
|
||||||
else:
|
else:
|
||||||
|
import uvicorn # pylint: disable=import-outside-toplevel
|
||||||
server_info = args.server.split(':', 1)
|
server_info = args.server.split(':', 1)
|
||||||
host = server_info[0]
|
host = server_info[0]
|
||||||
if len(server_info) > 1:
|
if len(server_info) > 1:
|
||||||
@@ -232,21 +233,10 @@ class AdminServe:
|
|||||||
else:
|
else:
|
||||||
port = 8088
|
port = 8088
|
||||||
|
|
||||||
if args.engine == 'sanic':
|
server_module = importlib.import_module(f'nominatim.server.{args.engine}.server')
|
||||||
server_module = importlib.import_module('nominatim.server.sanic.server')
|
|
||||||
|
|
||||||
app = server_module.get_application(args.project_dir)
|
app = server_module.get_application(args.project_dir)
|
||||||
app.run(host=host, port=port, debug=True, single_process=True)
|
uvicorn.run(app, host=host, port=port)
|
||||||
else:
|
|
||||||
import uvicorn # pylint: disable=import-outside-toplevel
|
|
||||||
|
|
||||||
if args.engine == 'falcon':
|
|
||||||
server_module = importlib.import_module('nominatim.server.falcon.server')
|
|
||||||
elif args.engine == 'starlette':
|
|
||||||
server_module = importlib.import_module('nominatim.server.starlette.server')
|
|
||||||
|
|
||||||
app = server_module.get_application(args.project_dir)
|
|
||||||
uvicorn.run(app, host=host, port=port)
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
# SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
#
|
|
||||||
# This file is part of Nominatim. (https://nominatim.org)
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 by the Nominatim developer community.
|
|
||||||
# For a full list of authors see the git log.
|
|
||||||
"""
|
|
||||||
Server implementation using the sanic webserver framework.
|
|
||||||
"""
|
|
||||||
from typing import Any, Optional, Mapping, Callable, cast, Coroutine
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from sanic import Request, HTTPResponse, Sanic
|
|
||||||
from sanic.exceptions import SanicException
|
|
||||||
from sanic.response import text as TextResponse
|
|
||||||
|
|
||||||
from nominatim.api import NominatimAPIAsync
|
|
||||||
import nominatim.api.v1 as api_impl
|
|
||||||
from nominatim.config import Configuration
|
|
||||||
|
|
||||||
class ParamWrapper(api_impl.ASGIAdaptor):
|
|
||||||
""" Adaptor class for server glue to Sanic framework.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, request: Request) -> None:
|
|
||||||
self.request = request
|
|
||||||
|
|
||||||
|
|
||||||
def get(self, name: str, default: Optional[str] = None) -> Optional[str]:
|
|
||||||
return cast(Optional[str], self.request.args.get(name, default))
|
|
||||||
|
|
||||||
|
|
||||||
def get_header(self, name: str, default: Optional[str] = None) -> Optional[str]:
|
|
||||||
return cast(Optional[str], self.request.headers.get(name, default))
|
|
||||||
|
|
||||||
|
|
||||||
def error(self, msg: str, status: int = 400) -> SanicException:
|
|
||||||
exception = SanicException(msg, status_code=status)
|
|
||||||
|
|
||||||
return exception
|
|
||||||
|
|
||||||
|
|
||||||
def create_response(self, status: int, output: str) -> HTTPResponse:
|
|
||||||
return TextResponse(output, status=status, content_type=self.content_type)
|
|
||||||
|
|
||||||
|
|
||||||
def config(self) -> Configuration:
|
|
||||||
return cast(Configuration, self.request.app.ctx.api.config)
|
|
||||||
|
|
||||||
|
|
||||||
def _wrap_endpoint(func: api_impl.EndpointFunc)\
|
|
||||||
-> Callable[[Request], Coroutine[Any, Any, HTTPResponse]]:
|
|
||||||
async def _callback(request: Request) -> HTTPResponse:
|
|
||||||
return cast(HTTPResponse, await func(request.app.ctx.api, ParamWrapper(request)))
|
|
||||||
|
|
||||||
return _callback
|
|
||||||
|
|
||||||
|
|
||||||
def get_application(project_dir: Path,
|
|
||||||
environ: Optional[Mapping[str, str]] = None) -> Sanic:
|
|
||||||
""" Create a Nominatim sanic ASGI application.
|
|
||||||
"""
|
|
||||||
app = Sanic("NominatimInstance")
|
|
||||||
|
|
||||||
app.ctx.api = NominatimAPIAsync(project_dir, environ)
|
|
||||||
|
|
||||||
if app.ctx.api.config.get_bool('CORS_NOACCESSCONTROL'):
|
|
||||||
from sanic_cors import CORS # pylint: disable=import-outside-toplevel
|
|
||||||
CORS(app)
|
|
||||||
|
|
||||||
legacy_urls = app.ctx.api.config.get_bool('SERVE_LEGACY_URLS')
|
|
||||||
for name, func in api_impl.ROUTES:
|
|
||||||
endpoint = _wrap_endpoint(func)
|
|
||||||
app.add_route(endpoint, f"/{name}", name=f"v1_{name}_simple")
|
|
||||||
if legacy_urls:
|
|
||||||
app.add_route(endpoint, f"/{name}.php", name=f"v1_{name}_legacy")
|
|
||||||
|
|
||||||
return app
|
|
||||||
@@ -350,20 +350,6 @@ class NominatimEnvironment:
|
|||||||
return _request
|
return _request
|
||||||
|
|
||||||
|
|
||||||
def create_api_request_func_sanic(self):
|
|
||||||
import nominatim.server.sanic.server
|
|
||||||
|
|
||||||
async def _request(endpoint, params, project_dir, environ, http_headers):
|
|
||||||
app = nominatim.server.sanic.server.get_application(project_dir, environ)
|
|
||||||
|
|
||||||
_, response = await app.asgi_client.get(f"/{endpoint}", params=params,
|
|
||||||
headers=http_headers)
|
|
||||||
|
|
||||||
return response.text, response.status_code
|
|
||||||
|
|
||||||
return _request
|
|
||||||
|
|
||||||
|
|
||||||
def create_api_request_func_falcon(self):
|
def create_api_request_func_falcon(self):
|
||||||
import nominatim.server.falcon.server
|
import nominatim.server.falcon.server
|
||||||
import falcon.testing
|
import falcon.testing
|
||||||
|
|||||||
@@ -68,15 +68,6 @@ def test_cli_serve_php(cli_call, mock_func_factory):
|
|||||||
assert func.called == 1
|
assert func.called == 1
|
||||||
|
|
||||||
|
|
||||||
def test_cli_serve_sanic(cli_call, mock_func_factory):
|
|
||||||
mod = pytest.importorskip("sanic")
|
|
||||||
func = mock_func_factory(mod.Sanic, "run")
|
|
||||||
|
|
||||||
cli_call('serve', '--engine', 'sanic') == 0
|
|
||||||
|
|
||||||
assert func.called == 1
|
|
||||||
|
|
||||||
|
|
||||||
def test_cli_serve_starlette_custom_server(cli_call, mock_func_factory):
|
def test_cli_serve_starlette_custom_server(cli_call, mock_func_factory):
|
||||||
pytest.importorskip("starlette")
|
pytest.importorskip("starlette")
|
||||||
mod = pytest.importorskip("uvicorn")
|
mod = pytest.importorskip("uvicorn")
|
||||||
|
|||||||
Reference in New Issue
Block a user