Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions capella_diff_tools/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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),
Expand All @@ -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

Expand Down
53 changes: 46 additions & 7 deletions capella_diff_tools/report.html.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -109,11 +119,35 @@
{% if key in objects %}
<h4 style="color: {{color}}">{{key | upper}} ({{ objects[key] | length }})</h4>
<div class="section">
<ul>
{% for obj in objects[key] %}
<li>{{obj["display_name"] | e}}</li>
{% set parent_dict = {} %}
{% for obj in objects[key] %}
{% if "parent" in obj["attributes"] %}
{% set parent_name = obj["attributes"]["parent"]["display_name"] %}
{% set display_name = obj["display_name"] %}
{% if parent_name in parent_dict %}
{% set _ = parent_dict[parent_name].append(obj) %}
{% else %}
{% set _ = parent_dict.update({parent_name: [obj]}) %}
{% endif %}
{% endif %}
{% endfor %}
{% if parent_dict %}
{% for parent, children in parent_dict.items() %}
<h5>{{ parent | e }}</h5>
<ul>
{% for child in children %}
<li>{{ child.display_name | e }}</li>
<ul>
{% for key, value in child.attributes.items() %}
{% if key in ["start", "finish", "source", "target"] %}
<li><strong>{{ key | e }}</strong>: {{ value.display_name | e }}</li>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
</ul>
{% endfor %}
</ul>
{% endif %}
</div>
{% endif %}
{% endmacro %}
Expand All @@ -132,9 +166,14 @@
{% for change in obj["attributes"] %}
<li><b>{{ change }}</b>:
{% if "diff" in obj["attributes"][change] %}
{{ obj["attributes"][change]["diff"] }}
{% else %}
{{ obj["attributes"][change]["previous"] | e }} -&gt; {{ obj["attributes"][change]["current"] | e }}
{% if change == "description" %}
<ul>
<li><strong>Previous</strong>: {{ obj["attributes"][change]["previous"] | safe }}</li>
<li><strong>Current</strong>: {{ obj["attributes"][change]["current"] | safe }}</li>
</ul>
{% else %}
{{ obj["attributes"][change]["diff"] }}
{% endif %}
{% endif %}
</li>
{% endfor %}
Expand Down
27 changes: 25 additions & 2 deletions capella_diff_tools/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"<li><ins>{item}</ins></li>")
out.append(f"<li><ins>{item['display_name']}</ins></li>")
elif item["uuid"] in previous:
if item["display_name"] != previous[item["uuid"]]["display_name"]:
out.append(
Expand Down Expand Up @@ -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)
Expand All @@ -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"<del class='text-removed'>{text}</del>"
elif operation == 1:
current_result += f"<ins class='text-added'>{text}</ins>"
return previous_result, current_result


def _compute_diff_stats(data):
"""Compute the diff stats for the data.

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down