From db4b54f16ab38a8dbcdb05003e61aa619549d111 Mon Sep 17 00:00:00 2001 From: ewuerger Date: Tue, 19 Mar 2024 11:01:02 +0100 Subject: [PATCH] feat: Add `transparent_background` and more params handling --- .pre-commit-config.yaml | 10 +++--- .../collectors/default.py | 6 ++-- .../collectors/generic.py | 1 + .../collectors/tree_view.py | 6 ++-- capellambse_context_diagrams/context.py | 17 ++++++---- capellambse_context_diagrams/filters.py | 8 +++-- capellambse_context_diagrams/serializers.py | 11 ++++-- docs/gen_images.py | 34 +++++++++++++++---- tests/test_dataflow_views.py | 22 ++++++++++++ 9 files changed, 87 insertions(+), 28 deletions(-) create mode 100644 tests/test_dataflow_views.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1d3d5abd..fb653b29 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,19 +25,19 @@ repos: - id: fix-byte-order-marker - id: trailing-whitespace - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.10.1 + rev: 24.3.0 hooks: - id: black - repo: https://github.com/PyCQA/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.6.1 + rev: v1.9.0 hooks: - id: mypy - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.5.4 + rev: v1.5.5 hooks: - id: insert-license name: Insert Licence for Python, YAML and Dockerfiles @@ -67,6 +67,6 @@ repos: - --comment-style - "/*| *| */" - repo: https://github.com/fsfe/reuse-tool - rev: v2.1.0 + rev: v3.0.1 hooks: - id: reuse diff --git a/capellambse_context_diagrams/collectors/default.py b/capellambse_context_diagrams/collectors/default.py index 738e00ad..fbe4de4b 100644 --- a/capellambse_context_diagrams/collectors/default.py +++ b/capellambse_context_diagrams/collectors/default.py @@ -98,9 +98,9 @@ def collector( global_boxes.pop(child.uuid) ) for label in parent_box["labels"]: - label[ - "layoutOptions" - ] = makers.CENTRIC_LABEL_LAYOUT_OPTIONS + label["layoutOptions"] = ( + makers.CENTRIC_LABEL_LAYOUT_OPTIONS + ) _move_edge_to_local_edges( parent_box, connections, local_ports, diagram, data diff --git a/capellambse_context_diagrams/collectors/generic.py b/capellambse_context_diagrams/collectors/generic.py index e72182d7..fe60433b 100644 --- a/capellambse_context_diagrams/collectors/generic.py +++ b/capellambse_context_diagrams/collectors/generic.py @@ -141,6 +141,7 @@ def exchange_data_collector( params = (data.params or {}).copy() # Remove simple render parameters from params no_edgelabels: bool = params.pop("no_edgelabels", False) + params.pop("transparent_background", False) render_adj: dict[str, t.Any] = {} for name, value in params.items(): diff --git a/capellambse_context_diagrams/collectors/tree_view.py b/capellambse_context_diagrams/collectors/tree_view.py index b808308b..c6da3690 100644 --- a/capellambse_context_diagrams/collectors/tree_view.py +++ b/capellambse_context_diagrams/collectors/tree_view.py @@ -132,9 +132,9 @@ def collector( data["children"][0]["labels"][0].setdefault("layoutOptions", {}).update( makers.DEFAULT_LABEL_LAYOUT_OPTIONS ) - all_associations: cabc.Iterable[ - information.Association - ] = diagram._model.search("Association") + all_associations: cabc.Iterable[information.Association] = ( + diagram._model.search("Association") + ) _set_layout_options(data, params) processor = ClassProcessor(data, all_associations) processor._set_data_types_and_labels(data["children"][0], diagram.target) diff --git a/capellambse_context_diagrams/context.py b/capellambse_context_diagrams/context.py index c57b8833..b360482e 100644 --- a/capellambse_context_diagrams/context.py +++ b/capellambse_context_diagrams/context.py @@ -48,16 +48,14 @@ def __init__( self._default_render_params = render_params or {} @t.overload - def __get__(self, obj: None, objtype: type[t.Any]) -> ContextAccessor: - ... + def __get__(self, obj: None, objtype: type[t.Any]) -> ContextAccessor: ... @t.overload def __get__( self, obj: common.T, objtype: type[common.T] | None = None, - ) -> ContextDiagram: - ... + ) -> ContextDiagram: ... def __get__( self, @@ -341,10 +339,14 @@ def render(self, fmt: str | None, /, **params) -> t.Any: return super().render(fmt, **rparams) def _create_diagram(self, params: dict[str, t.Any]) -> cdiagram.Diagram: + transparent_background = params.pop("transparent_background", False) data = params.get("elkdata") or get_elkdata(self, params) layout = try_to_layout(data) add_context(layout, params.get("is_legend", False)) - return self.serializer.make_diagram(layout) + return self.serializer.make_diagram( + layout, + transparent_background=transparent_background, + ) @property # type: ignore def filters(self) -> cabc.MutableSet[str]: # type: ignore @@ -528,7 +530,10 @@ def _create_diagram(self, params: dict[str, t.Any]) -> cdiagram.Diagram: } # type: ignore[arg-type] ) self._add_layer_labels(layout) - return self.serializer.make_diagram(layout) + return self.serializer.make_diagram( + layout, + transparent_background=params.get("transparent_background", False), + ) def _add_layer_labels(self, layout: _elkjs.ELKOutputData) -> None: for layer in layout["children"]: diff --git a/capellambse_context_diagrams/filters.py b/capellambse_context_diagrams/filters.py index ba3494b2..7de33e00 100644 --- a/capellambse_context_diagrams/filters.py +++ b/capellambse_context_diagrams/filters.py @@ -92,9 +92,11 @@ def relabel_system_exchange( ] = { EX_ITEMS: lambda obj, _: exchange_items(obj), FEX_EX_ITEMS: exchange_name_and_items, - FEX_OR_EX_ITEMS: lambda obj, label: exchange_items(obj) - if getattr(obj, "exchange_items", "") - else label or obj.name, + FEX_OR_EX_ITEMS: lambda obj, label: ( + exchange_items(obj) + if getattr(obj, "exchange_items", "") + else label or obj.name + ), NO_UUID: uuid_filter, SYSTEM_EX_RELABEL: relabel_system_exchange, } diff --git a/capellambse_context_diagrams/serializers.py b/capellambse_context_diagrams/serializers.py index 3caee71a..1689c5a5 100644 --- a/capellambse_context_diagrams/serializers.py +++ b/capellambse_context_diagrams/serializers.py @@ -54,7 +54,11 @@ def __init__(self, elk_diagram: context.ContextDiagram) -> None: self._diagram = elk_diagram self._cache: dict[str, diagram.Box | diagram.Edge] = {} - def make_diagram(self, data: _elkjs.ELKOutputData) -> diagram.Diagram: + def make_diagram( + self, + data: _elkjs.ELKOutputData, + **kwargs: dict[str, t.Any], + ) -> diagram.Diagram: """Transform a layouted diagram into an `diagram.Diagram`. Parameters @@ -71,6 +75,7 @@ def make_diagram(self, data: _elkjs.ELKOutputData) -> diagram.Diagram: self.diagram = diagram.Diagram( self._diagram.name.replace("/", "\\"), styleclass=self._diagram.styleclass, + params=kwargs, ) for child in data["children"]: self.deserialize_child(child, diagram.Vector2D(), None) @@ -271,7 +276,9 @@ def get_styleoverrides( def order_children(self) -> None: """Reorder diagram elements such that symbols are drawn last.""" new_diagram = diagram.Diagram( - self.diagram.name, styleclass=self.diagram.styleclass + self.diagram.name, + styleclass=self.diagram.styleclass, + params=self.diagram.params, ) draw_last = list[diagram.DiagramElement]() for element in self.diagram: diff --git a/docs/gen_images.py b/docs/gen_images.py index 2dae034f..101774dd 100644 --- a/docs/gen_images.py +++ b/docs/gen_images.py @@ -35,13 +35,14 @@ class_tree_uuid = "b7c7f442-377f-492c-90bf-331e66988bda" realization_fnc_uuid = "beaf5ba4-8fa9-4342-911f-0266bb29be45" realization_comp_uuid = "b9f9a83c-fb02-44f7-9123-9d86326de5f1" +data_flow_uuid = "3b83b4ba-671a-4de8-9c07-a5c6b1d3c422" def generate_index_images() -> None: for uuid in diagram_uuids.values(): diag: context.ContextDiagram = model.by_uuid(uuid).context_diagram with mkdocs_gen_files.open(f"{str(dest / diag.name)}.svg", "w") as fd: - print(diag.as_svg, file=fd) + print(diag.render("svg", transparent_background=True), file=fd) def generate_no_symbol_images() -> None: @@ -52,7 +53,7 @@ def generate_no_symbol_images() -> None: diag.invalidate_cache() filepath = f"{str(dest / diag.name)} no_symbols.svg" with mkdocs_gen_files.open(filepath, "w") as fd: - print(diag.as_svg, file=fd) + print(diag.render("svg", transparent_background=True), file=fd) def generate_no_edgelabel_image(uuid: str) -> None: @@ -60,7 +61,12 @@ def generate_no_edgelabel_image(uuid: str) -> None: cdiagram.invalidate_cache() filename = " ".join((str(dest / cdiagram.name), "no_edgelabels")) with mkdocs_gen_files.open(f"{filename}.svg", "w") as fd: - print(cdiagram.render("svg", no_edgelabels=True), file=fd) + print( + cdiagram.render( + "svg", no_edgelabels=True, transparent_background=True + ), + file=fd, + ) def generate_filter_image( @@ -71,7 +77,7 @@ def generate_filter_image( diag.filters = {filter_name} filename = " ".join((str(dest / diag.name), suffix)) with mkdocs_gen_files.open(f"{filename}.svg", "w") as fd: - print(diag.as_svg, file=fd) + print(diag.render("svg", transparent_background=True), file=fd) def generate_styling_image( @@ -84,14 +90,19 @@ def generate_styling_image( diag.render_styles = styles filename = " ".join((str(dest / diag.name), suffix)) with mkdocs_gen_files.open(f"{filename}.svg", "w") as fd: - print(diag.as_svg, file=fd) + print(diag.render("svg", transparent_background=True), file=fd) def generate_hierarchy_image() -> None: obj = model.by_uuid(hierarchy_context) diag: context.ContextDiagram = obj.context_diagram with mkdocs_gen_files.open(f"{str(dest / diag.name)}.svg", "w") as fd: - print(diag.render("svg", include_inner_objects=True), file=fd) + print( + diag.render( + "svg", include_inner_objects=True, transparent_background=True + ), + file=fd, + ) def generate_class_tree_images() -> None: @@ -109,6 +120,7 @@ def generate_class_tree_images() -> None: direction="Right", partitioning=False, edgeLabelsSide="ALWAYS_DOWN", + transparent_background=True, ), file=fd, ) @@ -125,11 +137,20 @@ def generate_realization_view_images() -> None: depth=3, search_direction="ALL", show_owners=True, + transparent_background=True, ), file=fd, ) +def generate_data_flow_image() -> None: + diag: context.DataFlowViewDiagram = model.by_uuid( + data_flow_uuid + ).data_flow_view + with mkdocs_gen_files.open(f"{str(dest / diag.name)}.svg", "w") as fd: + print(diag.render("svg", transparent_background=True), file=fd) + + generate_index_images() generate_hierarchy_image() generate_no_symbol_images() @@ -153,3 +174,4 @@ def generate_realization_view_images() -> None: generate_styling_image(wizard, {}, "no_styles") generate_class_tree_images() generate_realization_view_images() +generate_data_flow_image() diff --git a/tests/test_dataflow_views.py b/tests/test_dataflow_views.py new file mode 100644 index 00000000..510ff92f --- /dev/null +++ b/tests/test_dataflow_views.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2022 Copyright DB InfraGO AG and the capellambse-context-diagrams contributors +# SPDX-License-Identifier: Apache-2.0 + +import capellambse +import pytest + + +@pytest.mark.parametrize( + "uuid", + [ + pytest.param( + "3b83b4ba-671a-4de8-9c07-a5c6b1d3c422", id="OperationalCapability" + ), + pytest.param("9390b7d5-598a-42db-bef8-23677e45ba06", id="Capability"), + ], +) +def test_data_flow_views(model: capellambse.MelodyModel, uuid: str) -> None: + obj = model.by_uuid(uuid) + + diag = obj.data_flow_view + + assert diag.nodes