Skip to content

Commit 8ec212b

Browse files
yt-msMidnighter
authored andcommitted
feat: minor improvements to Element.add_relationship()
1 parent 57dfb8b commit 8ec212b

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

src/structurizr/model/element.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def __init__(
7272
self.name = name
7373
self.description = description
7474
self.url = url
75+
# Note: relationships should always match get_efferent_relationships() - i.e. outbound relationships only
7576
self.relationships: Iterable[Relationship] = set(relationships)
7677

7778
self.tags.add(Tags.ELEMENT)
@@ -98,10 +99,15 @@ def get_afferent_relationships(self) -> Iterator[Relationship]:
9899
r for r in self.get_model().get_relationships() if self is r.destination
99100
)
100101

101-
def add_relationship(self, relationship: Optional[Relationship] = None, **kwargs):
102+
def add_relationship(self, relationship: Optional[Relationship] = None, **kwargs) -> Relationship:
102103
if relationship is None:
103104
relationship = Relationship(**kwargs)
105+
if relationship.source is None:
106+
relationship.source = self
107+
elif relationship.source is not self:
108+
raise ValueError(f"Cannot add relationship {relationship} to element {self} that is not its source.")
104109
self.relationships.add(relationship)
110+
return relationship
105111

106112
@classmethod
107113
def hydrate_arguments(cls, element_io: ElementIO) -> dict:

tests/unit/model/test_element.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,24 @@ def test_model_reference():
5353
element = ConcreteElement(name="Element")
5454
element.set_model(model)
5555
assert element.get_model() is model
56+
57+
58+
def test_element_can_only_add_relationship_to_source():
59+
"""Make sure that nothing adds a relationship to the wrong element."""
60+
element1 = ConcreteElement(name="elt1")
61+
element2 = ConcreteElement(name="elt1")
62+
with pytest.raises(
63+
ValueError, match="Cannot add relationship .* to element .* that is not its source"
64+
):
65+
element1.add_relationship(source=element2)
66+
67+
68+
def test_element_add_relationship_can_omit_source():
69+
"""
70+
When using add_relationship with params rather than an existing instance,
71+
it should default the source.
72+
"""
73+
element1 = ConcreteElement(name="elt1")
74+
element2 = ConcreteElement(name="elt1")
75+
r = element1.add_relationship(destination=element2)
76+
assert r.source is element1

0 commit comments

Comments
 (0)