From 38a41f43b191606d7a7922eb56a9bb2794b04f31 Mon Sep 17 00:00:00 2001
From: Felix Delattre <fd@gfz-potsdam.de>
Date: Thu, 22 Jul 2021 06:17:40 +0000
Subject: [PATCH] Switched to asynchronous quart framework

---
 .gitlab-ci.yml             |  4 ++--
 README.rst                 |  2 +-
 obmdataapi/__init__.py     | 47 ++++++++++++--------------------------
 obmdataapi/jsonrpcquart.py | 35 ++++++++++++++++++++++++++++
 setup.py                   |  6 ++---
 tests/conftest.py          |  8 ++-----
 6 files changed, 57 insertions(+), 45 deletions(-)
 create mode 100644 obmdataapi/jsonrpcquart.py

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index dde2b5a..574acac 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -30,6 +30,6 @@ tests:
   stage: test
   interruptible: true
   script:
-    - export FLASK_APP=obmdataapi
-    - nohup flask run > log.txt 2>&1 &
+    - export QUART_APP=obmdataapi
+    - nohup quart run > log.txt 2>&1 &
     - pytest tests
diff --git a/README.rst b/README.rst
index b7a747c..2b2490c 100644
--- a/README.rst
+++ b/README.rst
@@ -16,7 +16,7 @@ Requirements
 ------------
 
     * python >= 3.7
-    * Flask >= 2.0.1
+    * quart >= 0.15.1
 
 Installation
 ------------
diff --git a/obmdataapi/__init__.py b/obmdataapi/__init__.py
index 278933d..9a1de2e 100644
--- a/obmdataapi/__init__.py
+++ b/obmdataapi/__init__.py
@@ -19,45 +19,26 @@
 import logging
 import sys
 
-from flask import Flask, request, Response
-from jsonrpcserver import method, dispatch
-
+from quart import Quart
+from .jsonrpcquart import JSONRPCQuart
 
 logger = logging.getLogger()
 logger.setLevel(logging.DEBUG)
 logger.addHandler(logging.StreamHandler(sys.stdout))
 
+logger.info("obmapidata has started")
 
-def create_app(test_config=None):
-    """Create and configure an instance of the Flask application."""
-
-    logger.info("obmapidata has started")
-
-    app = Flask(__name__, instance_relative_config=True)
-    app.config.from_mapping(
-        # a default secret that should be overridden by instance config
-        SECRET_KEY="dev"
-    )
-
-    if test_config is None:
-        # load the instance config, if it exists, when not testing
-        app.config.from_pyfile("config.py", silent=True)
-    else:
-        # load the test config if passed in
-        app.config.update(test_config)
-
-    @method
-    def ping():
-        return "pong"
-
-    @app.route("/", methods=["POST"])
-    def index():
-        req = request.get_data().decode()
-        response = dispatch(req)
-        return Response(str(response), response.http_status, mimetype="application/json")
+app = Quart(__name__)
+app.api = JSONRPCQuart()
 
-    return app
+app.route(
+    "/",
+    methods=[
+        "POST",
+    ],
+)(app.api.handler)
 
 
-if __name__ == "__main__":
-    create_app().run()
+@app.api.add_function
+async def ping():
+    return "pong"
diff --git a/obmdataapi/jsonrpcquart.py b/obmdataapi/jsonrpcquart.py
new file mode 100644
index 0000000..dc7e6b4
--- /dev/null
+++ b/obmdataapi/jsonrpcquart.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2021:
+#   Helmholtz-Zentrum Potsdam Deutsches GeoForschungsZentrum GFZ
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see http://www.gnu.org/licenses/.
+
+import json
+
+from quart import Response, request
+from ajsonrpc.backend.common import CommonBackend
+
+
+class JSONRPCQuart(CommonBackend):
+    @property
+    def handler(self):
+        """Get Quart Handler"""
+
+        async def handle():
+            request_body = await request.body
+            response = await self.manager.get_response_for_payload(request_body)
+            return Response(json.dumps(response.body), mimetype="application/json")
+
+        return handle
diff --git a/setup.py b/setup.py
index baedc32..705a150 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 
-# Copyright (c) 2020-2021
+# Copyright (C) 2021
 #
 # * Helmholtz-Zentrum Potsdam Deutsches GeoForschungsZentrum GFZ
 #
@@ -20,9 +20,9 @@
 from setuptools import setup, find_packages
 
 tests_require = [
-    "Flask>=2.0.1",
     "jsonrpcclient[requests]",
     "pytest",
+    "quart",
 ]
 
 linters_require = ["pre-commit", "pylint"]
@@ -36,7 +36,7 @@ setup(
     license="AGPLv3+",
     keywords="API",
     author="Helmholtz-Zentrum Potsdam Deutsches GeoForschungsZentrum GFZ",
-    install_requires=["Flask>=2.0.1", "jsonrpcserver"],
+    install_requires=["ajsonrpc", "quart"],
     tests_require=tests_require,
     extras_require={
         "tests": tests_require,
diff --git a/tests/conftest.py b/tests/conftest.py
index e371511..5cc4e52 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -17,16 +17,12 @@
 # along with this program. If not, see http://www.gnu.org/licenses/.
 
 import pytest
-
-from obmdataapi import create_app
+import obmdataapi
 
 
 @pytest.fixture
 def app():
-    # create the app with common test config
-    app = create_app({"TESTING": True})
-
-    yield app
+    yield obmdataapi.app
 
 
 @pytest.fixture
-- 
GitLab