diff --git a/capellambse_context_diagrams/collectors/exchanges.py b/capellambse_context_diagrams/collectors/exchanges.py index cff5941b..a3910685 100644 --- a/capellambse_context_diagrams/collectors/exchanges.py +++ b/capellambse_context_diagrams/collectors/exchanges.py @@ -110,15 +110,18 @@ def collect_context( components.append(c) incomings |= incs outgoings |= outs - return ( - { - "element": comp, - "functions": functions, - "components": components, - }, - incomings, - outgoings, - ) + + start = { + "element": comp, + "functions": functions, + "components": components, + } + if self.diagram.hide_functions: + start["functions"] = [] + incomings = {} + outgoings = {} + + return start, incomings, outgoings def make_ports_and_update_children_size( self, @@ -155,7 +158,8 @@ def make_ports_and_update_children_size( child.height = height stack_height += makers.NEIGHBOR_VMARGIN + height - data.height = stack_height + if stack_height > 0: + data.height = stack_height @abc.abstractmethod def collect(self) -> None: @@ -222,6 +226,9 @@ def get_capella_order( def make_boxes(cntxt: dict[str, t.Any]) -> _elkjs.ELKInputChild | None: comp = cntxt["element"] functions = cntxt["functions"] + if self.diagram.hide_functions: + functions = [] + components = cntxt["components"] if comp.uuid not in made_children: children = [ @@ -278,8 +285,8 @@ def make_boxes(cntxt: dict[str, t.Any]) -> _elkjs.ELKInputChild | None: if right_child := make_boxes(right_context): self.data.children.append(right_child) self.right = right_child - except AttributeError: - pass + except AttributeError as error: + logger.exception("Interface collection failed: \n%r", str(error)) def add_interface(self) -> None: ex_data = generic.ExchangeData( diff --git a/capellambse_context_diagrams/context.py b/capellambse_context_diagrams/context.py index a9786c31..a0ae4a55 100644 --- a/capellambse_context_diagrams/context.py +++ b/capellambse_context_diagrams/context.py @@ -380,9 +380,11 @@ def __init__( class_: str, obj: common.GenericElement, include_interface: bool = False, + hide_functions: bool = False, **kw, ) -> None: self.include_interface = include_interface + self.hide_functions = hide_functions super().__init__(class_, obj, **kw, display_symbols_as_boxes=True) @property @@ -390,6 +392,13 @@ def name(self) -> str: # type: ignore return f"Interface Context of {self.target.name}" def _create_diagram(self, params: dict[str, t.Any]) -> cdiagram.Diagram: + for param_name in ("include_interface", "hide_functions"): + if override := params.pop(param_name, False): + setattr(self, param_name, override) + + if self.hide_functions: + self.include_interface = True + params["elkdata"] = exchanges.get_elkdata_for_exchanges( self, exchanges.InterfaceContextCollector, params ) diff --git a/tests/test_interface_diagrams.py b/tests/test_interface_diagrams.py index 00fce9b0..986d0406 100644 --- a/tests/test_interface_diagrams.py +++ b/tests/test_interface_diagrams.py @@ -43,3 +43,21 @@ def test_interface_diagram_with_included_interface( diag = obj.context_diagram.render(None, include_interface=True) assert diag[TEST_INTERFACE_UUID] + + +def test_interface_diagram_with_hide_functions( + model: capellambse.MelodyModel, +) -> None: + obj = model.by_uuid(TEST_INTERFACE_UUID) + + diag = obj.context_diagram.render(None, hide_functions=True) + obj.context_diagram.render("svgdiagram", hide_functions=True).save( + pretty=True + ) + + for uuid in ( + "fbfb2b20-b711-4211-9b75-25e38390cdbc", # LogicalFunction + "2b30434f-a087-40f1-917b-c9d0af15be23", # FunctionalExchange + ): + with pytest.raises(KeyError): + diag[uuid] # pylint: disable=pointless-statement