"""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 })