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

feat(schemaview): add is_simple_dict method #351

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
41 changes: 41 additions & 0 deletions linkml_runtime/utils/schemaview.py
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,47 @@
induced_slot = self.induced_slot(slot_name)
return True if induced_slot.multivalued else False

@lru_cache(None)
def is_simple_dict(self, slot_name: SlotDefinition) -> bool:
"""
returns True if slot is a simple dictionary, else returns False
:param slot_name: slot to test for simple dictionary
:return boolean:
"""
islot = self.induced_slot(slot_name)

Check warning on line 1030 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1030

Added line #L1030 was not covered by tests
if not islot.multivalued or not islot.inlined or islot.inlined_as_list:
return False
range_class = islot.range

Check warning on line 1033 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1032-L1033

Added lines #L1032 - L1033 were not covered by tests
if range_class is None:
return False
range_class_id_slot = self.get_identifier_slot(range_class.name, use_key=True)

Check warning on line 1036 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1035-L1036

Added lines #L1035 - L1036 were not covered by tests
if range_class_id_slot is None:
return False

Check warning on line 1038 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1038

Added line #L1038 was not covered by tests

non_id_slots = [s for s in self.class_induced_slots(range_class.name) if s.name != range_class_id_slot.name]
if len(non_id_slots) == 1:
return True

Check warning on line 1042 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1042

Added line #L1042 was not covered by tests
elif len(non_id_slots) > 1:
candidate_non_id_slots = []

Check warning on line 1044 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1044

Added line #L1044 was not covered by tests
for non_id_slot in non_id_slots:
if isinstance(non_id_slot.annotations, dict):
is_simple_dict_value = non_id_slot.annotations.get("simple_dict_value", False)

Check warning on line 1047 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1047

Added line #L1047 was not covered by tests
else:
is_simple_dict_value = getattr(non_id_slot.annotations, "simple_dict_value", False)

Check warning on line 1049 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1049

Added line #L1049 was not covered by tests
if is_simple_dict_value:
candidate_non_id_slots.append(non_id_slot)

Check warning on line 1051 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1051

Added line #L1051 was not covered by tests
if len(candidate_non_id_slots) == 1:
return True

Check warning on line 1053 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1053

Added line #L1053 was not covered by tests
else:
candidate_non_id_slots = []

Check warning on line 1055 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1055

Added line #L1055 was not covered by tests
for non_id_slot in non_id_slots:
if non_id_slot.required:
candidate_non_id_slots.append(non_id_slot)

Check warning on line 1058 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1058

Added line #L1058 was not covered by tests
if len(candidate_non_id_slots) == 1:
return True

Check warning on line 1060 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1060

Added line #L1060 was not covered by tests

return False

Check warning on line 1062 in linkml_runtime/utils/schemaview.py

View check run for this annotation

Codecov / codecov/patch

linkml_runtime/utils/schemaview.py#L1062

Added line #L1062 was not covered by tests

@lru_cache(None)
def slot_is_true_for_metadata_property(self, slot_name: SlotDefinition, metadata_property: str) -> bool:
"""
Expand Down
4 changes: 4 additions & 0 deletions tests/test_utils/input/schemaview_is_inlined.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ slots:

an_integer:
range: integer

inlined_simple_dict:
range: ThingWithId
inlined_as_list: false

# Pathological cases
inlined_integer:
Expand Down
21 changes: 21 additions & 0 deletions tests/test_utils/test_schemaview.py
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,7 @@ def test_is_inlined():
("inlined_thing_without_id", True),
("inlined_as_list_thing_without_id", True),
("an_integer", False),
("inlined_simple_dict", True),
("inlined_integer", False),
("inlined_as_list_integer", False)
]
Expand All @@ -873,6 +874,26 @@ def test_is_inlined():
assert sv.is_inlined(slot) == expected_result


def test_is_simple_dict():
schema_path = os.path.join(INPUT_DIR, "schemaview_is_inlined.yaml")
sv = SchemaView(schema_path)
cases = [
("a_thing_with_id", False),
("inlined_thing_with_id", False),
("inlined_as_list_thing_with_id", False),
("a_thing_without_id", False),
("inlined_thing_without_id", False),
("inlined_as_list_thing_without_id", False),
("an_integer", False),
("inlined_simple_dict", True),
("inlined_integer", False),
("inlined_as_list_integer", False)
]
for slot_name, expected_result in cases:
slot = sv.get_slot(slot_name)
assert sv.is_simple_dict(slot) == expected_result


def test_materialize_nonscalar_slot_usage():
schema_path = os.path.join(INPUT_DIR, "DJ_controller_schema.yaml")
sv = SchemaView(schema_path)
Expand Down
Loading