about summary refs log tree commit diff
path: root/gn3/api/case_attributes.py
diff options
context:
space:
mode:
Diffstat (limited to 'gn3/api/case_attributes.py')
-rw-r--r--gn3/api/case_attributes.py281
1 files changed, 0 insertions, 281 deletions
diff --git a/gn3/api/case_attributes.py b/gn3/api/case_attributes.py
index f5e2f92..b7f50ad 100644
--- a/gn3/api/case_attributes.py
+++ b/gn3/api/case_attributes.py
@@ -36,29 +36,6 @@ from gn3.oauth2.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):
-        """Initialise exception."""
-        super().__init__(
-            self, "No difference between existing data and sent data.")
-
-
-class CAJSONEncoder(json.JSONEncoder):
-    """Encoder for CaseAttribute-specific data"""
-
-    def default(self, obj):  # pylint: disable=[arguments-renamed]
-        """Default encoder"""
-        if isinstance(obj, datetime):
-            return obj.isoformat()
-        if isinstance(obj, uuid.UUID):
-            return str(obj)
-        return json.JSONEncoder.default(self, obj)
-
 
 def required_access(
         token: dict,
@@ -211,264 +188,6 @@ def inbredset_case_attribute_values(inbredset_id: int) -> Response:
         return jsonify(__case_attribute_values_by_inbred_set__(conn, inbredset_id))
 
 
-def __process_orig_data__(fieldnames, cadata, strains) -> tuple[dict, ...]:
-    """Process data from database and return tuple of dicts."""
-    data = {item["StrainName"]: item for item in cadata}
-    return tuple(
-        {
-            "Sample": strain["Name"],
-            **{
-                key: data.get(
-                    strain["Name"], {}).get("case-attributes", {}).get(key, "")
-                for key in fieldnames[1:]
-            }
-        } for strain in strains)
-
-
-def __process_edit_data__(fieldnames, form_data) -> tuple[dict, ...]:
-    """Process data from form and return tuple of dicts."""
-    def __process__(acc, strain_cattrs):
-        strain, cattrs = strain_cattrs
-        return acc + ({
-            "Sample": strain, **{
-                field: cattrs["case-attributes"].get(field, "")
-                for field in fieldnames[1:]
-            }
-        },)
-    return reduce(__process__, form_data.items(), tuple())
-
-
-def __write_csv__(fieldnames, data):
-    """Write the given `data` to a csv file and return the path to the file."""
-    fdesc, filepath = tempfile.mkstemp(".csv")
-    os.close(fdesc)
-    with open(filepath, "w", encoding="utf-8") as csvfile:
-        writer = csv.DictWriter(csvfile, fieldnames=fieldnames, dialect="unix")
-        writer.writeheader()
-        writer.writerows(data)
-
-    return filepath
-
-
-def __compute_diff__(
-        fieldnames: tuple[str, ...],
-        original_data: tuple[dict, ...],
-        edit_data: tuple[dict, ...]):
-    """Return the diff of the data."""
-    basefilename = __write_csv__(fieldnames, original_data)
-    deltafilename = __write_csv__(fieldnames, edit_data)
-    diff_results = run_cmd(json.dumps(
-        ["csvdiff", basefilename, deltafilename, "--format", "json"]))
-    os.unlink(basefilename)
-    os.unlink(deltafilename)
-    if diff_results["code"] == 0:
-        return json.loads(diff_results["output"])
-    return {}
-
-
-def __queue_diff__(conn: Connection, diff_data, diff_data_dir: Path) -> Path:
-    """
-    Queue diff for future processing.
-
-    Returns: `diff`
-        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"]):
-        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.
-            the_diff = {**diff_data, "created": created}
-            insert_id = __save_diff__(conn, the_diff, EditStatus.review)
-            diff_file.write(json.dumps({**the_diff, "db_id": insert_id},
-                                       cls=CAJSONEncoder))
-        return filepath
-    raise NoDiffError
-
-
-def __save_diff__(conn: Connection, diff_data: dict, status: EditStatus) -> int:
-    """Save to the database."""
-    with conn.cursor() as cursor:
-        cursor.execute(
-            "INSERT INTO "
-            "caseattributes_audit(id, status, editor, json_diff_data, time_stamp) "
-            "VALUES(%(db_id)s, %(status)s, %(editor)s, %(diff)s, %(ts)s) "
-            "ON DUPLICATE KEY UPDATE status=%(status)s",
-            {
-                "db_id": diff_data.get("db_id"),
-                "status": str(status),
-                "editor": str(diff_data["user_id"]),
-                "diff": json.dumps(diff_data, cls=CAJSONEncoder),
-                "ts": diff_data["created"].isoformat()
-            })
-        return diff_data.get("db_id") or cursor.lastrowid
-
-
-def __parse_diff_json__(json_str):
-    """Parse the json string to python objects."""
-    raw_diff = json.loads(json_str)
-    return {
-        **raw_diff,
-        "db_id": int(raw_diff["db_id"]) if raw_diff.get("db_id") else None,
-        "inbredset_id": (int(raw_diff["inbredset_id"])
-                         if raw_diff.get("inbredset_id") else None),
-        "user_id": (uuid.UUID(raw_diff["user_id"])
-                    if raw_diff.get("user_id") else None),
-        "created": (datetime.fromisoformat(raw_diff["created"])
-                    if raw_diff.get("created") else None)
-    }
-
-
-def __load_diff__(diff_filename):
-    """Load the diff."""
-    with open(diff_filename, encoding="utf8") as diff_file:
-        return __parse_diff_json__(diff_file.read())
-
-
-def __apply_additions__(
-        cursor, inbredset_id: int, additions_diff) -> None:
-    """Apply additions: creates new case attributes."""
-    # TODO: Not tested... will probably fail.
-    cursor.execute(
-        "INSERT INTO CaseAttribute(InbredSetId, Name, Description) "
-        "VALUES (:inbredset_id, :name, :desc)",
-        tuple({
-            "inbredset_id": inbredset_id,
-            "name": diff["name"],
-            "desc": diff["description"]
-        } for diff in additions_diff))
-
-
-def __apply_modifications__(
-        cursor, inbredset_id: int, modifications_diff, fieldnames) -> None:
-    """Apply modifications: changes values of existing case attributes."""
-    cattrs = tuple(field for field in fieldnames if field != "Sample")
-
-    def __retrieve_changes__(acc, row):
-        orig = dict(zip(fieldnames, row["Original"].split(",")))
-        new = dict(zip(fieldnames, row["Current"].split(",")))
-        return acc + tuple({
-            "Sample": new["Sample"],
-            cattr: new[cattr]
-        } for cattr in cattrs if new[cattr] != orig[cattr])
-
-    new_rows: tuple[dict, ...] = reduce(
-        __retrieve_changes__, modifications_diff, tuple())
-    strain_names = tuple({row["Sample"] for row in new_rows})
-    cursor.execute("SELECT Id AS StrainId, Name AS StrainName FROM Strain "
-                   f"WHERE Name IN ({', '.join(['%s'] * len(strain_names))})",
-                   strain_names)
-    strain_ids = {
-        row["StrainName"]: int(row["StrainId"])
-        for row in cursor.fetchall()}
-
-    cursor.execute("SELECT CaseAttributeId, Name AS CaseAttributeName "
-                   "FROM CaseAttribute WHERE InbredSetId=%s "
-                   f"AND Name IN ({', '.join(['%s'] * len(cattrs))})",
-                   (inbredset_id,) + cattrs)
-    cattr_ids = {
-        row["CaseAttributeName"]: row["CaseAttributeId"]
-        for row in cursor.fetchall()
-    }
-
-    cursor.executemany(
-        "INSERT INTO CaseAttributeXRefNew"
-        "(InbredSetId, StrainId, CaseAttributeId, Value) "
-        "VALUES(%(isetid)s, %(strainid)s, %(cattrid)s, %(value)s) "
-        "ON DUPLICATE KEY UPDATE Value=VALUES(value)",
-        tuple(
-            {
-                "isetid": inbredset_id,
-                "strainid": strain_ids[row["Sample"]],
-                "cattrid": cattr_ids[cattr],
-                "value": row[cattr]
-            }
-            for cattr in cattrs for row in new_rows
-            if bool(row.get(cattr, "").strip())))
-    cursor.executemany(
-        "DELETE FROM CaseAttributeXRefNew WHERE "
-        "InbredSetId=%(isetid)s AND StrainId=%(strainid)s "
-        "AND CaseAttributeId=%(cattrid)s",
-        tuple(
-            {
-                "isetid": inbredset_id,
-                "strainid": strain_ids[row["Sample"]],
-                "cattrid": cattr_ids[cattr]
-            }
-            for row in new_rows
-            for cattr in (key for key in row.keys() if key != "Sample")
-            if not bool(row[cattr].strip())))
-
-
-def __apply_deletions__(
-        cursor, inbredset_id: int, deletions_diff) -> None:
-    """Apply deletions: delete existing case attributes and their values."""
-    # TODO: Not tested... will probably fail.
-    params = tuple({
-        "inbredset_id": inbredset_id,
-        "case_attribute_id": diff["case_attribute_id"]
-    } for diff in deletions_diff)
-    cursor.executemany(
-        "DELETE FROM CaseAttributeXRefNew WHERE "
-        "InbredSetId=:inbredset_id AND CaseAttributeId=:case_attribute_id",
-        params)
-    cursor.executemany(
-        "DELETE FROM CaseAttribute WHERE "
-        "InbredSetId=:inbredset_id AND CaseAttributeId=:case_attribute_id",
-        params)
-
-
-def __apply_diff__(
-        conn: Connection, auth_token, inbredset_id: int, diff_filename, the_diff) -> None:
-    """
-    Apply the changes in the diff at `diff_filename` to the data in the database
-    if the user has appropriate privileges.
-    """
-    required_access(auth_token,
-                    inbredset_id,
-                    ("system:inbredset:edit-case-attribute",
-                     "system:inbredset:apply-case-attribute-edit"))
-    diffs = the_diff["diff"]
-    with conn.cursor(cursorclass=DictCursor) as cursor:
-        # __apply_additions__(cursor, inbredset_id, diffs["Additions"])
-        __apply_modifications__(
-            cursor, inbredset_id, diffs["Modifications"], the_diff["fieldnames"])
-        # __apply_deletions__(cursor, inbredset_id, diffs["Deletions"])
-        __save_diff__(conn, the_diff, EditStatus.approved)
-        new_path = Path(
-            diff_filename.parent,
-            f"{diff_filename.stem}-approved{diff_filename.suffix}")
-        os.rename(diff_filename, new_path)
-
-
-def __reject_diff__(conn: Connection,
-                    auth_token: dict,
-                    inbredset_id: int,
-                    diff_filename: Path,
-                    diff: dict) -> Path:
-    """
-    Reject the changes in the diff at `diff_filename` to the data in the
-    database if the user has appropriate privileges.
-    """
-    required_access(auth_token,
-                    inbredset_id,
-                    ("system:inbredset:edit-case-attribute",
-                     "system:inbredset:apply-case-attribute-edit"))
-    __save_diff__(conn, diff, EditStatus.rejected)
-    new_path = Path(diff_filename.parent,
-                    f"{diff_filename.stem}-rejected{diff_filename.suffix}")
-    os.rename(diff_filename, new_path)
-    return diff_filename
-
-
-
 
 @caseattr.route("/<int:inbredset_id>/edit", methods=["POST"])
 @require_token