def export(conn): tsv = export_terms(conn, ["OBI:0100046"], ["CURIE", "label", "definition"], "tsv") actual_lines = tsv.split("\n") expected_lines = [] with open("tests/resources/obi-export.tsv", "r") as f: for line in f: expected_lines.append(line.strip()) diff = get_diff(actual_lines, expected_lines) if diff: print("The actual and expected outputs differ:") print() for line in diff: print(line) assert not diff
def export_no_predicates(conn): tsv = export_terms(conn, ["OBI:0100046"], None, "tsv", default_value_format="CURIE") with open("test.tsv", "w") as f: f.write(tsv) actual_lines = tsv.split("\n") actual_lines = [x.strip() for x in actual_lines] expected_lines = [] with open("tests/resources/obi-export-all.tsv", "r") as f: for line in f: expected_lines.append(line.strip()) diff = get_diff(actual_lines, expected_lines) if diff: print("The actual and expected outputs differ:") print() for line in diff: print(line) assert not diff
def update(): user_id = session.get("user_id") if request.args.get("add"): args = request.args template = args.get("template") term_id = unquote(args.get("ontology-ID")) message = add_to_template(user_id, template, args, exists=True) return render_tree("obi", term_id, message=message, from_update=True) term_id = unquote(request.args.get("term")) if not term_id: abort(400, "A term is required in the parameters.") obi_db = os.path.join(DATABASE_DIR, "obi.db") if not os.path.exists(obi_db): abort(400, "build/obi.db must exist in DROID directory for term updating") message = "" # Find the location of this term fname, line = locate_term(term_id) if fname == "build/obi-edit.db": obi_db = os.path.join(DATABASE_DIR, "obi.db") if not os.path.exists(obi_db): abort( 400, "build/obi.db must exist in DROID directory for term updating") with sqlite3.connect(obi_db) as conn: # Get the annotation properties that we want cur = conn.cursor() aps = get_annotation_properties(cur) # Get the term label cur.execute( "SELECT value FROM statements WHERE stanza = ? AND predicate = 'rdfs:label'", (term_id, ), ) res = cur.fetchone() label = None if res: label = res[0] # Close the cursor to unlock the database cur.close() # Export annotations annotations = export.export_terms(conn, [term_id], sorted(aps.keys()), "tsv", default_value_format="label") # Export logic logic = export.export_terms( conn, [term_id], ["rdfs:subClassOf", "owl:equivalentClass"], "tsv", default_value_format="label", no_headers=True, ) ann_headers = annotations.split("\n")[0].split("\t") ann_details = annotations.split("\n")[1].split("\t") logic_details = logic.strip().split("\t") metadata_html = [] # Add the ontology ID element field = build_form_field("text", "ontology ID", None, True, value=term_id) if field: metadata_html.extend(field) # Add the label element field = build_form_field("text", "label", None, True, value=label) if field: metadata_html.extend(field) # Add the rest of the annotations i = 0 while i < len(ann_headers): header = ann_headers[i] detail = ann_details[i] ap_label = aps[header] i += 1 if header.startswith("<"): continue field = build_form_field("text", ap_label, None, False, value=detail) if not field: logging.warning("Could not build field for property: " + ap_label) continue metadata_html.extend(field) logic_html = [] # TODO: these are not including anon classes, wait for thick triples? # Maybe add subclass if len(logic_details) == 1: field = build_form_field("search", "parent class", None, False, value=logic_details[0]) if not field: logging.warning("Could not build field for parent class") else: logic_html.extend(field) # Maybe add equivalent class if len(logic_details) == 2: field = build_form_field("search", "equivalent class", None, False, value=logic_details[1]) if not field: logging.warning("Could not build field for equivalent class") else: logic_html.extend(field) if label and " " in label: # Encase in single quotes when label has a space label = f"'{label}'" return render_template( "edit-term.html", title=f"Update " + label or term_id, metadata="\n".join(metadata_html), logic="\n".join(logic_html), message=message, user=True, ) elif fname.startswith(TEMPLATES_DIR): # Get the template name & its fields template = os.path.splitext(os.path.basename(fname))[0] metadata_fields, logic_fields = get_template_fields(template) # Get the current values for this term from the template with open(fname, "r") as f: reader = csv.DictReader(f, delimiter="\t") row = next((x for i, x in enumerate(reader) if i == line - 2), None) if not row: abort(500, f"Unable to find row {line} in " + fname) metadata_values = {} for field in metadata_fields.keys(): metadata_values[field] = row.get(field, "") logic_values = {} for field in logic_fields.keys(): logic_values[field] = row.get(field, "") hidden = {"template": template} metadata_html = build_form_html(metadata_fields, values=metadata_values, hidden=hidden) logic_html = build_form_html(logic_fields, values=logic_values) # Term is in a template file - we will get the details and create the form return render_template( "edit-term.html", title=f"Update " + term_id, metadata="\n".join(metadata_html), logic="\n".join(logic_html), message=message, user=True, ) # TODO: Term is in an import file - we give option to update parent or delete # We also need to determine how to edit an import term that is a specified descendant/ancestor message = build_message("warning", "Unable to edit import terms at this time.") return render_tree("obi", term_id, message=message, from_update=True)
def show_export(): remove_term = request.args.get("remove") # Get the terms to display user_id = session.get("user_id") exports = Export.query.filter_by(user_id=user_id) terms = [] for e in exports: if not e.term_id: logging.info("Missing term_id, removing export entry") db_session.delete(e) db_session.commit() elif e.term_id == remove_term: logging.info("Removing " + remove_term) db_session.delete(e) db_session.commit() else: terms.append(e.term_id) logging.info(terms) if not terms: return render_template("base.html", default="There are no terms to export.", user=True) terms = sorted(terms) # Get annotation properties from OBI obi_db = os.path.join(DATABASE_DIR, "obi.db") if not os.path.exists(obi_db): abort(400, "build/obi.db must exist in DROID directory for exporting") with sqlite3.connect(obi_db) as conn: cur = conn.cursor() aps = get_annotation_properties(cur) aps.update({ "CURIE": "ontology ID", "rdfs:label": "label", "rdfs:subClassOf": "parent class", "owl:equivalentClass": "equivalent class", "owl:disjointWith": "disjoint class" }) cur.close() with sqlite3.connect(obi_db) as conn: # TODO - make display configurable, display as label, IRI, or CURIE export_table = export.export_terms(conn, terms, aps.keys(), "tsv", default_value_format="label") # Only include headers with values f = StringIO(export_table) reader = csv.DictReader(f, delimiter="\t") headers = set() rows = [] for row in reader: new_itm = {} for k, v in row.items(): if v: ap_label = aps[k] new_itm[ap_label] = v headers.add(ap_label) rows.append(new_itm) # Sort headers alphabetically headers = sorted(headers) # Place ID first then label headers.remove("label") headers.insert(0, "label") headers.remove("ontology ID") headers.insert(0, "ontology ID") rows_fixed = [] for row in rows: new_row = [] term_id = None for h in headers: if h == "ontology ID": term_id = row[h] new_row.append(row.get(h, "")) new_row.insert(0, f'<a href="export?remove={term_id}">x</a>') rows_fixed.append(new_row) headers.insert(0, "") export_fmt = request.args.get("format") if export_fmt: fw = StringIO() sep = "\t" mt = "text/tab-separated-values" if export_fmt == "csv": sep = "," mt = "text/comma-separated-values" elif export_fmt != "tsv": abort(400, "Not a valid export format: " + export_fmt) writer = csv.DictWriter(fw, delimiter=sep, lineterminator="\n", fieldnames=headers) writer.writeheader() writer.writerows(rows) return Response(fw.getvalue(), mimetype=mt) return render_template("table.html", headers=headers, rows=rows_fixed, export=True, user=True)