src/pqc_mbom/diff.py
1.2 KB · 34 lines · python Raw
1 """Diff two MBOMs - useful for auditing model updates / fine-tunes."""
2
3 from __future__ import annotations
4
5 from dataclasses import dataclass
6
7 from pqc_mbom.component import ModelComponent
8 from pqc_mbom.mbom import MBOM
9
10
11 @dataclass(frozen=True)
12 class MBOMDiff:
13 added: list[ModelComponent]
14 removed: list[ModelComponent]
15 changed: list[tuple[ModelComponent, ModelComponent]] # (old, new) same id different hash
16
17 @property
18 def is_empty(self) -> bool:
19 """True iff the two MBOMs describe the same component set with identical hashes."""
20 return not self.added and not self.removed and not self.changed
21
22
23 def diff_mboms(old: MBOM, new: MBOM) -> MBOMDiff:
24 old_by_id = {c.component_id: c for c in old.components}
25 new_by_id = {c.component_id: c for c in new.components}
26
27 added = [c for cid, c in new_by_id.items() if cid not in old_by_id]
28 removed = [c for cid, c in old_by_id.items() if cid not in new_by_id]
29 changed: list[tuple[ModelComponent, ModelComponent]] = []
30 for cid, old_c in old_by_id.items():
31 if cid in new_by_id and old_c.hash() != new_by_id[cid].hash():
32 changed.append((old_c, new_by_id[cid]))
33 return MBOMDiff(added=added, removed=removed, changed=changed)
34