From c2800ce646952f06a741d59b904eec73938aa058 Mon Sep 17 00:00:00 2001 From: Mike Geppert Date: Sun, 4 Jan 2026 12:52:44 -0600 Subject: [PATCH] Change rule differences to columnar format for easier field comparison - Display rule fields side-by-side in columns like other sections - Makes it easier to compare State, Once, Length, Free, Rules, etc. - Consistent formatting with rest of report --- device_diff.py | 55 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/device_diff.py b/device_diff.py index 7723699..4d3e057 100644 --- a/device_diff.py +++ b/device_diff.py @@ -278,7 +278,7 @@ class DeviceComparison: def _print_rule_differences(self, differences: List[Dict], device1_name: str, device2_name: str) -> None: """ - Print rule differences in row format (device per row). + Print rule differences in columnar format for easier field comparison. Args: differences: List of difference dictionaries @@ -288,25 +288,48 @@ class DeviceComparison: if not differences: return + # Group differences by rule number + rules_by_number = {} for diff in differences: rule_key = str(diff['key']) + rules_by_number[rule_key] = diff + + # Print each rule's details in columnar format + for rule_num in sorted(rules_by_number.keys()): + diff = rules_by_number[rule_num] val1 = diff['device1_value'] val2 = diff['device2_value'] - print(f"\n{rule_key}:") + print(f"\n{rule_num}:") - # Print Device 1 - print(f" {device1_name}:") - if isinstance(val1, dict): - for key, value in val1.items(): - print(f" {key}: {value}") - else: - print(f" {val1}") + # Extract all fields from both devices + if isinstance(val1, dict) and isinstance(val2, dict): + all_fields = set(val1.keys()) | set(val2.keys()) - # Print Device 2 - print(f" {device2_name}:") - if isinstance(val2, dict): - for key, value in val2.items(): - print(f" {key}: {value}") - else: - print(f" {val2}") + # Calculate column widths + max_field_len = max(len(field) for field in all_fields) if all_fields else 10 + field_width = max(max_field_len, 10) + + dev1_header = device1_name + dev2_header = device2_name + + # Calculate value column widths + val1_width = max(len(dev1_header), 20) + val2_width = max(len(dev2_header), 20) + + # Print header + print(f"{'Field':<{field_width}} {dev1_header:<{val1_width}} {dev2_header:<{val2_width}}") + print("-" * field_width + " " + "-" * val1_width + " " + "-" * val2_width) + + # Print each field + for field in sorted(all_fields): + v1 = str(val1.get(field, 'N/A')) + v2 = str(val2.get(field, 'N/A')) + + # Truncate if too long + if len(v1) > val1_width: + v1 = v1[:val1_width-3] + "..." + if len(v2) > val2_width: + v2 = v2[:val2_width-3] + "..." + + print(f"{field:<{field_width}} {v1:<{val1_width}} {v2:<{val2_width}}")