diff options
author | Frederick Muriuki Muriithi | 2024-07-29 16:04:13 -0500 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2024-08-05 09:52:18 -0500 |
commit | e16d7750c9f1e754a3e14a496380de0b014fffe1 (patch) | |
tree | c24e12b1381cd61363febfc5bcde165bd8fd0a46 /uploader/monadic_requests.py | |
parent | d3fd64fb5237febb9628c4ccbd259969327ab2ec (diff) | |
download | gn-uploader-e16d7750c9f1e754a3e14a496380de0b014fffe1.tar.gz |
Provide a generalised way to handle errors and exceptions.
Diffstat (limited to 'uploader/monadic_requests.py')
-rw-r--r-- | uploader/monadic_requests.py | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/uploader/monadic_requests.py b/uploader/monadic_requests.py index f0a60f4..aa34951 100644 --- a/uploader/monadic_requests.py +++ b/uploader/monadic_requests.py @@ -1,9 +1,57 @@ """Wrap requests functions with monads.""" +import traceback +from typing import Union, Optional, Callable + import requests +from requests.models import Response from pymonad.either import Left, Right, Either +from flask import ( + flash, + request, + redirect, + render_template, + current_app as app, + escape as flask_escape) +# HTML Status codes indicating a successful request. SUCCESS_CODES = (200, 201, 202, 203, 204, 205, 206, 207, 208, 226) +# Possible error(s) that can be encontered while attempting to do a request. +PossibleError = Union[Response, Exception] + + +def make_error_handler( + redirect_to: Optional[Response] = None, + cleanup_thunk: Callable = lambda *args: None +) -> Callable[[PossibleError], Response]: + """ + Build a function to gracefully handle errors encountered while doing + requests. + + :rtype: Callable + """ + redirect_to = redirect_to or redirect(request.url) + def __handler__(resp_or_exc: PossibleError) -> Response: + cleanup_thunk() + if issubclass(type(resp_or_exc), Exception): + # Is an exception! + return render_template( + "unhandled_exception.html", + trace=traceback.format_exception(resp_or_exc)) + if isinstance(resp_or_exc, Response): + flash("The authorisation server responded with " + f"({flask_escape(resp_or_exc.status_code)}, " + f"{flask_escape(resp_or_exc.reason)}) for the request to " + f"'{flask_escape(resp_or_exc.request.url)}'", + "alert-danger") + return redirect_to + + flash("Unspecified error!", "alert-danger") + app.logger.debug("Error (%s): %s", type(resp_or_exc), resp_or_exc) + return redirect_to + return __handler__ + + def get(url, params=None, **kwargs) -> Either: """ A wrapper around `requests.get` function. |