Compare two ParsedManpage objects and return a list of structured diff entries. Each entry is a dict with: - "type": "field" | "option_changed" | "option_added" | "option_removed" - "label": human-readable label - "details": list of (field, old_val, new_val) tuples (for field/
(
stored_mp: ParsedManpage,
fresh_mp: ParsedManpage,
skip_fields: tuple[str, ...] = (),
)
| 58 | |
| 59 | |
| 60 | def compare_manpages( |
| 61 | stored_mp: ParsedManpage, |
| 62 | fresh_mp: ParsedManpage, |
| 63 | skip_fields: tuple[str, ...] = (), |
| 64 | ) -> list[dict]: |
| 65 | """Compare two ParsedManpage objects and return a list of structured diff entries. |
| 66 | |
| 67 | Each entry is a dict with: |
| 68 | - "type": "field" | "option_changed" | "option_added" | "option_removed" |
| 69 | - "label": human-readable label |
| 70 | - "details": list of (field, old_val, new_val) tuples (for field/option_changed) |
| 71 | or option object (for added/removed) |
| 72 | |
| 73 | *skip_fields* is an optional iterable of top-level field names to ignore. |
| 74 | """ |
| 75 | diffs: list[dict] = [] |
| 76 | skip = set(skip_fields) |
| 77 | |
| 78 | for field in _MP_FIELDS: |
| 79 | if field in skip: |
| 80 | continue |
| 81 | old_val = _normalize(field, getattr(stored_mp, field)) |
| 82 | new_val = _normalize(field, getattr(fresh_mp, field)) |
| 83 | if old_val != new_val: |
| 84 | diffs.append( |
| 85 | { |
| 86 | "type": "field", |
| 87 | "label": field, |
| 88 | "details": [(field, old_val, new_val)], |
| 89 | } |
| 90 | ) |
| 91 | |
| 92 | stored_opts = {_option_key(o): o for o in stored_mp.options} |
| 93 | fresh_opts = {_option_key(o): o for o in fresh_mp.options} |
| 94 | all_keys = list(dict.fromkeys(list(stored_opts.keys()) + list(fresh_opts.keys()))) |
| 95 | |
| 96 | for key in all_keys: |
| 97 | s_opt = stored_opts.get(key) |
| 98 | f_opt = fresh_opts.get(key) |
| 99 | |
| 100 | if s_opt and f_opt: |
| 101 | opt_diffs = [] |
| 102 | for field in _OPT_FIELDS: |
| 103 | old_val = _normalize(field, getattr(s_opt, field)) |
| 104 | new_val = _normalize(field, getattr(f_opt, field)) |
| 105 | if old_val != new_val: |
| 106 | opt_diffs.append((field, old_val, new_val)) |
| 107 | if opt_diffs: |
| 108 | diffs.append( |
| 109 | { |
| 110 | "type": "option_changed", |
| 111 | "label": _fmt_flags(s_opt), |
| 112 | "details": opt_diffs, |
| 113 | } |
| 114 | ) |
| 115 | elif f_opt: |
| 116 | diffs.append( |
| 117 | { |
no test coverage detected