about summary refs log tree commit diff
path: root/uploader/route_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'uploader/route_utils.py')
-rw-r--r--uploader/route_utils.py90
1 files changed, 90 insertions, 0 deletions
diff --git a/uploader/route_utils.py b/uploader/route_utils.py
new file mode 100644
index 0000000..53247e6
--- /dev/null
+++ b/uploader/route_utils.py
@@ -0,0 +1,90 @@
+"""Generic routing utilities."""
+import logging
+from json.decoder import JSONDecodeError
+
+from flask import (flash,
+                   url_for,
+                   request,
+                   redirect,
+                   render_template,
+                   current_app as app)
+
+from gn_libs.mysqldb import database_connection
+
+from uploader.datautils import base64_encode_dict, base64_decode_to_dict
+from uploader.population.models import (populations_by_species,
+                                        population_by_species_and_id)
+
+logger = logging.getLogger(__name__)
+
+def generic_select_population(
+        # pylint: disable=[too-many-arguments, too-many-positional-arguments]
+        species: dict,
+        template: str,
+        population_id: str,
+        back_to: str,
+        forward_to: str,
+        activelink: str,
+        error_message: str = "No such population found!"
+):
+    """Handles common flow for 'select population' step."""
+    with database_connection(app.config["SQL_URI"]) as conn:
+        if not bool(population_id):
+            return render_template(
+                template,
+                species=species,
+                populations=populations_by_species(conn, species["SpeciesId"]),
+                activelink=activelink)
+
+        if population_id == "CREATE-POPULATION":
+            return redirect(url_for(
+                "species.populations.create_population",
+                species_id=species["SpeciesId"],
+                return_to=forward_to))
+
+        population = population_by_species_and_id(
+            conn, species["SpeciesId"], int(population_id))
+        if not bool(population):
+            flash(error_message, "alert-danger")
+            return redirect(url_for(back_to, species_id=species["SpeciesId"]))
+
+        return redirect(url_for(forward_to,
+                                species_id=species["SpeciesId"],
+                                population_id=population["Id"]))
+
+
+def redirect_to_next(default: dict):
+    """Redirect to the next uri if specified, else redirect to default."""
+    assert "uri" in default, "You must provide at least the 'uri' value."
+    try:
+        next_page = base64_decode_to_dict(request.args.get("next"))
+        _uri = next_page["uri"]
+        next_page.pop("uri")
+        return redirect(url_for(_uri, **next_page))
+    except (TypeError, JSONDecodeError) as _err:
+        logger.debug("We could not decode the next value '%s'",
+                     next_page,
+                     exc_info=True)
+
+    return redirect(url_for(
+        default["uri"],
+        **{key:value for key,value in default.items() if key != "uri"}))
+
+
+def build_next_argument(uri: str, **kwargs) -> str:
+    """Build the `next` URI argument from provided details."""
+    dumps_keywords = (
+        "skipkeys", "ensure_ascii", "check_circular", "allow_nan", "cls",
+        "indent", "separators", "default", "sort_keys")
+    return base64_encode_dict(
+        {
+            "uri": uri,
+            **{
+                key: val for key,val in kwargs.items()
+                if key not in dumps_keywords
+            }
+        },
+        **{
+            key: val for key,val in kwargs.items()
+            if key in dumps_keywords
+        })