diff.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. from __future__ import annotations
  2. from app.core.knowledge.contracts import (
  3. KnowledgeSnapshot,
  4. PointChange,
  5. SnapshotDiff,
  6. )
  7. def diff_snapshots(old: KnowledgeSnapshot, new: KnowledgeSnapshot) -> SnapshotDiff:
  8. if (old.source_type, old.source_uid) != (new.source_type, new.source_uid):
  9. raise ValueError("knowledge snapshots must describe the same source object")
  10. old_points = {point.point_key: point for point in old.points}
  11. new_points = {point.point_key: point for point in new.points}
  12. groups: dict[str, list[PointChange]] = {
  13. "added": [],
  14. "modified": [],
  15. "deleted": [],
  16. "unchanged": [],
  17. }
  18. for point_key in sorted(set(old_points) | set(new_points)):
  19. old_point = old_points.get(point_key)
  20. new_point = new_points.get(point_key)
  21. if old_point is None:
  22. kind = "added"
  23. elif new_point is None:
  24. kind = "deleted"
  25. elif (
  26. old_point.content_hash,
  27. old_point.metadata_hash,
  28. old_point.permission_hash,
  29. ) == (
  30. new_point.content_hash,
  31. new_point.metadata_hash,
  32. new_point.permission_hash,
  33. ):
  34. kind = "unchanged"
  35. else:
  36. kind = "modified"
  37. groups[kind].append(
  38. PointChange(
  39. point_key=point_key,
  40. change_kind=kind,
  41. old=old_point,
  42. new=new_point,
  43. permission_changed=bool(
  44. old_point
  45. and new_point
  46. and old_point.permission_hash != new_point.permission_hash
  47. ),
  48. )
  49. )
  50. return SnapshotDiff(
  51. added=tuple(groups["added"]),
  52. modified=tuple(groups["modified"]),
  53. deleted=tuple(groups["deleted"]),
  54. unchanged=tuple(groups["unchanged"]),
  55. )