diff options
| author | Munyoki Kilyungi | 2025-06-26 14:47:28 +0300 |
|---|---|---|
| committer | BonfaceKilz | 2025-07-07 07:58:31 +0300 |
| commit | e7d47ab9fa19a4b2aedfe33ba22c4e6d17c75740 (patch) | |
| tree | 833d4e9fc420882a4bc3b2510ce469b6f0bee684 /gn3/api/case_attributes.py | |
| parent | 43ce9c668ccd34675d68241cd1d6d8afd262a121 (diff) | |
| download | genenetwork3-e7d47ab9fa19a4b2aedfe33ba22c4e6d17c75740.tar.gz | |
Delete unused case-attributes functions and variables.
Signed-off-by: Munyoki Kilyungi <me@bonfacemunyoki.com>
Diffstat (limited to 'gn3/api/case_attributes.py')
| -rw-r--r-- | gn3/api/case_attributes.py | 281 |
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 |
