diff options
author | Frederick Muriuki Muriithi | 2023-08-30 12:42:28 +0300 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2023-10-10 11:12:49 +0300 |
commit | 3e06396c8966250540e72f7fa909b78dd10a5534 (patch) | |
tree | 4de835b81170fe67e98ee1712b18b409a7da1a6e | |
parent | 567e6f00efbf700adf82d6118be445b66b5e212d (diff) | |
download | genenetwork3-3e06396c8966250540e72f7fa909b78dd10a5534.tar.gz |
Implement some queuing logic for diffs
Queue the diffs into files - this might change somewhat once we verify whether
case-attribute editing needs an approval step.
-rw-r--r-- | gn3/case_attributes.py | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/gn3/case_attributes.py b/gn3/case_attributes.py index 3e22764..04df030 100644 --- a/gn3/case_attributes.py +++ b/gn3/case_attributes.py @@ -3,7 +3,9 @@ import os import csv import json import tempfile +from pathlib import Path from functools import reduce +from datetime import datetime from MySQLdb.cursors import DictCursor from flask import jsonify, request, Response, Blueprint, current_app @@ -19,6 +21,8 @@ from gn3.auth.authorisation.errors import AuthorisationError caseattr = Blueprint("case-attribute", __name__) +CATTR_DIFFS_DIR = "case-attribute-diffs" + class NoDiffError(ValueError): """Raised if there is no difference between the old and new data.""" def __init__(self): @@ -171,7 +175,7 @@ def __compute_diff__(fieldnames: tuple[str, ...], original_data: tuple[dict, ... return json.loads(diff_results["output"]) return {} -def __queue_diff__(conn: Connection, user: User, diff) -> str: +def __queue_diff__(conn: Connection, diff_data, diff_data_dir: Path) -> Path: """ Queue diff for future processing. @@ -179,9 +183,20 @@ def __queue_diff__(conn: Connection, user: User, diff) -> str: On success, this will return the filename where the diff was saved. On failure, it will raise a MySQL error. """ + diff = diff_data["diff"] if bool(diff["Additions"]) or bool(diff["Modifications"]) or bool(diff["Deletions"]): # TODO: Check user has "edit case attribute privileges" - raise NotImplementedError + diff_data_dir.mkdir(parents=True, exist_ok=True) + + created = datetime.now() + filepath = Path( + diff_data_dir, + f"{diff_data['inbredset_id']}:::{diff_data['user_id']}:::" + f"{created.isoformat()}.json") + with open(filepath, "w", encoding="utf8") as diff_file: + # We want this to fail if the metadata items below are not provided. + diff_file.write(json.dumps({**diff_data, "created": created.isoformat()})) + return filepath raise NoDiffError def __apply_diff__(conn: Connection, user: User, diff_filename) -> None: @@ -226,24 +241,24 @@ def edit_case_attributes(inbredset_id: int) -> Response: database_connection(current_app.config["SQL_URI"]) as conn): # TODO: Check user has "edit case attribute privileges" user = the_token.user + fieldnames = (["Strain"] + sorted( + attr["Name"] for attr in + __case_attribute_labels_by_inbred_set__(conn, inbredset_id))) try: - fieldnames = (["Strain"] + sorted( - attr["Name"] for attr in - __case_attribute_labels_by_inbred_set__(conn, inbredset_id))) - diff_filename = __queue_diff__(conn, user, __compute_diff__( - fieldnames, - __process_orig_data__( - fieldnames, - __case_attribute_values_by_inbred_set__(conn, inbredset_id), - __inbredset_strains__(conn, inbredset_id)), - __process_edit_data__(fieldnames, request.json["edit-data"]))) - - __apply_diff__(conn, user, diff_filename) - return jsonify({ - "diff-status": "applied", - "message": ("The changes to the case-attributes have been " - "applied successfully.") - }) + diff_filename = __queue_diff__( + conn, { + "inbredset_id": inbredset_id, + "user_id": str(user.user_id), + "fieldnames": fieldnames, + "diff": __compute_diff__( + fieldnames, + __process_orig_data__( + fieldnames, + __case_attribute_values_by_inbred_set__(conn, inbredset_id), + __inbredset_strains__(conn, inbredset_id)), + __process_edit_data__(fieldnames, request.json["edit-data"])) + }, + Path(current_app.config.get("TMPDIR"), CATTR_DIFFS_DIR)) except NoDiffError as _nde: msg = "There were no changes to make from submitted data." response = jsonify({ @@ -252,6 +267,14 @@ def edit_case_attributes(inbredset_id: int) -> Response: }) response.status_code = 400 return response + + try: + __apply_diff__(conn, user, diff_filename) + return jsonify({ + "diff-status": "applied", + "message": ("The changes to the case-attributes have been " + "applied successfully.") + }) except AuthorisationError as _auth_err: return jsonify({ "diff-status": "queued", |