Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow controling ontology IRI when saving #700

Merged
merged 7 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 33 additions & 12 deletions ontopy/ontology.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,21 @@


class Ontology(owlready2.Ontology): # pylint: disable=too-many-public-methods
"""A generic class extending owlready2.Ontology."""
"""A generic class extending owlready2.Ontology.

Additional attributes:
iri: IRI of this ontology. Currently only used for serialisation
with rdflib. Defaults to None, meaning `base_iri` will be used
instead.
label_annotations: List of label annotations, i.e. annotations
that are recognised by the get_by_label() method. Defaults
to `[skos:prefLabel, rdf:label, skos:altLabel]`.
prefix: Prefix for this ontology. Defaults to None.
"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.iri = None
self.label_annotations = DEFAULT_LABEL_ANNOTATIONS[:]
self.prefix = None

Expand Down Expand Up @@ -934,10 +945,6 @@
if overwrite and filename and os.path.exists(filename):
os.remove(filename)

EMMO = rdflib.Namespace( # pylint:disable=invalid-name
"http://emmo.info/emmo#"
)

if recursive:
if squash:
raise ValueError(
Expand Down Expand Up @@ -984,14 +991,14 @@
)

if squash:
from rdflib import ( # pylint:disable=import-outside-toplevel
URIRef,
RDF,
OWL,
)

URIRef, RDF, OWL = rdflib.URIRef, rdflib.RDF, rdflib.OWL

Check warning on line 994 in ontopy/ontology.py

View check run for this annotation

Codecov / codecov/patch

ontopy/ontology.py#L994

Added line #L994 was not covered by tests
graph = self.world.as_rdflib_graph()
graph.namespace_manager.bind("emmo", EMMO)
graph.namespace_manager.bind("", rdflib.Namespace(self.base_iri))
if self.iri:
base_iri = URIRef(self.base_iri)
for s, p, o in graph.triples((base_iri, None, None)):
graph.remove((s, p, o))
graph.add((URIRef(self.iri), p, o))

Check warning on line 1001 in ontopy/ontology.py

View check run for this annotation

Codecov / codecov/patch

ontopy/ontology.py#L996-L1001

Added lines #L996 - L1001 were not covered by tests

# Remove anonymous namespace and imports
graph.remove((URIRef("http://anonymous"), RDF.type, OWL.Ontology))
Expand All @@ -1015,6 +1022,20 @@
super().save(tmpfile, format="ntriples")
graph = rdflib.Graph()
graph.parse(tmpfile, format="ntriples")
graph.namespace_manager.bind(
"", rdflib.Namespace(self.base_iri)
)
if self.iri:
base_iri = rdflib.URIRef(self.base_iri)
for (
s,
p,
o,
) in graph.triples( # pylint: disable=not-an-iterable
(base_iri, None, None)
):
graph.remove((s, p, o))
graph.add((rdflib.URIRef(self.iri), p, o))
graph.serialize(destination=filename, format=format)
finally:
os.remove(tmpfile)
Expand Down
26 changes: 26 additions & 0 deletions tests/ontopy_tests/test_iri.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import re
from pathlib import Path
jesper-friis marked this conversation as resolved.
Show resolved Hide resolved

from ontopy import get_ontology


# if True:
def test_iri():
thisdir = Path(__file__).resolve().parent
ontodir = thisdir.parent / "testonto"
outdir = thisdir.parent / "output"

onto = get_ontology(ontodir / "testonto.ttl").load()
onto.base_iri = "http://example.com/onto"
onto.iri = "http://example.com/onto/testonto"
ontofile = outdir / "testonto.ttl"
if ontofile.exists():
ontofile.unlink()
onto.save(outdir / "testonto.ttl")
jesper-friis marked this conversation as resolved.
Show resolved Hide resolved

# Load saved ontology and make sure that base_iri and iri are stored
# correctly
with open(outdir / "testonto.ttl", mode="r") as f:
ttl = f.read()
assert re.findall(r"@prefix : (\S+) \.", ttl) == [f"<{onto.base_iri}>"]
assert re.findall(r"(\S+) a owl:Ontology", ttl) == [f"<{onto.iri}>"]
1 change: 1 addition & 0 deletions tests/output/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.ttl