From ed6a6a608ae73b01b217dfcf97e6d869645f9010 Mon Sep 17 00:00:00 2001 From: huyenngn Date: Mon, 13 May 2024 09:52:33 +0200 Subject: [PATCH] fix: Combine include_inner_objects and display_parent_relation flags --- capellambse_context_diagrams/__init__.py | 2 - .../collectors/default.py | 18 +- capellambse_context_diagrams/context.py | 2 - docs/gen_images.py | 4 +- docs/index.md | 252 +++++++++--------- tests/test_context_diagrams.py | 62 ----- 6 files changed, 136 insertions(+), 204 deletions(-) diff --git a/capellambse_context_diagrams/__init__.py b/capellambse_context_diagrams/__init__.py index da41a9b8..63c7001f 100644 --- a/capellambse_context_diagrams/__init__.py +++ b/capellambse_context_diagrams/__init__.py @@ -74,7 +74,6 @@ def register_classes() -> None: { "display_symbols_as_boxes": True, "display_parent_relation": True, - "include_inner_objects": True, "render_styles": styling.BLUE_ACTOR_FNCS, }, ), @@ -88,7 +87,6 @@ def register_classes() -> None: DiagramType.LAB, { "display_parent_relation": True, - "include_inner_objects": True, "render_styles": styling.BLUE_ACTOR_FNCS, }, ), diff --git a/capellambse_context_diagrams/collectors/default.py b/capellambse_context_diagrams/collectors/default.py index 8c899cca..de298575 100644 --- a/capellambse_context_diagrams/collectors/default.py +++ b/capellambse_context_diagrams/collectors/default.py @@ -26,9 +26,6 @@ def collector( diagram.display_parent_relation = (params or {}).pop( "display_parent_relation", diagram.display_parent_relation ) - diagram.include_inner_objects = (params or {}).pop( - "include_inner_objects", diagram.include_inner_objects - ) data = generic.collector(diagram, no_symbol=True) ports = port_collector(diagram.target, diagram.type) centerbox = data["children"][0] @@ -39,17 +36,16 @@ def collector( ex_datas: list[generic.ExchangeData] = [] edges: common.ElementList[fa.AbstractExchange] for ex in (edges := list(chain.from_iterable(connections.values()))): + if is_hierarchical := exchanges.is_hierarchical(ex, centerbox): - if diagram.display_parent_relation: - centerbox["labels"][0][ - "layoutOptions" - ] = makers.DEFAULT_LABEL_LAYOUT_OPTIONS - if not diagram.include_inner_objects: + if not diagram.display_parent_relation: continue - if not is_hierarchical or not diagram.display_parent_relation: - elkdata = data + centerbox["labels"][0][ + "layoutOptions" + ] = makers.DEFAULT_LABEL_LAYOUT_OPTIONS + elkdata: _elkjs.ELKInputData = centerbox else: - elkdata = centerbox + elkdata = data try: ex_data = generic.ExchangeData( ex, elkdata, diagram.filters, params, is_hierarchical diff --git a/capellambse_context_diagrams/context.py b/capellambse_context_diagrams/context.py index 174c6d77..b481227c 100644 --- a/capellambse_context_diagrams/context.py +++ b/capellambse_context_diagrams/context.py @@ -255,7 +255,6 @@ def __init__( render_styles: dict[str, styling.Styler] | None = None, display_symbols_as_boxes: bool = False, display_parent_relation: bool = False, - include_inner_objects: bool = False, slim_center_box: bool = True, ) -> None: super().__init__(obj._model) @@ -267,7 +266,6 @@ def __init__( self.__filters: cabc.MutableSet[str] = self.FilterSet(self) self.display_symbols_as_boxes = display_symbols_as_boxes self.display_parent_relation = display_parent_relation - self.include_inner_objects = include_inner_objects self.slim_center_box = slim_center_box if standard_filter := STANDARD_FILTERS.get(class_): diff --git a/docs/gen_images.py b/docs/gen_images.py index c09bfe8a..bf5e7a2f 100644 --- a/docs/gen_images.py +++ b/docs/gen_images.py @@ -99,7 +99,9 @@ def generate_hierarchy_image() -> None: with mkdocs_gen_files.open(f"{str(dest / diag.name)}.svg", "w") as fd: print( diag.render( - "svg", include_inner_objects=True, transparent_background=False + "svg", + display_parent_relation=True, + transparent_background=False, ), file=fd, ) diff --git a/docs/index.md b/docs/index.md index 93ab4d46..0d357eb7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -27,131 +27,131 @@ Generate **Context Diagrams** from your model data! The data is collected by either -- [portless_collector][capellambse_context_diagrams.collectors.portless.collector] for [`ModelObject`s][capellambse.model.common.element.ModelObject] from the Operational Architecture Layer -- [with_port_collector][capellambse_context_diagrams.collectors.default.collector] for all other Architecture Layers that use ports as connectors of exchanges. +- [portless_collector][capellambse_context_diagrams.collectors.portless.collector] for [`ModelObject`s][capellambse.model.common.element.ModelObject] from the Operational Architecture Layer +- [with_port_collector][capellambse_context_diagrams.collectors.default.collector] for all other Architecture Layers that use ports as connectors of exchanges. It is served conveniently by [get_elkdata][capellambse_context_diagrams.collectors.get_elkdata]. Available via `.context_diagram` on a [`ModelObject`][capellambse.model.common.element.ModelObject] with (diagram-class): -- ??? example "[`oa.Entity`][capellambse.model.layers.oa.Entity] (OAB)" - - ``` py - import capellambse - - model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") - diag = model.by_uuid("e37510b9-3166-4f80-a919-dfaac9b696c7").context_diagram - diag.render("svgdiagram").save(pretty=True) - ``` -
- -
Context diagram of Environment Entity with type [OAB]
-
- -- ??? example "[`oa.OperationalActivity`][capellambse.model.layers.oa.OperationalActivity] (OAIB)" - - ``` py - import capellambse - - model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") - diag = model.by_uuid("8bcb11e6-443b-4b92-bec2-ff1d87a224e7").context_diagram - diag.render("svgdiagram").save(pretty=True) - ``` -
- -
Context diagram of Activity Eat with type [OAIB]
-
- -- ??? example "[`oa.OperationalCapability`][capellambse.model.layers.oa.OperationalCapability] (OCB)" - - ``` py - import capellambse - - model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") - diag = model.by_uuid("da08ddb6-92ba-4c3b-956a-017424dbfe85").context_diagram - diag.render("svgdiagram").save(pretty=True) - ``` -
- -
Context diagram of Middle OperationalCapability with type [OCB]
-
- -- ??? example "[`ctx.Mission`][capellambse.model.layers.ctx.Mission] (MCB)" - - ``` py - import capellambse - - model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") - diag = model.by_uuid("5bf3f1e3-0f5e-4fec-81d5-c113d3a1b3a6").context_diagram - diag.render("svgdiagram").save(pretty=True) - ``` -
- -
Context diagram of Mission Top secret with type [MCB]
-
- -- ??? example "[`ctx.Capability`][capellambse.model.layers.ctx.Capability] (MCB)" - - ``` py - import capellambse - - model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") - diag = model.by_uuid("9390b7d5-598a-42db-bef8-23677e45ba06").context_diagram - diag.render("svgdiagram").save(pretty=True) - ``` -
- -
Context diagram of Capability Capability with type [MCB]
-
- -- [`ctx.SystemComponent`][capellambse.model.layers.ctx.SystemComponent] (SAB) - -- ??? example "[`ctx.SystemFunction`][capellambse.model.layers.ctx.SystemFunction] (SDFB)" - - ``` py - import capellambse - - model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") - diag = model.by_uuid("a5642060-c9cc-4d49-af09-defaa3024bae").context_diagram - diag.render("svgdiagram").save(pretty=True) - ``` -
- -
Context diagram of Lost SystemFunction with type [SDFB]
-
- -- ??? example "[`la.LogicalComponent`][capellambse.model.layers.la.LogicalComponent] (LAB)" - - ``` py - import capellambse - - model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") - diag = model.by_uuid("f632888e-51bc-4c9f-8e81-73e9404de784").context_diagram - diag.render("svgdiagram").save(pretty=True) - ``` -
- -
Context diagram of Left LogicalComponent with type [LAB]
-
- -- ??? example "[`la.LogicalFunction`][capellambse.model.layers.la.LogicalFunction] (LDFB)" - - ``` py - import capellambse - - model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") - diag = model.by_uuid("957c5799-1d4a-4ac0-b5de-33a65bf1519c").context_diagram - diag.render("svgdiagram").save(pretty=True) - ``` -
- -
Context diagram of educate Wizards LogicalFunction with type [LDFB]
-
- -* [`pa.PhysicalComponent`][capellambse.model.layers.pa.PhysicalComponent] (PAB) -* [`pa.PhysicalFunction`][capellambse.model.layers.pa.PhysicalFunction] (PDFB) -* [`pa.PhysicalComponent`][capellambse.model.layers.pa.PhysicalComponent] (PAB) -* [`pa.PhysicalFunction`][capellambse.model.layers.pa.PhysicalFunction] (PDFB) +- ??? example "[`oa.Entity`][capellambse.model.layers.oa.Entity] (OAB)" + + ``` py + import capellambse + + model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") + diag = model.by_uuid("e37510b9-3166-4f80-a919-dfaac9b696c7").context_diagram + diag.render("svgdiagram").save(pretty=True) + ``` +
+ +
Context diagram of Environment Entity with type [OAB]
+
+ +- ??? example "[`oa.OperationalActivity`][capellambse.model.layers.oa.OperationalActivity] (OAIB)" + + ``` py + import capellambse + + model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") + diag = model.by_uuid("8bcb11e6-443b-4b92-bec2-ff1d87a224e7").context_diagram + diag.render("svgdiagram").save(pretty=True) + ``` +
+ +
Context diagram of Activity Eat with type [OAIB]
+
+ +- ??? example "[`oa.OperationalCapability`][capellambse.model.layers.oa.OperationalCapability] (OCB)" + + ``` py + import capellambse + + model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") + diag = model.by_uuid("da08ddb6-92ba-4c3b-956a-017424dbfe85").context_diagram + diag.render("svgdiagram").save(pretty=True) + ``` +
+ +
Context diagram of Middle OperationalCapability with type [OCB]
+
+ +- ??? example "[`ctx.Mission`][capellambse.model.layers.ctx.Mission] (MCB)" + + ``` py + import capellambse + + model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") + diag = model.by_uuid("5bf3f1e3-0f5e-4fec-81d5-c113d3a1b3a6").context_diagram + diag.render("svgdiagram").save(pretty=True) + ``` +
+ +
Context diagram of Mission Top secret with type [MCB]
+
+ +- ??? example "[`ctx.Capability`][capellambse.model.layers.ctx.Capability] (MCB)" + + ``` py + import capellambse + + model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") + diag = model.by_uuid("9390b7d5-598a-42db-bef8-23677e45ba06").context_diagram + diag.render("svgdiagram").save(pretty=True) + ``` +
+ +
Context diagram of Capability Capability with type [MCB]
+
+ +- [`ctx.SystemComponent`][capellambse.model.layers.ctx.SystemComponent] (SAB) + +- ??? example "[`ctx.SystemFunction`][capellambse.model.layers.ctx.SystemFunction] (SDFB)" + + ``` py + import capellambse + + model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") + diag = model.by_uuid("a5642060-c9cc-4d49-af09-defaa3024bae").context_diagram + diag.render("svgdiagram").save(pretty=True) + ``` +
+ +
Context diagram of Lost SystemFunction with type [SDFB]
+
+ +- ??? example "[`la.LogicalComponent`][capellambse.model.layers.la.LogicalComponent] (LAB)" + + ``` py + import capellambse + + model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") + diag = model.by_uuid("f632888e-51bc-4c9f-8e81-73e9404de784").context_diagram + diag.render("svgdiagram").save(pretty=True) + ``` +
+ +
Context diagram of Left LogicalComponent with type [LAB]
+
+ +- ??? example "[`la.LogicalFunction`][capellambse.model.layers.la.LogicalFunction] (LDFB)" + + ``` py + import capellambse + + model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") + diag = model.by_uuid("957c5799-1d4a-4ac0-b5de-33a65bf1519c").context_diagram + diag.render("svgdiagram").save(pretty=True) + ``` +
+ +
Context diagram of educate Wizards LogicalFunction with type [LDFB]
+
+ +* [`pa.PhysicalComponent`][capellambse.model.layers.pa.PhysicalComponent] (PAB) +* [`pa.PhysicalFunction`][capellambse.model.layers.pa.PhysicalFunction] (PDFB) +* [`pa.PhysicalComponent`][capellambse.model.layers.pa.PhysicalComponent] (PAB) +* [`pa.PhysicalFunction`][capellambse.model.layers.pa.PhysicalFunction] (PDFB) #### Hierarchy in diagrams @@ -166,7 +166,7 @@ Hierarchy is identified and supported: model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") obj = model.by_uuid("16b4fcc5-548d-4721-b62a-d3d5b1c1d2eb") - diagram = obj.context_diagram.render("svgdiagram", include_inner_objects=True) + diagram = obj.context_diagram.render("svgdiagram", display_parent_relation=True) diagram.save(pretty=True) ```
@@ -197,11 +197,11 @@ The data is collected by [get_elkdata_for_exchanges][capellambse_context_diagram ### Customized edge routing !!! note "Custom routing" - The routing differs from [ELK's Layered Algorithm](https://www.eclipse.org/elk/reference/algorithms/org-eclipse-elk-layered.html): The flow display is disrupted! - We configure exchanges such that they appear in between the context - participants. This decision breaks the display of data flow which is one - of the main aims of ELK's Layered algorithm. However this lets counter - flow exchanges routes lengths and bendpoints increase. +The routing differs from [ELK's Layered Algorithm](https://www.eclipse.org/elk/reference/algorithms/org-eclipse-elk-layered.html): The flow display is disrupted! +We configure exchanges such that they appear in between the context +participants. This decision breaks the display of data flow which is one +of the main aims of ELK's Layered algorithm. However this lets counter +flow exchanges routes lengths and bendpoints increase.
diff --git a/tests/test_context_diagrams.py b/tests/test_context_diagrams.py index 2b6db5e1..118a6333 100644 --- a/tests/test_context_diagrams.py +++ b/tests/test_context_diagrams.py @@ -14,9 +14,6 @@ "99a1d711-74af-4db7-af08-4dbd91c281ce", "53558f58-270e-4206-8fc7-3cf9e788fac9", } -TEST_HIERARCHY_CHILDREN_UUIDS = { - "31bc2326-5a55-45f9-9967-f1957bcd3f89", -} TEST_ACTIVITY_UUIDS = { "097bb133-abf3-4df0-ae4e-a28378537691", "5cc0ba13-badb-40b5-9d4c-e4d7b964fb36", @@ -136,65 +133,6 @@ def test_context_diagrams_symbol_sizing( assert adiag[TEST_ACTOR_SIZING_UUID].size.y >= 37 -def test_include_inner_objects_in_context_diagram( - model: capellambse.MelodyModel, -) -> None: - obj = model.by_uuid(TEST_HIERARCHY_UUID) - - adiag = obj.context_diagram.render(None, include_inner_objects=True) - obj.context_diagram.render("svgdiagram", include_inner_objects=True).save( - pretty=True - ) - - children = {obj.uuid for obj in adiag[TEST_HIERARCHY_UUID].children} - - for uuid in TEST_HIERARCHY_CHILDREN_UUIDS: - assert uuid in children - - -def test_exclude_inner_objects_in_context_diagram( - model: capellambse.MelodyModel, -) -> None: - obj = model.by_uuid(TEST_HIERARCHY_UUID) - - adiag = obj.context_diagram.render(None, include_inner_objects=False) - obj.context_diagram.render("svgdiagram", include_inner_objects=False).save( - pretty=True - ) - - children = {obj.uuid for obj in adiag[TEST_HIERARCHY_UUID].children} - - for uuid in TEST_HIERARCHY_CHILDREN_UUIDS: - assert uuid not in children - - -def test_exclude_inner_objects_and_hide_parent_relation_in_context_diagram( - model: capellambse.MelodyModel, -) -> None: - obj = model.by_uuid(TEST_HIERARCHY_UUID) - - adiag = obj.context_diagram.render( - None, - display_parent_relation=False, - include_inner_objects=False, - depth=2, - ) - obj.context_diagram.render( - "svgdiagram", - display_parent_relation=False, - include_inner_objects=False, - depth=2, - ).save(pretty=True) - - for uuid in TEST_HIERARCHY_CHILDREN_UUIDS: - with pytest.raises(KeyError): - adiag[uuid] # pylint: disable=pointless-statement - - for uuid in TEST_HIERARCHY_PARENTS_UUIDS: - with pytest.raises(KeyError): - adiag[uuid] # pylint: disable=pointless-statement - - def test_parent_relation_in_context_diagram( model: capellambse.MelodyModel, ) -> None: