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

fixes permissible_values without explicit meaning declared causes errors, #46 #47

Merged
merged 2 commits into from
May 30, 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
1 change: 1 addition & 0 deletions docs/tutorial/pizza01-toppings-model.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ classes:
slot_uri: rdfs:label
conforms_to:
name: conforms_to
range: string
annotations:
owl.fstring: AnnotationAssertion( dcterms:conformsTo {id} pizza:{V} )
slot_uri: dcterms:conformsTo
Expand Down
25 changes: 21 additions & 4 deletions linkml_owl/dumpers/owl_dumper.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
SubObjectPropertyOf, TransitiveObjectProperty, SymmetricObjectProperty, AsymmetricObjectProperty, \
ReflexiveObjectProperty, IrreflexiveObjectProperty, Annotation, ObjectMinCardinality, ObjectHasValue, \
NamedIndividual, DataSomeValuesFrom, DataHasValue, DataAllValuesFrom, AnnotationProperty, DataProperty, Datatype, \
DisjointClasses, DisjointUnion
DisjointClasses, DisjointUnion, DataPropertyAssertion

from linkml_runtime.dumpers.dumper_root import Dumper
from linkml_runtime.utils.yamlutils import YAMLRoot
Expand Down Expand Up @@ -210,10 +210,23 @@ def transform(self, element: YAMLRoot, schema: SchemaDefinition, is_element_an_o
if element is None:
return None
try:
# translate Enum
# naive method to test if an object is an enum:
# try accessing the `meaning` field. If this fails,
# an exception is thrown, and we carry on.
# (when owl_duper is refactored to not be dependent on
# python dataclasses this will no longer be necessary)
meaning = element.meaning
return self._get_IRI_str(meaning)
if is_element_an_object:
# enum is used in an object context: translate to URI
if not meaning:
enum_uri = schema.default_prefix + ":" + type(element).__name__
meaning = enum_uri + "#" + str(element).replace(" ", "+")
return self._get_IRI_str(meaning)
else:
# enum is used in a data context - stringify
return str(element)
except AttributeError:
# not an enum - carry on
pass
if not self._instance_of_linkml_class(element):
# TODO: better way of detecting atoms
Expand Down Expand Up @@ -324,6 +337,8 @@ def transform(self, element: YAMLRoot, schema: SchemaDefinition, is_element_an_o
slot_interps = self._get_slot_interpretations(slot, linkml_class_name)
logging.debug(f'OWL interpretations for {k}={slot_interps}')
is_object_ref = slot.range in self.schema.classes
if "ObjectPropertyAssertion" in slot_interps or "ObjectProperty" in slot_interps:
is_object_ref = True
# normalize input_vals to a list, then recursively transform
if isinstance(v, list):
input_vals = v
Expand Down Expand Up @@ -390,7 +405,7 @@ def transform(self, element: YAMLRoot, schema: SchemaDefinition, is_element_an_o
# eai.add_operands((0, SubClassOf.__name__, ObjectUnionOf.__name__), parents, axiom_annotations)
axiom_type = None
# TODO: make this more generic / less repetitive
axiom_types = [SubClassOf, SubObjectPropertyOf, ClassAssertion, ObjectPropertyAssertion, EquivalentClasses, InverseObjectProperties,ObjectPropertyDomain, ObjectPropertyRange, AnnotationAssertion]
axiom_types = [SubClassOf, SubObjectPropertyOf, ClassAssertion, ObjectPropertyAssertion, DataPropertyAssertion, EquivalentClasses, InverseObjectProperties,ObjectPropertyDomain, ObjectPropertyRange, AnnotationAssertion]
for candidate_axiom_type in axiom_types:
if candidate_axiom_type.__name__ in slot_interps:
axiom_type = candidate_axiom_type
Expand Down Expand Up @@ -445,6 +460,8 @@ def transform(self, element: YAMLRoot, schema: SchemaDefinition, is_element_an_o
axiom = ClassAssertion(parent, subj)
elif axiom_type == ObjectPropertyAssertion:
axiom = ObjectPropertyAssertion(slot_uri, subj, parent)
elif axiom_type == DataPropertyAssertion:
axiom = DataPropertyAssertion(slot_uri, subj, parent)
elif axiom_type == InverseObjectProperties:
axiom = InverseObjectProperties(subj, parent)
elif axiom_type == ObjectPropertyDomain:
Expand Down
340 changes: 114 additions & 226 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ python = "^3.8.1"
click = "*"
funowl = ">=0.2.3"
Jinja2 = ">=3.0.3"
linkml = ">=1.7.4"
linkml = "^1.7.10"
linkml-runtime = ">=1.7.0"

[tool.poetry.dev-dependencies]
Expand Down
42 changes: 42 additions & 0 deletions tests/inputs/enum_model.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
id: http://example.org/enum-test
name: enum-test
imports:
- linkml:types
prefixes:
linkml: https://w3id.org/linkml/
ex: http://example.org/enum-test/
BFO: http://purl.obolibrary.org/obo/BFO_

default_prefix: ex
default_curi_maps:
- semweb_context

slots:
id:
identifier: true
range: uriorcurie
job:
range: JobEnum
annotations:
owl: ObjectPropertyAssertion

job_str:
range: JobEnum
annotations:
owl: DataPropertyAssertion

classes:

Person:
slots:
- id
- job
- job_str

enums:
JobEnum:
permissible_values:
Bricklayer:
Chimney Sweep:
Welder:
meaning: ex:Welder
57 changes: 57 additions & 0 deletions tests/inputs/monsters_and_magic.expected.ofn
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,23 @@ Ontology( <https://w3id.org/cmungall/monsters-and-magic>
SubClassOf( mnm:Humanoid mnm:Creature )
Declaration( Class( mnm:Orc ) )
AnnotationAssertion( schema:description mnm:Orc "An orc is a humanoid creature from Middle-earth." )
DataPropertyAssertion( mnm:armor_class mnm:Orc "13"^^xsd:integer )
DataPropertyAssertion( mnm:strength mnm:Orc "16"^^xsd:integer )
DataPropertyAssertion( mnm:dexterity mnm:Orc "11"^^xsd:integer )
DataPropertyAssertion( mnm:constitution mnm:Orc "12"^^xsd:integer )
DataPropertyAssertion( mnm:intelligence mnm:Orc "10"^^xsd:integer )
DataPropertyAssertion( mnm:wisdom mnm:Orc "8"^^xsd:integer )
DataPropertyAssertion( mnm:charisma mnm:Orc "8"^^xsd:integer )
SubClassOf( mnm:Orc mnm:Humanoid )
Declaration( Class( mnm:Goblin ) )
AnnotationAssertion( schema:description mnm:Goblin "A goblin is a humanoid creature from Middle-earth." )
DataPropertyAssertion( mnm:armor_class mnm:Goblin "15"^^xsd:integer )
DataPropertyAssertion( mnm:strength mnm:Goblin "8"^^xsd:integer )
DataPropertyAssertion( mnm:dexterity mnm:Goblin "14"^^xsd:integer )
DataPropertyAssertion( mnm:constitution mnm:Goblin "10"^^xsd:integer )
DataPropertyAssertion( mnm:intelligence mnm:Goblin "10"^^xsd:integer )
DataPropertyAssertion( mnm:wisdom mnm:Goblin "8"^^xsd:integer )
DataPropertyAssertion( mnm:charisma mnm:Goblin "8"^^xsd:integer )
SubClassOf( mnm:Goblin mnm:Humanoid )
Declaration( Class( mnm:SerpentineCreature ) )
AnnotationAssertion( schema:description mnm:SerpentineCreature "A serpentine creature is a creature that has a snake-like body." )
Expand Down Expand Up @@ -67,24 +81,66 @@ Ontology( <https://w3id.org/cmungall/monsters-and-magic>
SubClassOf( mnm:MagicallyCreatedCreature mnm:Creature )
Declaration( Class( mnm:RugOfSmothering ) )
AnnotationAssertion( schema:description mnm:RugOfSmothering "A rug of smothering is a rug that can be used to suffocate a creature." )
DataPropertyAssertion( mnm:armor_class mnm:RugOfSmothering "13"^^xsd:integer )
DataPropertyAssertion( mnm:strength mnm:RugOfSmothering "16"^^xsd:integer )
DataPropertyAssertion( mnm:dexterity mnm:RugOfSmothering "11"^^xsd:integer )
DataPropertyAssertion( mnm:constitution mnm:RugOfSmothering "12"^^xsd:integer )
DataPropertyAssertion( mnm:intelligence mnm:RugOfSmothering "10"^^xsd:integer )
DataPropertyAssertion( mnm:wisdom mnm:RugOfSmothering "8"^^xsd:integer )
DataPropertyAssertion( mnm:charisma mnm:RugOfSmothering "8"^^xsd:integer )
SubClassOf( mnm:RugOfSmothering mnm:MagicallyCreatedCreature )
Declaration( Class( mnm:Basilisk ) )
AnnotationAssertion( schema:description mnm:Basilisk "A basilisk is a legendary serpent-like creature with the body of a snake and the head of a king cobra." )
DataPropertyAssertion( mnm:armor_class mnm:Basilisk "13"^^xsd:integer )
DataPropertyAssertion( mnm:strength mnm:Basilisk "16"^^xsd:integer )
DataPropertyAssertion( mnm:dexterity mnm:Basilisk "11"^^xsd:integer )
DataPropertyAssertion( mnm:constitution mnm:Basilisk "12"^^xsd:integer )
DataPropertyAssertion( mnm:intelligence mnm:Basilisk "10"^^xsd:integer )
DataPropertyAssertion( mnm:wisdom mnm:Basilisk "8"^^xsd:integer )
DataPropertyAssertion( mnm:charisma mnm:Basilisk "8"^^xsd:integer )
SubClassOf( mnm:Basilisk mnm:SerpentineCreature )
Declaration( Class( mnm:UndeadCreature ) )
AnnotationAssertion( schema:description mnm:UndeadCreature "An undead creature is a creature that is dead, but has been brought back to life by magic." )
SubClassOf( mnm:UndeadCreature mnm:Humanoid )
Declaration( Class( mnm:WhiteWalker ) )
AnnotationAssertion( schema:description mnm:WhiteWalker "A white walker is an undead creature from the Game of Thrones universe." )
DataPropertyAssertion( mnm:armor_class mnm:WhiteWalker "13"^^xsd:integer )
DataPropertyAssertion( mnm:strength mnm:WhiteWalker "16"^^xsd:integer )
DataPropertyAssertion( mnm:dexterity mnm:WhiteWalker "11"^^xsd:integer )
DataPropertyAssertion( mnm:constitution mnm:WhiteWalker "12"^^xsd:integer )
DataPropertyAssertion( mnm:intelligence mnm:WhiteWalker "10"^^xsd:integer )
DataPropertyAssertion( mnm:wisdom mnm:WhiteWalker "8"^^xsd:integer )
DataPropertyAssertion( mnm:charisma mnm:WhiteWalker "8"^^xsd:integer )
SubClassOf( mnm:WhiteWalker mnm:UndeadCreature )
Declaration( Class( mnm:Lich ) )
AnnotationAssertion( schema:description mnm:Lich "A lich is a fictional undead creature in the Dungeons & Dragons fantasy role-playing game." )
DataPropertyAssertion( mnm:armor_class mnm:Lich "13"^^xsd:integer )
DataPropertyAssertion( mnm:strength mnm:Lich "16"^^xsd:integer )
DataPropertyAssertion( mnm:dexterity mnm:Lich "11"^^xsd:integer )
DataPropertyAssertion( mnm:constitution mnm:Lich "12"^^xsd:integer )
DataPropertyAssertion( mnm:intelligence mnm:Lich "10"^^xsd:integer )
DataPropertyAssertion( mnm:wisdom mnm:Lich "8"^^xsd:integer )
DataPropertyAssertion( mnm:charisma mnm:Lich "8"^^xsd:integer )
SubClassOf( mnm:Lich mnm:UndeadCreature )
Declaration( Class( mnm:Vampire ) )
AnnotationAssertion( schema:description mnm:Vampire "A vampire is a fictional undead creature in the Dungeons & Dragons fantasy role-playing game." )
DataPropertyAssertion( mnm:armor_class mnm:Vampire "13"^^xsd:integer )
DataPropertyAssertion( mnm:strength mnm:Vampire "16"^^xsd:integer )
DataPropertyAssertion( mnm:dexterity mnm:Vampire "11"^^xsd:integer )
DataPropertyAssertion( mnm:constitution mnm:Vampire "12"^^xsd:integer )
DataPropertyAssertion( mnm:intelligence mnm:Vampire "10"^^xsd:integer )
DataPropertyAssertion( mnm:wisdom mnm:Vampire "8"^^xsd:integer )
DataPropertyAssertion( mnm:charisma mnm:Vampire "8"^^xsd:integer )
SubClassOf( mnm:Vampire mnm:UndeadCreature )
Declaration( Class( mnm:Zombie ) )
AnnotationAssertion( schema:description mnm:Zombie "A zombie is a fictional undead creature in the Dungeons & Dragons fantasy role-playing game." )
DataPropertyAssertion( mnm:armor_class mnm:Zombie "13"^^xsd:integer )
DataPropertyAssertion( mnm:strength mnm:Zombie "16"^^xsd:integer )
DataPropertyAssertion( mnm:dexterity mnm:Zombie "11"^^xsd:integer )
DataPropertyAssertion( mnm:constitution mnm:Zombie "12"^^xsd:integer )
DataPropertyAssertion( mnm:intelligence mnm:Zombie "10"^^xsd:integer )
DataPropertyAssertion( mnm:wisdom mnm:Zombie "8"^^xsd:integer )
DataPropertyAssertion( mnm:charisma mnm:Zombie "8"^^xsd:integer )
SubClassOf( mnm:Zombie mnm:UndeadCreature )
Declaration( NamedIndividual( mnm:Smaug ) )
Declaration( Class( mnm:Smaug ) )
Expand All @@ -98,6 +154,7 @@ Ontology( <https://w3id.org/cmungall/monsters-and-magic>
ClassAssertion( mnm:WhiteWalker mnm:TheNightKing )
Declaration( Class( mnm:Paladin ) )
AnnotationAssertion( schema:description mnm:Paladin "A paladin is a holy warrior who fights evil using divine magic." )
DataPropertyAssertion( mnm:hit_dice mnm:Paladin "D10" )
Declaration( Class( mnm:Wizard ) )
AnnotationAssertion( schema:description mnm:Wizard "A wizard is a person who practices magic." )
Declaration( Class( mnm:Rogue ) )
Expand Down
Loading
Loading