Browse Source

Error handling (#85)

* Add Hebrew test strings.

* Fix Dicta input.

* Reintroduce error handlerrs.

* Fix error handling.
Stefano Cossu 4 months ago
parent
commit
3a9a6fc259

+ 23 - 2
scriptshifter/exceptions.py

@@ -4,6 +4,27 @@ BREAK = "__break"
 CONT = "__continue"
 
 
-class ConfigError(Exception):
+class ApiError(Exception):
+    """ Base class for all exceptions expecting an API response. """
+    status_code = 400
+    msg = "An undefined error occurred."
+
+    def __init__(self, msg=None):
+        if msg is not None:
+            self.msg = msg
+
+    def to_json(self):
+        return {
+            "message": self.msg,
+            "status_code": self.status_code,
+        }
+
+
+class ConfigError(ApiError):
     """ Raised when a malformed configuration is detected. """
-    pass
+    status_code = 500
+
+
+class UpstreamError(ApiError):
+    """ Raised when an external service responds with an error code. """
+    status_code = 500

+ 5 - 2
scriptshifter/hooks/hebrew/dicta_api.py

@@ -2,7 +2,7 @@ from os import environ
 
 from requests import post
 
-from scriptshifter.exceptions import BREAK
+from scriptshifter.exceptions import BREAK, UpstreamError
 from scriptshifter.tools import capitalize
 
 EP = environ.get("TXL_DICTA_EP")
@@ -20,7 +20,10 @@ def s2r_post_config(ctx):
                 "data": ctx.src,
                 "genre": ctx.options.get("genre", DEFAULT_GENRE)
             })
-    rsp.raise_for_status()
+    try:
+        rsp.raise_for_status()
+    except Exception:
+        raise UpstreamError("Error received from Dicta service.")
 
     rom = rsp.json().get("transliteration")
 

+ 11 - 8
scriptshifter/rest_api.py

@@ -2,12 +2,12 @@ import logging
 
 from base64 import b64encode
 from copy import deepcopy
-from json import loads
+from json import dumps, loads
 from os import environ, urandom
 
 from flask import Flask, jsonify, render_template, request
 
-# from scriptshifter.exceptions import ApiError
+from scriptshifter.exceptions import ApiError
 from scriptshifter.tables import list_tables, load_table
 from scriptshifter.trans import transliterate
 
@@ -32,12 +32,15 @@ def create_app():
 app = create_app()
 
 
-#@app.exception_handler(ApiError)
-#def handle_exception(request: Request, e: ApiError):
-#    return JSONResponse(
-#        content=e.to_json(),
-#        status_code=e.status_code
-#    )
+@app.errorhandler(ApiError)
+def handle_exception(e: ApiError):
+    return ({
+        "warnings": [
+            "ScriptShifter HTTP request failed with status code "
+            f"{e.status_code}: {e.msg}"
+        ],
+        "output": "",
+    }, e.status_code)
 
 
 @app.route("/", methods=["GET"])

+ 15 - 2
scriptshifter/templates/index.html

@@ -121,15 +121,28 @@
                         label.setAttribute("for", opt.id);
                         label.append(opt.label);
 
-                        let input = document.createElement("input");
-                        if (opt.type == "boolean") {
+                        var input;
+                        if (opt.type == "list") {
+                            input = document.createElement("select");
+                            opt.options.forEach((sel) => {
+                                let option = document.createElement("option");
+                                option.append(sel.label);
+                                option.value = sel.id;
+                                if (option.value == opt.default) {
+                                    option.selected = true;
+                                };
+                                input.append(option);
+                            })
+                        } else if (opt.type == "boolean") {
                             // Use checkbox for boolean type.
+                            input = document.createElement("input");
                             input.setAttribute("type", "checkbox");
                             if (opt.default) {
                                 input.setAttribute("checked", 1);
                             }
                         } else {
                             // Use text for all other types.
+                            input = document.createElement("input");
                             input.value = opt.default;
                         }
                         input.setAttribute("id", opt.id);