Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to capellambse v0.6.x #5

Merged
merged 1 commit into from
Sep 24, 2024
Merged
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
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ repos:
hooks:
- id: mypy
additional_dependencies:
- capellambse==0.6.6
- types-pyyaml
- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.5.4
Expand Down
14 changes: 8 additions & 6 deletions capella_diff_tools/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,26 @@

import datetime
import logging
import os
import pathlib
import sys
import typing as t

import capellambse
import capellambse.filehandler.git
import capellambse.model as m
import click
import markupsafe
import yaml
from capellambse import filehandler as fh
from capellambse.model import common as c

import capella_diff_tools

from . import compare, report, types

logger = logging.getLogger(__name__)

_T = t.TypeVar("_T", bound=c.GenericElement)
_T = t.TypeVar("_T", bound=m.ModelElement)


@click.command()
Expand All @@ -32,7 +33,7 @@
prog_name="Capella Diff Tools",
message="%(prog)s %(version)s",
)
@click.argument("model", type=capellambse.cli_helpers.ModelInfoCLI())
@click.argument("model", type=capellambse.ModelInfoCLI())
@click.argument("old_version")
@click.argument("new_version")
@click.option(
Expand Down Expand Up @@ -91,7 +92,7 @@ def main(
report_file.write(report.generate_html(result))


def _ensure_git(path: str | pathlib.Path) -> str:
def _ensure_git(path: str | os.PathLike[str]) -> str:
proto, path = fh.split_protocol(path)
if proto == "file":
assert isinstance(path, pathlib.Path)
Expand All @@ -110,17 +111,18 @@ def _get_revision_info(
revision: str,
) -> types.RevisionInfo:
"""Return the revision info of the given model."""
info = model.info
res = model._loader.resources["\x00"]
assert isinstance(res, fh.git.GitFileHandler)
info = res.get_model_info()
assert isinstance(info, fh.git.GitHandlerInfo)
assert t.assert_type(info.rev_hash, str) is not None
author, date_str, description = res._git(
"log",
"-1",
"--format=%aN%x00%aI%x00%B",
info.rev_hash,
encoding="utf-8",
).split("\x00")
assert info.rev_hash is not None
return {
"hash": info.rev_hash,
"revision": revision,
Expand Down
41 changes: 19 additions & 22 deletions capella_diff_tools/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@

import capellambse
import capellambse.model as m
import capellambse.model.common as c

from . import types

logger = logging.getLogger(__name__)

_T = t.TypeVar("_T", bound=c.GenericElement)
_T = t.TypeVar("_T", bound=m.ModelElement)


def compare_all_diagrams(
Expand Down Expand Up @@ -71,7 +70,7 @@ def _compare_diagrams_on_layer(


def _diag2dict(
obj: m.diagram.Diagram | c.GenericElement,
obj: m.Diagram | m.ModelElement,
) -> types.FullDiagram:
"""Serialize a diagram element into a dict.

Expand All @@ -81,9 +80,7 @@ def _diag2dict(
return {"uuid": obj.uuid, "display_name": _get_name(obj)}


def _diag2diff(
old: m.diagram.Diagram, new: m.diagram.Diagram
) -> types.ChangedDiagram | None:
def _diag2diff(old: m.Diagram, new: m.Diagram) -> types.ChangedDiagram | None:
"""Serialize the differences between the old and new diagram.

This function is used for diagrams that were modified. Newly
Expand Down Expand Up @@ -148,25 +145,25 @@ def compare_all_objects(

def _group_all_objects(
model: capellambse.MelodyModel,
) -> dict[str, dict[str, c.ElementList[c.GenericElement]]]:
) -> dict[str, dict[str, m.ElementList[m.ModelElement]]]:
"""Return a dict of all objects, grouped by layer."""
result: dict[str, dict[str, c.ElementList[c.GenericElement]]]
result: dict[str, dict[str, m.ElementList[m.ModelElement]]]
result = {"oa": {}, "sa": {}, "la": {}, "pa": {}}
for layer, objs in result.items():
ungrouped = sorted(
model.search(below=getattr(model, layer)),
key=lambda i: type(i).__name__,
)
for objtype, group in itertools.groupby(ungrouped, key=type):
objs[objtype.__name__] = c.ElementList(
objs[objtype.__name__] = m.ElementList(
model, [i._element for i in group], objtype
)
return result


def _compare_object_type(
old: c.ElementList[_T],
new: c.ElementList[_T],
old: m.ElementList[_T],
new: m.ElementList[_T],
) -> types.ObjectChange:
changes: types.ObjectChange = {}

Expand All @@ -188,7 +185,7 @@ def _compare_object_type(
return changes


def _obj2dict(obj: c.GenericElement) -> types.FullObject:
def _obj2dict(obj: m.ModelElement) -> types.FullObject:
"""Serialize a model object into a dict.

This function is used for objects that were either created or
Expand All @@ -197,7 +194,7 @@ 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):
if isinstance(acc, m.BasePOD):
val = getattr(obj, attr)
if val is None:
continue
Expand All @@ -210,7 +207,7 @@ def _obj2dict(obj: c.GenericElement) -> types.FullObject:


def _obj2diff(
old: c.GenericElement, new: c.GenericElement
old: m.ModelElement, new: m.ModelElement
) -> types.ChangedObject | None:
"""Serialize the differences between the old and new object.

Expand All @@ -224,7 +221,7 @@ def _obj2diff(
for attr in dir(type(old)):
if not isinstance(
getattr(type(old), attr, None),
(c.AttributeProperty, c.AttrProxyAccessor, c.LinkAccessor),
(m.BasePOD, m.AttrProxyAccessor, m.LinkAccessor),
):
continue

Expand Down Expand Up @@ -259,16 +256,16 @@ def _obj2diff(
else:
raise

if isinstance(old_val, c.GenericElement) and isinstance(
new_val, c.GenericElement
if isinstance(old_val, m.ModelElement) and isinstance(
new_val, m.ModelElement
):
if old_val.uuid != new_val.uuid:
attributes[attr] = {
"previous": _serialize_obj(old_val),
"current": _serialize_obj(new_val),
}
elif isinstance(old_val, c.ElementList) and isinstance(
new_val, c.ElementList
elif isinstance(old_val, m.ElementList) and isinstance(
new_val, m.ElementList
):
if [i.uuid for i in old_val] != [i.uuid for i in new_val]:
attributes[attr] = {
Expand All @@ -291,16 +288,16 @@ def _obj2diff(


def _serialize_obj(obj: t.Any) -> t.Any:
if isinstance(obj, c.GenericElement):
if isinstance(obj, m.ModelElement):
return {"uuid": obj.uuid, "display_name": _get_name(obj)}
elif isinstance(obj, c.ElementList):
elif isinstance(obj, m.ElementList):
return [{"uuid": i.uuid, "display_name": _get_name(i)} for i in obj]
elif isinstance(obj, (enum.Enum, enum.Flag)):
return obj.name
return obj


def _get_name(obj: m.diagram.Diagram | c.GenericElement) -> str:
def _get_name(obj: m.Diagram | m.ModelElement) -> str:
"""Return the object's name.

If the object doesn't own a name, its type is returned instead.
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.6.6,<0.7",
"click",
"diff-match-patch>=20230430",
"jinja2>=3.1.2",
Expand Down
Loading