diff --git a/capella2polarion/elements/api_helper.py b/capella2polarion/elements/api_helper.py index ffbce1e3..b6295b29 100644 --- a/capella2polarion/elements/api_helper.py +++ b/capella2polarion/elements/api_helper.py @@ -1,16 +1,14 @@ # Copyright DB Netz AG and contributors # SPDX-License-Identifier: Apache-2.0 """Capella2Polarion specific helper functions to use the API.""" -import base64 +import base64 as b64 import collections.abc as cabc -import io import logging -import re import typing as t +import cairosvg import polarion_rest_api_client as polarion_api from capellambse.model import common -from PIL import Image, ImageChops from capella2polarion.elements import serialize @@ -82,38 +80,25 @@ def patch_work_item( logger.error("Updating work item %r failed. %s", wi, error.args[0]) -def decode_diagram(dia: str): - """Decode a diagram from a base64 string.""" - encoded = dia.replace("data:image/", "").split(";base64,", 1) - - decoded = base64.b64decode(encoded[1]) - - return encoded[0], decoded +def split_and_decode_diagram(diagram: str) -> tuple[str, bytes]: + """Split the diagram into type and data and decode the data.""" + prefix, encoded = diagram.split(";base64,") + return prefix.replace("data:image/", ""), b64.b64decode(encoded) def has_visual_changes(old: str, new: str) -> bool: """Return True if the images of the diagrams differ.""" - type_old, decoded_old = decode_diagram(old) - type_new, decoded_new = decode_diagram(new) + type_old, decoded_old = split_and_decode_diagram(old) + type_new, decoded_new = split_and_decode_diagram(new) if type_old != type_new: return True if type_old == "svg+xml": - d_new = decoded_new.decode("utf-8").splitlines() - for i, d_old in enumerate(decoded_old.decode("utf-8").splitlines()): - if re.sub(r'id=["\'][^"\']*["\']', "", d_old) != re.sub( - r'id=["\'][^"\']*["\']', "", d_new[i] - ): - return True - return False - - image_old = Image.open(io.BytesIO(decoded_old)) - image_new = Image.open(io.BytesIO(decoded_new)) - - diff = ImageChops.difference(image_old, image_new) + decoded_old = cairosvg.svg2png(bytestring=decoded_old) + decoded_new = cairosvg.svg2png(bytestring=decoded_new) - return bool(diff.getbbox()) + return decoded_old != decoded_new def handle_links( diff --git a/pyproject.toml b/pyproject.toml index b9a600b9..40fe5330 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ dependencies = [ "PyYAML", "polarion-rest-api-client @ git+https://github.com/DSD-DBS/polarion-rest-api-client.git@feat-add-attachments-workitem-relations", "requests", + "cairosvg", ] [project.urls] diff --git a/tests/test_elements.py b/tests/test_elements.py index 510b45cd..802cb9ad 100644 --- a/tests/test_elements.py +++ b/tests/test_elements.py @@ -80,36 +80,6 @@ class TestAPIHelper: pathlib.Path(__file__).parent / "data" / "svg_diff" / "example.svg" ) SVG_PREFIX = "data:image/svg+xml;base64," - PNG_PREFIX = "data:image/png;base64," - - def encode_png(self, img: Image.Image) -> str: - image_buffer = io.BytesIO() - img.save(image_buffer, format="PNG") - image_buffer.seek(0) - encoded = base64.b64encode(image_buffer.read()).decode() - image_buffer.close() - return f"{self.PNG_PREFIX}{encoded}" - - def test_pixel_diff(self): - img1 = Image.new("RGB", (100, 100)) - img2 = Image.new("RGB", (100, 100)) - img2.putpixel((0, 0), (255, 0, 0)) - - assert ( - api_helper.has_visual_changes( - self.encode_png(img1), - self.encode_png(img2), - ) - is True - ) - - assert ( - api_helper.has_visual_changes( - self.encode_png(img1), - self.encode_png(img1), - ) - is False - ) def encode_svg(self, params) -> str: svg = self.SVG_PATH.read_text() @@ -146,7 +116,7 @@ def encode_svg(self, params) -> str: ), ], ) - def test_svg_diff(self, changed_params, expected): + def test_image_diff(self, changed_params, expected): old_params, new_params = changed_params assert (