"""File parsing module""" import os from functools import reduce import jsonpickle from redis import Redis from flask import ( flash, request, url_for, redirect, Blueprint, render_template, current_app as app) from . import jobs from quality_control.errors import InvalidValue from quality_control.parsing import ( FileType, strain_names) parsebp = Blueprint("parse", __name__) @parsebp.route("/parse", methods=["GET"]) def parse(): """Trigger file parsing""" # TODO: Maybe implement external process to parse the files errors = False filename = request.args.get("filename") filetype = request.args.get("filetype") if filename is None: flash("No file provided", "alert-error") errors = True if filetype is None: flash("No filetype provided", "alert-error") errors = True if filetype not in ("average", "standard-error"): flash("Invalid filetype provided", "alert-error") errors = True filepath = os.path.join(app.config["UPLOAD_FOLDER"], filename) if not os.path.exists(filepath): flash("Selected file does not exist (any longer)", "alert-danger") errors = True if errors: return redirect(url_for("entry.upload_file")) with Redis.from_url(app.config["REDIS_URL"], decode_responses=True) as rconn: job = jobs.launch_job( rconn, filepath, filetype, app.config["REDIS_URL"], f"{app.config['UPLOAD_FOLDER']}/job_errors") return redirect(url_for("parse.parse_status", job_id=job["job_id"])) @parsebp.route("/status/", methods=["GET"]) def parse_status(job_id: str): with Redis.from_url(app.config["REDIS_URL"], decode_responses=True) as rconn: job = jobs.job(rconn, job_id) if job: error_filename = jobs.error_filename( job_id, f"{app.config['UPLOAD_FOLDER']}/job_errors") if os.path.exists(error_filename): stat = os.stat(error_filename) if stat.st_size > 0: return redirect(url_for("parse.fail", job_id=job_id)) print(f"THE JOB {job}") job_id = job["job_id"] progress = float(job["percent"]) status = job["status"] filename = job.get("filename", "uploaded file") if status == "success": return redirect(url_for("parse.results", job_id=job_id)) if status == "parse-error": return redirect(url_for("parse.fail", job_id=job_id)) return render_template( "job_progress.html", job_id = job_id, job_status = status, progress = progress, message = job.get("message", ""), job_name = f"Parsing '{filename}'") return render_template("no_such_job.html", job_id=job_id) @parsebp.route("/results/", methods=["GET"]) def results(job_id: str): """Show results of parsing...""" with Redis.from_url(app.config["REDIS_URL"], decode_responses=True) as rconn: job = jobs.job(rconn, job_id) if job: filename = job["filename"] errors = jsonpickle.decode(job["errors"]) return render_template( "parse_results.html", errors=errors, job_name = f"Parsing '{filename}'", isinvalidvalue=lambda item: isinstance(item, InvalidValue)) return render_template("no_such_job.html", job_id=job_id) @parsebp.route("/fail/", methods=["GET"]) def fail(job_id: str): """Handle parsing failure""" with Redis.from_url(app.config["REDIS_URL"], decode_responses=True) as rconn: job = jobs.job(rconn, job_id) if job: error_filename = jobs.error_filename( job_id, f"{app.config['UPLOAD_FOLDER']}/job_errors") if os.path.exists(error_filename): stat = os.stat(error_filename) if stat.st_size > 0: return render_template( "worker_failure.html", job_id=job_id) return render_template("parse_failure.html", job=job) return render_template("no_such_job.html", job_id=job_id)