diff --git a/src/oaklib/interfaces/basic_ontology_interface.py b/src/oaklib/interfaces/basic_ontology_interface.py
index 22038ab30..a5d8d1afa 100644
--- a/src/oaklib/interfaces/basic_ontology_interface.py
+++ b/src/oaklib/interfaces/basic_ontology_interface.py
@@ -203,7 +203,7 @@ def converter(self) -> curies.Converter:
:return: A converter
"""
if self._converter is None:
- self._converter = curies.Converter.from_prefix_map(self.prefix_map())
+ self._converter = curies.Converter.from_prefix_map(self.prefix_map(), strict=False)
return self._converter
def set_metamodel_mappings(self, mappings: Union[str, Path, List[Mapping]]) -> None:
diff --git a/tests/input/obo-compliance.obo b/tests/input/obo-compliance.obo
index f70afd914..20df87b16 100644
--- a/tests/input/obo-compliance.obo
+++ b/tests/input/obo-compliance.obo
@@ -565,6 +565,53 @@ idspace: Y http://example.org/Y/
id: X:1
created_by: Y:1
+!! name: prefixes-conflict-oio
+!! description: tests conflicting prefixes/contractions for oboInOwl namespace, where oio might be built-in
+!! unstable: true
+!! seeAlso: https://github.com/INCATools/ontology-access-kit/issues/760
+idspace: oboInOwl http://www.geneontology.org/formats/oboInOwl#
+
+[Term]
+id: X:1
+name: X:1
+def: "." []
+
+!! name: prefixes-conflict-skos
+!! description: tests conflicting prefixes for the SKOS namespace
+!! unstable: true
+!! seeAlso: https://github.com/INCATools/ontology-access-kit/issues/760
+idspace: skos http://example.org/not-skos/
+
+[Term]
+id: X:1
+property_value: skos:exactMatch Y:1
+
+[Typedef]
+id: skos:exactMatch
+is_metadata_tag: true
+
+!! name: prefixes-conflict-main-idspace
+!! description: tests conflicting prefixes for the main ID space
+!! invalid: true
+!! seeAlso: https://github.com/INCATools/ontology-access-kit/issues/760
+idspace: X http://example.org/X/
+idspace: FAKEX http://example.org/X/
+
+[Term]
+id: X:1
+name: X:1
+
+!! name: expansion-conflict-main-idspace
+!! description: tests conflicting expansions for the main ID space
+!! invalid: true
+!! seeAlso: https://github.com/INCATools/ontology-access-kit/issues/760
+idspace: X http://example.org/X/
+idspace: X http://example.org/FAKEX/
+
+[Term]
+id: X:1
+name: X:1
+
!! # #########
!! # Headers
!! # #########
@@ -658,6 +705,20 @@ subset: S {source="PMID:123464"}
id: X:1
disjoint_from: X:2 {source="PMID:123465"}
+!! name: gci-relation
+!! description: General Class Inclusion relation
+
+[Term]
+id: X:1
+relationship: R:1 X:2 {gci_predicate="R:2", gci_filler="X:3"}
+
+!! name: gci-is-a
+!! description: General Class Inclusion is_a
+
+[Term]
+id: X:1
+is_a: X:2 {gci_predicate="R:2", gci_filler="X:3"}
+
!! name: created_by-annotated
!! description: Metadata for creator with annotation
diff --git a/tests/input/obo-compliance/expansion-conflict-main-idspace/expansion-conflict-main-idspace.meta.yaml b/tests/input/obo-compliance/expansion-conflict-main-idspace/expansion-conflict-main-idspace.meta.yaml
new file mode 100644
index 000000000..8e57bb043
--- /dev/null
+++ b/tests/input/obo-compliance/expansion-conflict-main-idspace/expansion-conflict-main-idspace.meta.yaml
@@ -0,0 +1,4 @@
+name: expansion-conflict-main-idspace
+name: expansion-conflict-main-idspace
+description: tests conflicting expansions for the main ID space
+invalid: true
\ No newline at end of file
diff --git a/tests/input/obo-compliance/expansion-conflict-main-idspace/expansion-conflict-main-idspace.obo b/tests/input/obo-compliance/expansion-conflict-main-idspace/expansion-conflict-main-idspace.obo
new file mode 100644
index 000000000..1d96a591a
--- /dev/null
+++ b/tests/input/obo-compliance/expansion-conflict-main-idspace/expansion-conflict-main-idspace.obo
@@ -0,0 +1,10 @@
+format-version: 1.4
+ontology: expansion-conflict-main-idspace
+idspace: X http://example.org/X/
+idspace: X http://example.org/FAKEX/
+
+[Term]
+id: X:1
+name: X:1
+
+
diff --git a/tests/input/obo-compliance/gci-is-a/gci-is-a.expected.json b/tests/input/obo-compliance/gci-is-a/gci-is-a.expected.json
new file mode 100644
index 000000000..3acf8d565
--- /dev/null
+++ b/tests/input/obo-compliance/gci-is-a/gci-is-a.expected.json
@@ -0,0 +1,31 @@
+{
+ "graphs" : [ {
+ "id" : "http://purl.obolibrary.org/obo/gci-is-a.owl",
+ "meta" : {
+ "basicPropertyValues" : [ {
+ "pred" : "http://www.geneontology.org/formats/oboInOwl#hasOBOFormatVersion",
+ "val" : "1.4"
+ } ]
+ },
+ "nodes" : [ {
+ "id" : "http://www.geneontology.org/formats/oboInOwl#hasOBOFormatVersion",
+ "lbl" : "has_obo_format_version",
+ "type" : "PROPERTY"
+ }, {
+ "id" : "http://www.geneontology.org/formats/oboInOwl#id",
+ "lbl" : "id",
+ "type" : "PROPERTY"
+ } ],
+ "edges" : [ {
+ "sub" : "http://purl.obolibrary.org/obo/X_1",
+ "pred" : "is_a",
+ "obj" : "http://purl.obolibrary.org/obo/X_2",
+ "meta" : {
+ "basicPropertyValues" : [ {
+ "pred" : "http://www.geneontology.org/formats/oboInOwl#gci_predicate",
+ "val" : "R:2"
+ } ]
+ }
+ } ]
+ } ]
+}
\ No newline at end of file
diff --git a/tests/input/obo-compliance/gci-is-a/gci-is-a.expected.owl b/tests/input/obo-compliance/gci-is-a/gci-is-a.expected.owl
new file mode 100644
index 000000000..2c52ec4b4
--- /dev/null
+++ b/tests/input/obo-compliance/gci-is-a/gci-is-a.expected.owl
@@ -0,0 +1,83 @@
+
+
+
+ 1.4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ has_obo_format_version
+
+
+
+
+
+
+
+ id
+
+
+
+
+
+
+
+
+
+
+
+
+
+ X:1
+
+
+
+
+
+ R:2
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/input/obo-compliance/gci-is-a/gci-is-a.meta.yaml b/tests/input/obo-compliance/gci-is-a/gci-is-a.meta.yaml
new file mode 100644
index 000000000..d896fb72f
--- /dev/null
+++ b/tests/input/obo-compliance/gci-is-a/gci-is-a.meta.yaml
@@ -0,0 +1,3 @@
+name: gci-is-a
+name: gci-is-a
+description: General Class Inclusion is_a
\ No newline at end of file
diff --git a/tests/input/obo-compliance/gci-is-a/gci-is-a.obo b/tests/input/obo-compliance/gci-is-a/gci-is-a.obo
new file mode 100644
index 000000000..37ac76264
--- /dev/null
+++ b/tests/input/obo-compliance/gci-is-a/gci-is-a.obo
@@ -0,0 +1,7 @@
+format-version: 1.4
+ontology: gci-is-a
+
+[Term]
+id: X:1
+is_a: X:2 {gci_predicate="R:2", gci_filler="X:3"}
+
diff --git a/tests/input/obo-compliance/gci-relation/gci-relation.expected.json b/tests/input/obo-compliance/gci-relation/gci-relation.expected.json
new file mode 100644
index 000000000..091f684f0
--- /dev/null
+++ b/tests/input/obo-compliance/gci-relation/gci-relation.expected.json
@@ -0,0 +1,31 @@
+{
+ "graphs" : [ {
+ "id" : "http://purl.obolibrary.org/obo/gci-relation.owl",
+ "meta" : {
+ "basicPropertyValues" : [ {
+ "pred" : "http://www.geneontology.org/formats/oboInOwl#hasOBOFormatVersion",
+ "val" : "1.4"
+ } ]
+ },
+ "nodes" : [ {
+ "id" : "http://www.geneontology.org/formats/oboInOwl#hasOBOFormatVersion",
+ "lbl" : "has_obo_format_version",
+ "type" : "PROPERTY"
+ }, {
+ "id" : "http://www.geneontology.org/formats/oboInOwl#id",
+ "lbl" : "id",
+ "type" : "PROPERTY"
+ } ],
+ "edges" : [ {
+ "sub" : "http://purl.obolibrary.org/obo/X_1",
+ "pred" : "http://purl.obolibrary.org/obo/R_1",
+ "obj" : "http://purl.obolibrary.org/obo/X_2",
+ "meta" : {
+ "basicPropertyValues" : [ {
+ "pred" : "http://www.geneontology.org/formats/oboInOwl#gci_predicate",
+ "val" : "R:2"
+ } ]
+ }
+ } ]
+ } ]
+}
\ No newline at end of file
diff --git a/tests/input/obo-compliance/gci-relation/gci-relation.expected.owl b/tests/input/obo-compliance/gci-relation/gci-relation.expected.owl
new file mode 100644
index 000000000..826fe43d4
--- /dev/null
+++ b/tests/input/obo-compliance/gci-relation/gci-relation.expected.owl
@@ -0,0 +1,104 @@
+
+
+
+ 1.4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ has_obo_format_version
+
+
+
+
+
+
+
+ id
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ X:1
+
+
+
+
+
+
+
+
+
+ R:2
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/input/obo-compliance/gci-relation/gci-relation.meta.yaml b/tests/input/obo-compliance/gci-relation/gci-relation.meta.yaml
new file mode 100644
index 000000000..eceb19845
--- /dev/null
+++ b/tests/input/obo-compliance/gci-relation/gci-relation.meta.yaml
@@ -0,0 +1,3 @@
+name: gci-relation
+name: gci-relation
+description: General Class Inclusion relation
\ No newline at end of file
diff --git a/tests/input/obo-compliance/gci-relation/gci-relation.obo b/tests/input/obo-compliance/gci-relation/gci-relation.obo
new file mode 100644
index 000000000..89d296e94
--- /dev/null
+++ b/tests/input/obo-compliance/gci-relation/gci-relation.obo
@@ -0,0 +1,7 @@
+format-version: 1.4
+ontology: gci-relation
+
+[Term]
+id: X:1
+relationship: R:1 X:2 {gci_predicate="R:2", gci_filler="X:3"}
+
diff --git a/tests/input/obo-compliance/prefixes-conflict-main-idspace/prefixes-conflict-main-idspace.meta.yaml b/tests/input/obo-compliance/prefixes-conflict-main-idspace/prefixes-conflict-main-idspace.meta.yaml
new file mode 100644
index 000000000..bb65f539e
--- /dev/null
+++ b/tests/input/obo-compliance/prefixes-conflict-main-idspace/prefixes-conflict-main-idspace.meta.yaml
@@ -0,0 +1,4 @@
+name: prefixes-conflict-main-idspace
+name: prefixes-conflict-main-idspace
+description: tests conflicting prefixes for the main ID space
+invalid: true
\ No newline at end of file
diff --git a/tests/input/obo-compliance/prefixes-conflict-main-idspace/prefixes-conflict-main-idspace.obo b/tests/input/obo-compliance/prefixes-conflict-main-idspace/prefixes-conflict-main-idspace.obo
new file mode 100644
index 000000000..e6e80a0ba
--- /dev/null
+++ b/tests/input/obo-compliance/prefixes-conflict-main-idspace/prefixes-conflict-main-idspace.obo
@@ -0,0 +1,9 @@
+format-version: 1.4
+ontology: prefixes-conflict-main-idspace
+idspace: X http://example.org/X/
+idspace: FAKEX http://example.org/X/
+
+[Term]
+id: X:1
+name: X:1
+
diff --git a/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.expected.json b/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.expected.json
new file mode 100644
index 000000000..d8b4987c2
--- /dev/null
+++ b/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.expected.json
@@ -0,0 +1,33 @@
+{
+ "graphs" : [ {
+ "id" : "http://purl.obolibrary.org/obo/prefixes-conflict-oio.owl",
+ "meta" : {
+ "basicPropertyValues" : [ {
+ "pred" : "http://www.geneontology.org/formats/oboInOwl#hasOBOFormatVersion",
+ "val" : "1.4"
+ } ]
+ },
+ "nodes" : [ {
+ "id" : "http://purl.obolibrary.org/obo/IAO_0000115",
+ "lbl" : "definition",
+ "type" : "PROPERTY"
+ }, {
+ "id" : "http://purl.obolibrary.org/obo/X_1",
+ "lbl" : "X:1",
+ "type" : "CLASS",
+ "meta" : {
+ "definition" : {
+ "val" : "."
+ }
+ }
+ }, {
+ "id" : "http://www.geneontology.org/formats/oboInOwl#hasOBOFormatVersion",
+ "lbl" : "has_obo_format_version",
+ "type" : "PROPERTY"
+ }, {
+ "id" : "http://www.geneontology.org/formats/oboInOwl#id",
+ "lbl" : "id",
+ "type" : "PROPERTY"
+ } ]
+ } ]
+}
\ No newline at end of file
diff --git a/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.expected.owl b/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.expected.owl
new file mode 100644
index 000000000..4cd6d71c9
--- /dev/null
+++ b/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.expected.owl
@@ -0,0 +1,81 @@
+
+
+
+ 1.4
+
+
+
+
+
+
+
+
+
+
+
+
+ definition
+
+
+
+
+
+
+
+ has_obo_format_version
+
+
+
+
+
+
+
+ id
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .
+ X:1
+ X:1
+
+
+
+
+
+
+
diff --git a/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.meta.yaml b/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.meta.yaml
new file mode 100644
index 000000000..07c2775ad
--- /dev/null
+++ b/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.meta.yaml
@@ -0,0 +1,4 @@
+name: prefixes-conflict-oio
+name: prefixes-conflict-oio
+description: tests conflicting prefixes/contractions for oboInOwl namespace, where oio might be built-in
+unstable: true
\ No newline at end of file
diff --git a/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.obo b/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.obo
new file mode 100644
index 000000000..ef80fa07b
--- /dev/null
+++ b/tests/input/obo-compliance/prefixes-conflict-oio/prefixes-conflict-oio.obo
@@ -0,0 +1,9 @@
+format-version: 1.4
+ontology: prefixes-conflict-oio
+idspace: oboInOwl http://www.geneontology.org/formats/oboInOwl#
+
+[Term]
+id: X:1
+name: X:1
+def: "." []
+
diff --git a/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.expected.json b/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.expected.json
new file mode 100644
index 000000000..c2e92992c
--- /dev/null
+++ b/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.expected.json
@@ -0,0 +1,38 @@
+{
+ "graphs" : [ {
+ "id" : "http://purl.obolibrary.org/obo/prefixes-conflict-skos.owl",
+ "meta" : {
+ "basicPropertyValues" : [ {
+ "pred" : "http://www.geneontology.org/formats/oboInOwl#hasOBOFormatVersion",
+ "val" : "1.4"
+ } ]
+ },
+ "nodes" : [ {
+ "id" : "http://example.org/not-skos/exactMatch",
+ "type" : "PROPERTY",
+ "meta" : {
+ "basicPropertyValues" : [ {
+ "pred" : "http://www.geneontology.org/formats/oboInOwl#is_metadata_tag",
+ "val" : "true"
+ } ]
+ }
+ }, {
+ "id" : "http://purl.obolibrary.org/obo/X_1",
+ "type" : "CLASS",
+ "meta" : {
+ "basicPropertyValues" : [ {
+ "pred" : "http://example.org/not-skos/exactMatch",
+ "val" : "http://purl.obolibrary.org/obo/Y_1"
+ } ]
+ }
+ }, {
+ "id" : "http://www.geneontology.org/formats/oboInOwl#hasOBOFormatVersion",
+ "lbl" : "has_obo_format_version",
+ "type" : "PROPERTY"
+ }, {
+ "id" : "http://www.geneontology.org/formats/oboInOwl#id",
+ "lbl" : "id",
+ "type" : "PROPERTY"
+ } ]
+ } ]
+}
\ No newline at end of file
diff --git a/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.expected.owl b/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.expected.owl
new file mode 100644
index 000000000..389b2d20a
--- /dev/null
+++ b/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.expected.owl
@@ -0,0 +1,81 @@
+
+
+
+ 1.4
+
+
+
+
+
+
+
+
+
+
+
+
+ skos:exactMatch
+ true
+
+
+
+
+
+
+
+ has_obo_format_version
+
+
+
+
+
+
+
+ id
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ X:1
+
+
+
+
+
+
+
diff --git a/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.meta.yaml b/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.meta.yaml
new file mode 100644
index 000000000..f7fc31b2a
--- /dev/null
+++ b/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.meta.yaml
@@ -0,0 +1,4 @@
+name: prefixes-conflict-skos
+name: prefixes-conflict-skos
+description: tests conflicting prefixes for the SKOS namespace
+unstable: true
\ No newline at end of file
diff --git a/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.obo b/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.obo
new file mode 100644
index 000000000..829a2173f
--- /dev/null
+++ b/tests/input/obo-compliance/prefixes-conflict-skos/prefixes-conflict-skos.obo
@@ -0,0 +1,12 @@
+format-version: 1.4
+ontology: prefixes-conflict-skos
+idspace: skos http://example.org/not-skos/
+
+[Term]
+id: X:1
+property_value: skos:exactMatch Y:1
+
+[Typedef]
+id: skos:exactMatch
+is_metadata_tag: true
+
diff --git a/tests/input/obo-compliance/prefixes-created_by/prefixes-created_by.obo b/tests/input/obo-compliance/prefixes-created_by/prefixes-created_by.obo
index d74ef1fbb..e58492d16 100644
--- a/tests/input/obo-compliance/prefixes-created_by/prefixes-created_by.obo
+++ b/tests/input/obo-compliance/prefixes-created_by/prefixes-created_by.obo
@@ -6,4 +6,3 @@ idspace: Y http://example.org/Y/
id: X:1
created_by: Y:1
-
diff --git a/tests/test_converters/test_obo_format.py b/tests/test_converters/test_obo_format.py
index 33a28df33..1b937aac3 100644
--- a/tests/test_converters/test_obo_format.py
+++ b/tests/test_converters/test_obo_format.py
@@ -8,13 +8,77 @@
Note: some of these tests may migrate from OAK to a more central location.
-Currently these tests do two things:
+Currently the tests in this suite do two things:
-1. Compile a compliance suite by converting from a source .obo file
+1. Compile a compliance suite by converting from a source .obo file (COMPILED_OBO_FILE)
- writes to tests/input/obo-compliance
- these may eventually be moved to a separate repo
2. Test that conversion to and from .obo matches these files
- generates files in tests/output/obo-compliance
+
+Step 1: Generate the compliance suite
+--------------------------------------
+
+Step 1 is intended to be run relatively infrequently. It generates the source-of-truth "expected" files.
+Note there is some bootstrapping here. We trust a certain version of robot/obographs/owlapi to generate the
+canonical files. For the first iteration these should be manually inspected to see if they align to the spec.
+Once we are happy with these, in general they should not change again.
+
+The source file COMPILED_OBO_FILE looks like this:
+
+.. code-block:: obo
+
+ !! name: name
+ !! description: rdfs:label
+
+ [Term]
+ id: X:1
+ name: x1
+
+ !! name: invalid-name-duplicate
+ !! description: max 1 name
+ !! invalid: true
+
+ [Term]
+ id: X:1
+ name: x1
+ name: x2
+
+ !! name: namespace
+ !! description: oio:namespace
+
+ [Term]
+ id: X:1
+ namespace: NS1
+
+ !! name: xref
+ !! description: rdfs:label
+
+This is designed for easy editing. New tests can be added by providing !! separators
+and name/description metadata.
+
+If new tests are added, test_generate_canonical_files in unskip mode. This will generate the directories in
+tests/input/obo-compliance
+
+E.g.
+
+.. code-block:: bash
+
+ alt_id/
+ alt_id.obo
+ alt_id.meta.yaml
+
+Next, robot will be run from the command line to generate the expected files:
+
+- alt_id.expected.json
+- alt_id.expected.obo
+- alt_id.expected.ofn
+- alt_id.expected.owl
+
+Step 2: Checking current behavior against the compliance suite
+--------------------------------------------------------------
+
+
"""
import difflib
@@ -24,7 +88,7 @@
import subprocess
from functools import lru_cache
from pathlib import Path
-from typing import Optional
+from typing import Optional, Union, Tuple
import pytest
import rdflib
@@ -202,15 +266,18 @@ def test_generate_canonical_files(split_compiled_obo, output_format):
make_filename(ontology_id, "expected", output_format, parent=OBO_COMPLIANCE_DIR)
)
if canonical_path.exists():
- logger.info(f"(skipping) Comparing {output_path} to {canonical_path}")
- # compare_output(path, ontology_id, "robot", output_format)
+ print(f"Comparing {output_path} to {canonical_path}")
+ compare_output(output_path, canonical_path, output_format, strict=True)
else:
canonical_path.parent.mkdir(exist_ok=True, parents=True)
# copy the output to the input dir
# logger.info(f"Copying {output_path} to {canonical_path}")
shutil.copy(output_path, canonical_path)
+ shutil.copy(mk_version_path(output_path), mk_version_path(canonical_path))
else:
assert ok is None
+ print(f"DID NOT CONVERT {path} to {output_path}")
+ assert False
@pytest.mark.parametrize(
@@ -226,6 +293,9 @@ def test_oak_loaders_dumpers(split_compiled_obo, output_format, wrapper):
"""
Tests that conversion via OAK generates files that are compliant.
+ This tests the conversion from .obo format (these are generated in advance from source, see
+ docs above) into other formats using OAK.
+
:param split_compiled_obo:
:param output_format:
:param wrapper:
@@ -255,23 +325,29 @@ def test_oak_loaders_dumpers(split_compiled_obo, output_format, wrapper):
# non-canonical forms are not expected to be identical
continue
canonical = canonical_path(ontology_id, output_format)
- _, _, fatal = compare_output(
- output_path, canonical, output_format, metadata=metadata[ontology_id]
+ compare_output(
+ output_path, canonical, output_format, metadata=metadata[ontology_id], strict=False
)
- if output_format == "obo":
- assert not fatal
def compare_output(
- generated_path: str, canonical_path: str, format: str = None, metadata: dict = None
-):
+ generated_path: str, canonical_path: str, format: str = None, metadata: dict = None, strict=False,
+) -> Tuple[int, list, bool]:
"""
Compare the output of OAK loading and dumping vs canonical files.
+ In all cases difflib is used over ascii representations
+
+ - for obo files, the diff is a simple ascii diff (this sensitive to line ordering)
+ - for json files, the files are reserialized to canonicalize the order of keys
+ - for owl files, the files are reserialized using rdflib
+
+ The constant KNOWN_ISSUES holds the list of test names that are known to be problematic.
+
:param generated_path:
:param canonical_path:
:param format:
- :return:
+ :return: Tuple of [number of changes, list of diffs, fatal]
"""
fatal = False
if not metadata:
@@ -314,10 +390,12 @@ def compare_output(
expected = "EXPECTED"
else:
if name in KNOWN_ISSUES:
- expected = "TOD"
+ expected = "TODO"
else:
expected = "UNEXPECTED"
- fatal = False
+ fatal = True
+ if strict:
+ raise ValueError(f"UNEXPECTED DIFF {format}: {canonical_path} vs {generated_path}")
logger.info(f"## {name}:: {expected} DIFF {format}: {canonical_path} vs {generated_path}:")
for diff in diffs:
logger.info(diff)
@@ -394,6 +472,15 @@ def canonical_path(ontology_id: str, output_format: str) -> str:
return str(OBO_COMPLIANCE_DIR / ontology_id / f"{ontology_id}.expected.{output_format}")
+def mk_version_path(path: Union[str, Path]) -> str:
+ """
+ Make a version path for a given path.
+
+ :param path:
+ :return:
+ """
+ return f"{path}.versioninfo"
+
def robot_convert(input_path: str, output_path: str) -> Optional[bool]:
"""
Convert an ontology using robot.
@@ -403,24 +490,43 @@ def robot_convert(input_path: str, output_path: str) -> Optional[bool]:
:return:
"""
if not robot_is_on_path():
+ logger.warning(f"ROBOT NOT ON PATH")
return None
cmd = [
"robot",
"convert",
"-i",
input_path,
+ # "-t",
+ # "http://www.geneontology.org/formats/oboInOwl#id",
+ # "convert",
"-o",
output_path,
]
try:
+ print(f"Running {cmd}")
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
if result.stderr:
logging.warning(result.stderr)
logging.info(result.stdout)
- return True
except subprocess.CalledProcessError as e:
logging.info(f"Robot call failed: {e}")
return False
+ try:
+ version_meta_file = mk_version_path(output_path)
+ version_cmd = [
+ "robot",
+ "--version",
+ ]
+ with open(version_meta_file, "w") as outfile:
+ result = subprocess.run(version_cmd, check=True, stdout=outfile, text=True)
+ if result.stderr:
+ logging.warning(result.stderr)
+ logging.info(result.stdout)
+ return True
+ except subprocess.CalledProcessError as e:
+ logging.info(f"Robot --version call failed: {e}")
+ return False
def ogger_convert(input_path: str, output_path: str) -> Optional[bool]:
diff --git a/tests/test_implementations/test_pronto.py b/tests/test_implementations/test_pronto.py
index 3c5610fce..d9625b807 100644
--- a/tests/test_implementations/test_pronto.py
+++ b/tests/test_implementations/test_pronto.py
@@ -86,6 +86,22 @@ def test_custom_prefixes(self):
if iri is not None:
self.assertEqual(oi.uri_to_curie(iri), curie, f"in contract iri: {iri}")
+ def test_conflicting_oio_prefixes(self):
+ """
+ See https://github.com/INCATools/ontology-access-kit/issues/702
+ """
+ resource = OntologyResource(slug="metadata-map-prefixes-test.obo", directory=INPUT_DIR, local=True)
+ adapter = ProntoImplementation(resource)
+ m = adapter.entity_metadata_map("HP:0000001")
+ self.assertIsNotNone(m)
+ uri = "http://www.geneontology.org/formats/oboInOwl#foo"
+ curie = adapter.uri_to_curie(uri)
+ # behavior is currently intentionally undefined
+ assert (curie == "oio:foo" or curie == "oboInOwl:foo")
+ # must be reversible
+ assert adapter.curie_to_uri(curie) == uri
+
+
def test_relationship_map(self):
oi = self.oi
rels = oi.outgoing_relationship_map("GO:0005773")
diff --git a/tests/test_implementations/test_simple_obo.py b/tests/test_implementations/test_simple_obo.py
index a1eced5f7..eae4d697b 100644
--- a/tests/test_implementations/test_simple_obo.py
+++ b/tests/test_implementations/test_simple_obo.py
@@ -103,6 +103,22 @@ def test_custom_prefixes(self):
if iri is not None:
self.assertEqual(oi.uri_to_curie(iri), curie, f"in contract iri: {iri}")
+ def test_conflicting_oio_prefixes(self):
+ """
+ See https://github.com/INCATools/ontology-access-kit/issues/702
+ """
+ # TODO: DRY. This is currently duplicative of a pronto test
+ resource = OntologyResource(slug="metadata-map-prefixes-test.obo", directory=INPUT_DIR, local=True)
+ adapter = SimpleOboImplementation(resource)
+ m = adapter.entity_metadata_map("HP:0000001")
+ self.assertIsNotNone(m)
+ uri = "http://www.geneontology.org/formats/oboInOwl#foo"
+ curie = adapter.uri_to_curie(uri)
+ # behavior is currently intentionally undefined
+ assert (curie == "oio:foo" or curie == "oboInOwl:foo")
+ # must be reversible
+ assert adapter.curie_to_uri(curie) == uri
+
def test_relationships_extra(self):
oi = self.oi
rels = oi.outgoing_relationship_map("GO:0005773")