Skip to content

Commit b4aade2

Browse files
ilaifMidnighter
andcommitted
feat: allow adding relationships
Co-authored-by: Midnighter <[email protected]>
1 parent 67da967 commit b4aade2

File tree

3 files changed

+34
-13
lines changed

3 files changed

+34
-13
lines changed

src/structurizr/model/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,8 @@
2727
from .model import Model, ModelIO
2828
from .tags import Tags
2929
from .container import Container, ContainerIO
30+
31+
32+
_symbols = locals()
33+
34+
RelationshipIO.update_forward_refs(**_symbols)

src/structurizr/model/element.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,13 @@
1717

1818

1919
from abc import ABC
20-
from typing import TYPE_CHECKING, Iterator, Optional
20+
from typing import Iterable, Iterator, List, Optional
2121

2222
from pydantic import Field, HttpUrl
2323

2424
from ..mixin import ModelRefMixin
2525
from .model_item import ModelItem, ModelItemIO
26-
27-
28-
if TYPE_CHECKING:
29-
from .relationship import Relationship
26+
from .relationship import Relationship, RelationshipIO
3027

3128

3229
__all__ = ("ElementIO", "Element")
@@ -46,6 +43,7 @@ class ElementIO(ModelItemIO, ABC):
4643
name: str = Field(...)
4744
description: str = Field("")
4845
url: Optional[HttpUrl] = Field(None)
46+
relationships: Optional[List[RelationshipIO]] = Field([])
4947

5048

5149
class Element(ModelRefMixin, ModelItem, ABC):
@@ -60,28 +58,44 @@ class Element(ModelRefMixin, ModelItem, ABC):
6058
"""
6159

6260
def __init__(
63-
self, *, name: str, description: str = "", url: Optional[str] = None, **kwargs
61+
self,
62+
*,
63+
name: str,
64+
description: str = "",
65+
url: Optional[str] = None,
66+
relationships: Optional[Iterable[Relationship]] = (),
67+
**kwargs,
6468
) -> None:
6569
"""Initialize an element with an empty 'private' model reference."""
6670
super().__init__(**kwargs)
6771
self.name = name
6872
self.description = description
6973
self.url = url
74+
self.relationships = set(relationships)
7075

71-
def get_relationships(self) -> Iterator["Relationship"]:
76+
def __repr__(self):
77+
"""Return a string representation of this instance."""
78+
return f"{type(self).__name__}(id={self.id}, name={self.name})"
79+
80+
def get_relationships(self) -> Iterator[Relationship]:
7281
"""Return a Iterator over all relationships involving this element."""
7382
return (
7483
r
7584
for r in self.get_model().get_relationships()
7685
if self is r.source or self is r.destination
7786
)
7887

79-
def get_efferent_relationships(self) -> Iterator["Relationship"]:
88+
def get_efferent_relationships(self) -> Iterator[Relationship]:
8089
"""Return a Iterator over all outgoing relationships involving this element."""
8190
return (r for r in self.get_model().get_relationships() if self is r.source)
8291

83-
def get_afferent_relationships(self) -> Iterator["Relationship"]:
92+
def get_afferent_relationships(self) -> Iterator[Relationship]:
8493
"""Return a Iterator over all incoming relationships involving this element."""
8594
return (
8695
r for r in self.get_model().get_relationships() if self is r.destination
8796
)
97+
98+
def add_relationship(self, relationship: Optional[Relationship] = None, **kwargs):
99+
if relationship is None:
100+
relationship = Relationship(**kwargs)
101+
self.relationships.add(relationship)

src/structurizr/model/relationship.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@
1616
"""Provide the relationship model."""
1717

1818

19-
from typing import Optional
19+
from typing import TYPE_CHECKING, Optional
2020

2121
from pydantic import Field
2222

23-
from .element import Element
2423
from .interaction_style import InteractionStyle
2524
from .model_item import ModelItem, ModelItemIO
2625

2726

27+
if TYPE_CHECKING:
28+
from .element import Element
29+
2830
__all__ = ("Relationship", "RelationshipIO")
2931

3032

@@ -73,9 +75,9 @@ class Relationship(ModelItem):
7375
def __init__(
7476
self,
7577
*,
76-
source: Optional[Element] = None,
78+
source: Optional["Element"] = None,
7779
source_id: str = "",
78-
destination: Optional[Element] = None,
80+
destination: Optional["Element"] = None,
7981
destination_id: str = "",
8082
description: str = "",
8183
technology: str = "",

0 commit comments

Comments
 (0)