diff options
Diffstat (limited to 'uploader/route_utils.py')
| -rw-r--r-- | uploader/route_utils.py | 90 |
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 + }) |
