Skip to content

Commit 075ce76

Browse files
committed
Add functions to look up a LinkML python class by URI or CURIE
1 parent b669108 commit 075ce76

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

linkml_runtime/utils/yamlutils.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from deprecated.classic import deprecated
77
from jsonasobj2 import JsonObj, as_json, as_dict, JsonObjTypes, items
88
import jsonasobj2
9-
from rdflib import Graph
9+
from rdflib import Graph, URIRef
1010
from yaml.constructor import ConstructorError
1111

1212
from linkml_runtime.utils.context_utils import CONTEXTS_PARAM_TYPE, merge_contexts
@@ -243,6 +243,26 @@ def _normalize_inlined_slot(self, slot_name: str, slot_type: Type, key_name: Opt
243243
self[slot_name] = dict_slot[0]
244244
self._normalize_inlined_as_dict(slot_name, slot_type, key_name, keyed)
245245

246+
@classmethod
247+
def _class_for(cls, attribute: str, uri_or_curie: Union[str, URIRef]) -> Optional[Type["YAMLRoot"]]:
248+
""" Locate self or descendant class that has attribute == uri_or_curie """
249+
if getattr(cls, attribute, None) == uri_or_curie:
250+
return cls
251+
for subclass in cls.__subclasses__():
252+
match = subclass._class_for(attribute, uri_or_curie)
253+
if match:
254+
return match
255+
return None
256+
257+
def _class_for_uri(self, uri: str, use_model_uri: bool = False) -> Optional["YAMLRoot"]:
258+
"""
259+
Return the self or descendant of self having with a matching class uri
260+
"""
261+
return self.__class__._class_for('class_model_uri' if use_model_uri else 'class_class_uri', URIRef(uri))
262+
263+
def _class_for_curie(self, curie: str) -> Optional["YAMLRoot"]:
264+
return self.__class__._class_for('class_class_curie', curie)
265+
246266
# ==================
247267
# Error intercepts
248268
# ==================
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import unittest
2+
from linkml_runtime.linkml_model.meta import Element, LINKML
3+
4+
class PolyDataclassTestCase(unittest.TestCase):
5+
def test_class_for_uri(self):
6+
""" Test various class lookup options """
7+
e = Element(name="Test")
8+
9+
# Test class URI
10+
cls = e._class_for_uri(LINKML.ClassDefinition)
11+
self.assertEqual('ClassDefinition', cls.__name__)
12+
13+
# Test model URI
14+
cls = e._class_for_uri(LINKML.TypeDefinition, use_model_uri=True)
15+
self.assertEqual('TypeDefinition', cls.__name__)
16+
17+
# Test class curie (note there isn't any model curie
18+
cls = e._class_for_curie("linkml:TypeDefinition")
19+
self.assertEqual('TypeDefinition', cls.__name__)
20+
21+
# Make sure the self test works
22+
cls = e._class_for_uri(LINKML.Element)
23+
self.assertEqual('Element', cls.__name__)
24+
25+
# Make sure we fail gracefully
26+
cls = e._class_for_uri("linkml:Missing")
27+
self.assertIsNone(cls)
28+
29+
30+
if __name__ == '__main__':
31+
unittest.main()

0 commit comments

Comments
 (0)