Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
12 changes: 5 additions & 7 deletions ontopy/excelparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
import ontopy
from ontopy import get_ontology
from ontopy.utils import EMMOntoPyException, NoSuchLabelError
from ontopy.utils import ReadCatalogError, read_catalog
from ontopy.utils import ReadCatalogError
from ontopy.utils import read_catalog, english
from ontopy.ontology import LabelDefinitionError
from ontopy.manchester import evaluate
import owlready2 # pylint: disable=C0411
Expand All @@ -30,11 +31,6 @@ class ExcelError(EMMOntoPyException):
"""Raised on errors in Excel file."""


def english(string):
"""Returns `string` as an English location string."""
return owlready2.locstr(string, lang="en")


def create_ontology_from_excel( # pylint: disable=too-many-arguments, too-many-locals
excelpath: str,
concept_sheet_name: str = "Concepts",
Expand Down Expand Up @@ -325,6 +321,9 @@ def create_ontology_from_pandas( # pylint:disable=too-many-locals,too-many-bran
onto.base_iri = base_iri

onto.sync_python_names()
# prefLabel, label, and altLabel
# are default label annotations
onto.set_default_label_annotations()

# Add object properties
if objectproperties is not None:
Expand Down Expand Up @@ -365,7 +364,6 @@ def create_ontology_from_pandas( # pylint:disable=too-many-locals,too-many-bran
entitytype=owlready2.DataPropertyClass,
force=force,
)

onto.sync_attributes(
name_policy="uuid", name_prefix="EMMO_", class_docstring="elucidation"
)
Expand Down
83 changes: 54 additions & 29 deletions ontopy/ontology.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# pylint: disable=too-many-lines,fixme,arguments-differ,protected-access
from typing import TYPE_CHECKING, Optional, Union
import os
import fnmatch
import itertools
import inspect
import warnings
Expand All @@ -28,6 +29,7 @@

from ontopy.factpluspluswrapper.sync_factpp import sync_reasoner_factpp
from ontopy.utils import (
english,
asstring,
read_catalog,
write_catalog,
Expand Down Expand Up @@ -266,7 +268,8 @@ def get_unabbreviated_triples(
self, subject=subject, predicate=predicate, obj=obj, blank=blank
)

def _set_label_annotations(self):
def set_default_label_annotations(self):
"""Sets the default label annotations."""
if self._label_annotations is None:
for iri in DEFAULT_LABEL_ANNOTATIONS:
try:
Expand Down Expand Up @@ -315,8 +318,6 @@ def get_by_label(
f"Invalid label definition, must be a string: {label!r}"
)

self._set_label_annotations()

if colon_in_label is None:
colon_in_label = self._colon_in_label
if colon_in_label:
Expand All @@ -332,7 +333,7 @@ def get_by_label(
warnings.warn(
f"Prefix given both as argument ({prefix}) "
f"and in label ({splitlabel[0]}). "
"Prefix given in argument takes presendence "
"Prefix given in argument takes precedence. "
)
if not prefix:
prefix = splitlabel[0]
Expand All @@ -343,12 +344,13 @@ def get_by_label(
label_annotations=label_annotations,
prefix=prefix,
)
if len(entitylist) > 0:
return entitylist[0]
if len(entitylist) == 1:
return next(iter(entitylist))

raise NoSuchLabelError(
f"No label annotations matches {label!r} with prefix "
f"{prefix!r}"
f"Either no label annotations matches for {label!r} "
f"with prefix {prefix!r} or several entities have "
"the same label and prefix."
)

# Label is a full IRI
Expand All @@ -357,19 +359,25 @@ def get_by_label(
return entity

# First entity with matching label annotation
annotation_ids = (
(self._abbreviate(ann, False) for ann in label_annotations)
if label_annotations
else (ann.storid for ann in self.label_annotations)
)

if label_annotations:
annotation_ids = (
self._abbreviate(ann, False) for ann in label_annotations
)
elif self._label_annotations:
annotation_ids = (ann.storid for ann in self._label_annotations)
else:
annotation_ids = None

get_triples = (
self.world._get_data_triples_spod_spod
if imported
else self._get_data_triples_spod_spod
)
for annotation_id in annotation_ids:
for s, _, _, _ in get_triples(None, annotation_id, label, None):
return self.world[self._unabbreviate(s)]
if annotation_ids:
for annotation_id in annotation_ids:
for s, _, _, _ in get_triples(None, annotation_id, label, None):
return self.world[self._unabbreviate(s)]

# Special labels
if self._special_labels and label in self._special_labels:
Expand Down Expand Up @@ -398,7 +406,6 @@ def get_by_label_all(self, label, label_annotations=None, prefix=None):
The current implementation also supports "*" as a wildcard
matching any number of characters. This may change in the future.
"""
self._set_label_annotations()

if not isinstance(label, str):
raise TypeError(
Expand All @@ -409,26 +416,38 @@ def get_by_label_all(self, label, label_annotations=None, prefix=None):
f"Invalid label definition, {label!r} contains spaces."
)

if label_annotations is None:
annotations = (_.name for _ in self.label_annotations)
else:
if label_annotations:
annotations = (
_.name if hasattr(_, "storid") else _ for _ in label_annotations
)
entity = self.world.search(**{next(annotations): label})
for key in annotations:
entity.extend(self.world.search(**{key: label}))
elif self._label_annotations:
annotations = (_.name for _ in self.label_annotations)

else:
annotations = None
entities = set()
if annotations:
# entity = self.world.search(**{next(annotations): label})
for key in annotations:
entities.update(self.world.search(**{key: label}))

if self._special_labels and label in self._special_labels:
entity.append(self._special_labels[label])
entities.update(self._special_labels[label])

# Find existence in get_entities
matches = fnmatch.filter(
(ent.name for ent in self.get_entities()), label
)

entity_accessed_directly = self.world[self.base_iri + label]
if entity_accessed_directly and entity_accessed_directly not in entity:
entity.append(entity_accessed_directly)
entities.update(
ent for ent in self.get_entities() if ent.name in matches
)

if prefix:
return [_ for _ in entity if _.namespace.ontology.prefix == prefix]
return entity
return set(
_ for _ in entities if _.namespace.ontology.prefix == prefix
)
return entities

def add_label_annotation(self, iri):
"""Adds label annotation used by get_by_label().
Expand Down Expand Up @@ -1717,6 +1736,12 @@ def new_entity(

with self:
entity = types.new_class(name, parents)
# Set prefLabel to name if label_annotations is set
# and prefLabel is one of the annotations
if self.label_annotations and "prefLabel" in [
ann.name for ann in self.label_annotations
]:
entity.prefLabel = english(name)
return entity

# Method that creates new ThingClass using new_entity
Expand Down
5 changes: 5 additions & 0 deletions ontopy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ class EntityClassDefinitionError(EMMOntoPyException):
"""Error in ThingClass definition."""


def english(string):
"""Returns `string` as an English location string."""
return owlready2.locstr(string, lang="en")


def isinteractive():
"""Returns true if we are running from an interactive interpreater,
false otherwise."""
Expand Down
5 changes: 3 additions & 2 deletions tests/ontopy_tests/test_new_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ def test_new_entity(testonto: "Ontology") -> None:

# Test that new entity is found by both version of get_by_label
assert testonto.get_by_label("FantasyClass") == testonto.FantasyClass
assert testonto.get_by_label_all("FantasyClass") == [testonto.FantasyClass]
print(testonto.get_by_label_all("*"))
assert testonto.get_by_label_all("FantasyClass") == {testonto.FantasyClass}

testonto.sync_attributes()
# Test that after sync_attributes, the entity is not counted more than once
assert testonto.get_by_label_all("FantasyClass") == [testonto.FantasyClass]
assert testonto.get_by_label_all("FantasyClass") == {testonto.FantasyClass}

with pytest.raises(LabelDefinitionError):
testonto.new_entity("Fantasy Class", testonto.TestClass)
Expand Down
2 changes: 1 addition & 1 deletion tests/ontopy_tests/test_prefix.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
def test_prefix(testonto: "Ontology", emmo: "Ontology") -> None:
"""Test prefix in ontology"""

assert len(testonto.get_by_label_all("*")) == 6
assert len(testonto.get_by_label_all("*")) == 7
assert set(testonto.get_by_label_all("*", prefix="testonto")) == set(
[
testonto.hasObjectProperty,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ def test_basic(emmo: "Ontology") -> None:

# Test that new entity is found by both version of get_by_label
assert onto.get_by_label("Hydrogen") == onto.Hydrogen
assert onto.get_by_label_all("Hydrogen") == [onto.Hydrogen]
assert onto.get_by_label_all("Hydrogen") == {onto.Hydrogen}

onto.sync_attributes()
# Test that after sync_attributes, the entity is not counted more than once
assert onto.get_by_label_all("Hydrogen") == [onto.Hydrogen]
assert onto.get_by_label_all("Hydrogen") == {onto.Hydrogen}

with pytest.raises(LabelDefinitionError):
onto.new_entity("Hydr ogen", emmo.Atom)
Expand Down
1 change: 1 addition & 0 deletions tests/test_excelparser/test_excelparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def test_excelparser(repo_dir: "Path") -> None:
repo_dir / "tests" / "test_excelparser" / "onto_update.xlsx"
)
ontology, catalog, errors = create_ontology_from_excel(xlspath, force=True)
ontology.save("test.ttl")
assert onto == ontology
assert errors.keys() == {
"already_defined",
Expand Down
72 changes: 72 additions & 0 deletions tests/test_get_by_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,78 @@
from ontopy.ontology import NoSuchLabelError


def test_get_by_label_onto() -> None:
"""Test that label annotations are added correctly if they are not added before
using get_by_label
"""
import owlready2

testonto = get_ontology("http://domain_ontology/new_ontology")
testonto.new_entity("Class", owlready2.Thing)
assert testonto._label_annotations == None
assert testonto.get_by_label("Class") == testonto.Class


def test_get_by_label_all_onto() -> None:
"""Test that label annotations are added correctly if they are not added before
using get_by_label_all
"""
import owlready2

testonto = get_ontology("http://domain_ontology/new_ontology")
testonto.new_entity("Class", owlready2.Thing)
assert testonto._label_annotations == None
assert testonto.get_by_label_all("*") == {testonto.Class}
testonto.new_annotation_property(
"SpecialAnnotation", owlready2.AnnotationProperty
)
testonto.Class.SpecialAnnotation.append("This is a comment")
testonto.set_default_label_annotations()

testonto.new_entity("Klasse", testonto.Class)

assert testonto.Klasse.prefLabel == ["Klasse"]

testonto.Klasse.altLabel = "Class2"
assert testonto.get_by_label_all("*") == {
testonto.prefLabel,
testonto.altLabel,
testonto.Class,
testonto.SpecialAnnotation,
testonto.Klasse,
}
assert testonto.get_by_label_all("Class*") == {
testonto.Class,
testonto.Klasse,
}


def test_get_by_label_emmo(emmo: "Ontology") -> None:
# Loading emmo-inferred where everything is sqashed into one ontology
emmo = get_ontology().load()
assert emmo[emmo.Atom.name] == emmo.Atom
assert emmo[emmo.Atom.iri] == emmo.Atom

# Load an ontology with imported sub-ontologies
onto = get_ontology(
"https://raw.githubusercontent.com/BIG-MAP/BattINFO/master/battinfo.ttl"
).load()
assert onto.Electrolyte.prefLabel.first() == "Electrolyte"

# Check colon_in_name argument
onto.Atom.altLabel.append("Element:X")
with pytest.raises(NoSuchLabelError):
onto.get_by_label("Element:X")

assert onto.get_by_label("Element:X", colon_in_label=True) == onto.Atom


import pytest

from ontopy import get_ontology
from ontopy.ontology import NoSuchLabelError


# Loading emmo-inferred where everything is sqashed into one ontology
emmo = get_ontology().load()
assert emmo[emmo.Atom.name] == emmo.Atom
Expand Down