Skip to content

Commit

Permalink
Merge pull request #47 from linkml/issue-46
Browse files Browse the repository at this point in the history
issue 46
  • Loading branch information
cmungall authored May 30, 2024
2 parents 0159462 + a6a67d1 commit 2a9d694
Show file tree
Hide file tree
Showing 8 changed files with 422 additions and 352 deletions.
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

0 comments on commit 2a9d694

Please sign in to comment.