diff --git a/capella_diff_tools/compare.py b/capella_diff_tools/compare.py index 8824268..3df7c32 100644 --- a/capella_diff_tools/compare.py +++ b/capella_diff_tools/compare.py @@ -142,7 +142,6 @@ def compare_all_objects( changes = _compare_object_type(old_layerobjs, new_layerobjs) if changes: result.setdefault(layer, {})[obj_type] = changes - return result @@ -197,11 +196,27 @@ def _obj2dict(obj: c.GenericElement) -> types.FullObject: attributes: dict[str, t.Any] = {} for attr in dir(type(obj)): acc = getattr(type(obj), attr, None) - if isinstance(acc, c.AttributeProperty): - val = getattr(obj, attr) - if val is None: - continue - attributes[attr] = _serialize_obj(val) + if not isinstance(acc, c.AttributeProperty) and attr not in [ + "parent", + "source", + "target", + "start", + "finish", + ]: + continue + + val = getattr(obj, attr) + if val is None: + continue + attributes[attr] = _serialize_obj(val) + + if hasattr(obj, "source") and hasattr(obj, "target"): + attributes["source"] = _serialize_obj(obj.source) + attributes["target"] = _serialize_obj(obj.target) + elif hasattr(obj, "start") and hasattr(obj, "finish"): + attributes["start"] = _serialize_obj(obj.start) + attributes["finish"] = _serialize_obj(obj.finish) + return { "uuid": obj.uuid, "display_name": _get_name(obj), @@ -222,9 +237,12 @@ def _obj2diff( """ attributes: dict[str, types.ChangedAttribute] = {} for attr in dir(type(old)): - if not isinstance( - getattr(type(old), attr, None), - (c.AttributeProperty, c.AttrProxyAccessor, c.LinkAccessor), + if ( + not isinstance( + getattr(type(old), attr, None), + (c.AttributeProperty, c.AttrProxyAccessor, c.LinkAccessor), + ) + and attr != "parent" ): continue diff --git a/capella_diff_tools/report.html.jinja b/capella_diff_tools/report.html.jinja index d033e67..ea96a54 100644 --- a/capella_diff_tools/report.html.jinja +++ b/capella_diff_tools/report.html.jinja @@ -34,6 +34,16 @@ .created, ins { color: #00aa00; } + .text-removed, del > p { + background: #ffe6e6; + text-decoration: none; + display: inline; + } + .text-added, ins > p { + background: #e6ffe6; + text-decoration: none; + display: inline; + } /* nice table style with borders, bold th*/ table { border-collapse: collapse; @@ -109,11 +119,35 @@ {% if key in objects %}

{{key | upper}} ({{ objects[key] | length }})

- + {% endif %}
{% endif %} {% endmacro %} @@ -132,9 +166,14 @@ {% for change in obj["attributes"] %}
  • {{ change }}: {% if "diff" in obj["attributes"][change] %} - {{ obj["attributes"][change]["diff"] }} - {% else %} - {{ obj["attributes"][change]["previous"] | e }} -> {{ obj["attributes"][change]["current"] | e }} + {% if change == "description" %} + + {% else %} + {{ obj["attributes"][change]["diff"] }} + {% endif %} {% endif %}
  • {% endfor %} diff --git a/capella_diff_tools/report.py b/capella_diff_tools/report.py index e3af53a..71b9ff2 100644 --- a/capella_diff_tools/report.py +++ b/capella_diff_tools/report.py @@ -52,7 +52,7 @@ def _diff_lists(previous, current): previous = {item["uuid"]: item for item in previous} for item in current: if item["uuid"] not in previous: - out.append(f"
  • {item}
  • ") + out.append(f"
  • {item['display_name']}
  • ") elif item["uuid"] in previous: if item["display_name"] != previous[item["uuid"]]["display_name"]: out.append( @@ -96,7 +96,13 @@ def _traverse_and_diff(data): elif prev_type == curr_type == list: diff = _diff_lists(value["previous"], value["current"]) updates[key] = {"diff": diff} - + elif key == "description": + prev, curr = _diff_description( + value["previous"].splitlines(), + value["current"].splitlines(), + ) + updates[key] = {"diff": ""} + value.update({"previous": prev, "current": curr}) elif isinstance(value, list): for item in value: _traverse_and_diff(item) @@ -107,6 +113,23 @@ def _traverse_and_diff(data): return data +def _diff_description(previous, current): + dmp = diff_match_patch.diff_match_patch() + diff = dmp.diff_main("\n".join(previous), "\n".join(current)) + dmp.diff_cleanupSemantic(diff) + previous_result = "" + current_result = "" + for operation, text in diff: + if operation == 0: + previous_result += text + current_result += text + elif operation == -1: + previous_result += f"{text}" + elif operation == 1: + current_result += f"{text}" + return previous_result, current_result + + def _compute_diff_stats(data): """Compute the diff stats for the data. diff --git a/pyproject.toml b/pyproject.toml index 83f7a21..2bdb478 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ classifiers = [ "Programming Language :: Python :: 3.12", ] dependencies = [ - "capellambse>=0.5.39,<0.6", + "capellambse>=0.5.70,<0.6", "click", "diff-match-patch>=20230430", "jinja2>=3.1.2",