Skip to content

Commit

Permalink
raise an error when two classes have the same ambiguous attribute
Browse files Browse the repository at this point in the history
Closes linkml/linkml#2403

Signed-off-by: Vincent Kelleher <[email protected]>
  • Loading branch information
Vincent Kelleher committed Dec 5, 2024
1 parent ad74966 commit ad8d5ad
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 5 deletions.
4 changes: 2 additions & 2 deletions linkml_runtime/utils/schemaview.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,8 +631,8 @@ def get_slot(self, slot_name: SLOT_NAME, imports=True, attributes=True, strict=F
for c in self.all_classes(imports=imports).values():
if slot_name in c.attributes:
if slot is not None:
# slot name is ambiguous: return a stub slot
return SlotDefinition(slot_name)
raise ValueError(f'Attribute "{slot_name}" is already defined in another class, please use a '
f'slot in that case')
slot = copy(c.attributes[slot_name])
slot.from_schema = c.from_schema
slot.owner = c.name
Expand Down
27 changes: 27 additions & 0 deletions tests/test_utils/input/get_slot_with_ambiguous_attributes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
id: https://examples.org/get-slot-with-attribute#
name: get-slot-with-attribute

prefixes:
test: https://examples.org/get-slot-with-attribute#

default_prefix: test
default_range: string

classes:
ClassWithAttributes:
attributes:
randomAttribute:
description: "A random attribute for testing purposes"
range: integer
minimum_value: 0
maximum_value: 999

ImportantSecondClass:
description: "Important class to reproduce the error I got as the class loop needs to have at least a
second iteration"
attributes:
randomAttribute:
description: "Now you see the ambiguity intensifying ?"
range: integer
minimum_value: 0
maximum_value: 111
11 changes: 8 additions & 3 deletions tests/test_utils/test_schemaview.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,9 +744,6 @@ def test_ambiguous_attributes():
a2x = SlotDefinition('a2', range='BarEnum')
view.add_class(ClassDefinition('C2', attributes={a1x.name: a1x, a2x.name: a2x}))

assert view.get_slot(a1.name).range is None
assert view.get_slot(a2.name).range is None
assert view.get_slot(a3.name).range is not None
assert len(view.all_slots(attributes=True)) == 3
assert len(view.all_slots(attributes=False)) == 0
assert len(view.all_slots()) == 3
Expand All @@ -757,6 +754,14 @@ def test_ambiguous_attributes():
assert view.induced_slot(a2x.name, 'C2').range == a2x.range


def test_ambiguous_attribute_through_get_slot():
schema_path = os.path.join(INPUT_DIR, "get_slot_with_ambiguous_attributes.yaml")
sv = SchemaView(schema_path)
with pytest.raises(ValueError) as exception:
sv.get_slot("randomAttribute")
assert str(exception.value) == ('Attribute "randomAttribute" is already defined in another class, please use a '
'slot in that case')

def test_metamodel_in_schemaview():
view = package_schemaview('linkml_runtime.linkml_model.meta')
assert 'meta' in view.imports_closure()
Expand Down

0 comments on commit ad8d5ad

Please sign in to comment.