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

Correct saving squashed ontology #719

Merged
merged 11 commits into from
Feb 29, 2024
3 changes: 3 additions & 0 deletions docs/api_reference/ontopy/testutils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# testutils

::: ontopy.testutils
33 changes: 27 additions & 6 deletions ontopy/ontology.py
Original file line number Diff line number Diff line change
Expand Up @@ -1000,21 +1000,42 @@ def save(
)
elif squash:
URIRef, RDF, OWL = rdflib.URIRef, rdflib.RDF, rdflib.OWL
iri = self.iri if self.iri else self.base_iri
graph = self.world.as_rdflib_graph()
graph.namespace_manager.bind("", rdflib.Namespace(iri))

# Make a copy of the owlready2 graph object to not mess with
# owlready2 internals
graph = rdflib.Graph()
graph_owlready2 = self.world.as_rdflib_graph()
for triple in graph_owlready2.triples((None, None, None)):
graph.add(triple)

# Add namespaces
graph.namespace_manager.bind("", rdflib.Namespace(self.base_iri))
graph.namespace_manager.bind(
"swrl", rdflib.Namespace("http://www.w3.org/2003/11/swrl#")
)

# Remove all ontology-declarations in the graph that are
# not the current ontology.
for s, _, _ in graph.triples((None, RDF.type, OWL.Ontology)):
for s, _, _ in graph.triples( # pylint: disable=not-an-iterable
(None, RDF.type, OWL.Ontology)
):
if str(s).rstrip("/#") != self.base_iri.rstrip("/#"):
for _, p, o in graph.triples((s, None, None)):
for (
_,
p,
o,
) in graph.triples( # pylint: disable=not-an-iterable
(s, None, None)
):
graph.remove((s, p, o))
graph.remove((s, OWL.imports, None))

# Insert correct IRI of the ontology
if self.iri:
base_iri = URIRef(self.base_iri)
for s, p, o in graph.triples((base_iri, None, None)):
for s, p, o in graph.triples( # pylint: disable=not-an-iterable
(base_iri, None, None)
):
graph.remove((s, p, o))
graph.add((URIRef(self.iri), p, o))

Expand Down
29 changes: 29 additions & 0 deletions ontopy/testutils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Motule primarly intended to be imported by tests.
jesper-friis marked this conversation as resolved.
Show resolved Hide resolved

It defines some directories and some utility functions that can be used
with and without conftest.
"""
import sys
from pathlib import Path
from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader


rootdir = Path(__file__).resolve().parent.parent
testdir = rootdir / "tests"
ontodir = testdir / "testonto"
outdir = testdir / "output"
toolsdir = rootdir / "tools"


def get_tool_module(name):
"""Imports and returns the module for the EMMOntoPy tool
corresponding to `name`."""
if str(toolsdir) not in sys.path:
sys.path.append(str(toolsdir))

# For Python 3.4+
spec = spec_from_loader(name, SourceFileLoader(name, str(toolsdir / name)))
module = module_from_spec(spec)
spec.loader.exec_module(module)
return module
114 changes: 0 additions & 114 deletions tests/tools/conftest.py

This file was deleted.

24 changes: 6 additions & 18 deletions tests/tools/test_emmocheck.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
"""Test the `emmocheck` tool."""
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from types import ModuleType
from typing import Callable

# if True:
def test_run() -> None:
"""Check that running `emmocheck` works."""
from ontopy.testutils import ontodir, get_tool_module

def test_run(get_tool: "Callable[[str], ModuleType]") -> None:
"""Check that running `emmocheck` works.

Parameters:
get_tool: Local module fixture to load a named tool as a module.
See the current folder's `conftest.py` file.

"""
from pathlib import Path

test_file = (
Path(__file__).resolve().parent.parent / "testonto" / "models.ttl"
)
emmocheck = get_tool("emmocheck")
test_file = ontodir / "models.ttl"
emmocheck = get_tool_module("emmocheck")

emmocheck.main([str(test_file)])
40 changes: 15 additions & 25 deletions tests/tools/test_excel2onto.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
"""Test the `ontograph` tool."""
from typing import TYPE_CHECKING

import pytest

if TYPE_CHECKING:
from pathlib import Path
from types import ModuleType
from typing import Callable


@pytest.mark.filterwarnings("ignore::UserWarning")
def test_run(get_tool: "Callable[[str], ModuleType]", tmpdir: "Path") -> None:
def test_run() -> None:
"""Check that running `excel2onto` works.

Parameters:
Expand All @@ -20,36 +13,33 @@ def test_run(get_tool: "Callable[[str], ModuleType]", tmpdir: "Path") -> None:
exist only for the lifetime of this test function.

"""
from pathlib import Path
from ontopy.testutils import ontodir, outdir, testdir, get_tool_module

test_file = (
Path(__file__).resolve().parent.parent
/ "test_excelparser"
/ "onto.xlsx"
)
test_file2 = (
Path(__file__).resolve().parent.parent
/ "test_excelparser"
/ "onto_update.xlsx"
)
excel2onto = get_tool("excel2onto")
test_file = testdir / "test_excelparser" / "onto.xlsx"
test_file2 = testdir / "test_excelparser" / "onto_update.xlsx"
excel2onto = get_tool_module("excel2onto")

excel2onto.main(
[f"--output={str(tmpdir)}/onto.ttl", "--force", str(test_file)]
)
outfile = outdir / "onto.ttl"
if outfile.exists(): # consider to add an --overwrite option to excel2onto
outfile.unlink()
excel2onto.main([f"--output={outfile}", "--force", str(test_file)])

# Append to outfile
excel2onto.main(
[
f"--output={str(tmpdir)}/onto.ttl",
f"--output={outdir}/onto.ttl",
"--force",
"--input_ontology=newonto.ttl",
str(test_file2),
]
)

outfile = outdir / "ontology.ttl"
if outfile.exists():
outfile.unlink()
excel2onto.main(
[
f"--output={str(tmpdir)}/ontology.ttl",
f"--output={outfile}",
"--force",
"--update=False",
str(test_file),
Expand Down
47 changes: 27 additions & 20 deletions tests/tools/test_ontoconvert.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
"""Test the `ontoconvert` tool."""
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from pathlib import Path
from types import ModuleType
from typing import Callable

# if True:
def test_run() -> None:
"""Check that running `ontoconvert` works."""
import re
from ontopy.testutils import ontodir, outdir, get_tool_module

def test_run(get_tool: "Callable[[str], ModuleType]", tmpdir: "Path") -> None:
"""Check that running `ontoconvert` works.
ontoconvert = get_tool_module("ontoconvert")

Parameters:
get_tool: Local module fixture to load a named tool as a module.
See the current folder's `conftest.py` file.
tmpdir: A generic pytest fixture to generate a temporary directory, which will
exist only for the lifetime of this test function.

"""
from pathlib import Path

test_file = (
Path(__file__).resolve().parent.parent / "testonto" / "models.ttl"
# Test 1
ontoconvert.main(
[str(ontodir / "models.ttl"), str(outdir / "test_ontoconvert1.ttl")]
)
ontoconvert = get_tool("ontoconvert")
output1 = (outdir / "test_ontoconvert1.ttl").read_text()
assert re.search("@prefix : <http://emmo.info/models#>", output1)
assert re.search("<http://emmo.info/models> .* owl:Ontology", output1)
assert re.search("testclass .* owl:Class", output1)

ontoconvert.main([str(test_file), str(tmpdir / "test.ttl")])
# Test 2 - squash
ontoconvert.main(
[
"-asw",
"--iri=https://w3id.org/ex/testonto",
"--base-iri=https://w3id.org/ex/testonto#",
str(ontodir / "testonto.ttl"),
str(outdir / "test_ontoconvert2.ttl"),
]
)
output2 = (outdir / "test_ontoconvert2.ttl").read_text()
assert re.search("@prefix : <https://w3id.org/ex/testonto#>", output2)
assert re.search("<https://w3id.org/ex/testonto> .* owl:Ontology", output2)
assert re.search("testclass .* owl:Class", output2)
Loading
Loading