@@ -18,102 +18,136 @@ def parse_metrics(content):
18
18
metrics .append (metric )
19
19
return metrics
20
20
21
+ def extract_metric_name (line ):
22
+ """Extracts metric name from a metric line, matching the diff generation format"""
23
+ if '{' in line :
24
+ return line .split ('{' )[0 ].strip ()
25
+ return line .strip ()
26
+
21
27
def parse_diff_file (diff_path ):
22
28
"""
23
29
Parses a unified diff file and categorizes changes into added, removed, and modified metrics.
24
30
"""
25
- changes = {
26
- 'added' : defaultdict (list ),
27
- 'removed' : defaultdict (list ),
28
- 'modified' : defaultdict (list )
29
- }
30
-
31
- current_block = []
32
- current_change = None
33
-
31
+ added_lines = []
32
+ removed_lines = []
34
33
with open (diff_path , 'r' ) as f :
35
34
for line in f :
36
- line = line .strip ()
37
- # Skip diff headers
38
- if line .startswith ('+++' ) or line .startswith ('---' ):
35
+ # Skip file headers and context lines
36
+ if line .startswith ('+++' ) or line .startswith ('---' ) or line .startswith ('@@' ) or line .startswith (' ' ):
39
37
continue
38
+ if line .startswith ('+' ):
39
+ added_lines .append (line [1 :].strip ())
40
+ elif line .startswith ('-' ):
41
+ removed_lines .append (line [1 :].strip ())
42
+
43
+ # Group lines by metric name
44
+ added_by_metric = defaultdict (list )
45
+ for line in added_lines :
46
+ metric_name = extract_metric_name (line )
47
+ if metric_name :
48
+ added_by_metric [metric_name ].append (line )
40
49
41
- # Start new block for changes
42
- if line .startswith ('+' ) or line .startswith ('-' ):
43
- if current_block and current_change :
44
- metric_name = extract_metric_name (current_block [0 ])
45
- if metric_name :
46
- changes [current_change ][metric_name ].append ('\n ' .join (current_block ))
47
- current_block = [line [1 :].strip ()] # Remove +/-
48
- current_change = 'added' if line .startswith ('+' ) else 'removed'
49
- elif line .startswith (' ' ):
50
- if current_block :
51
- current_block .append (line .strip ())
52
- else :
53
- if current_block and current_change :
54
- metric_name = extract_metric_name (current_block [0 ])
55
- if metric_name :
56
- changes [current_change ][metric_name ].append ('\n ' .join (current_block ))
57
- current_block = []
58
- current_change = None
59
-
60
- # Process any remaining block
61
- if current_block and current_change :
62
- metric_name = extract_metric_name (current_block [0 ])
50
+ removed_by_metric = defaultdict (list )
51
+ for line in removed_lines :
52
+ metric_name = extract_metric_name (line )
63
53
if metric_name :
64
- changes [current_change ][metric_name ].append ('\n ' .join (current_block ))
65
-
66
- # Identify modified metrics (same metric name with both additions and removals)
67
- common_metrics = set (changes ['added' ].keys ()) & set (changes ['removed' ].keys ())
68
- for metric in common_metrics :
69
- changes ['modified' ][metric ] = {
70
- 'added' : changes ['added' ].pop (metric ),
71
- 'removed' : changes ['removed' ].pop (metric )
54
+ removed_by_metric [metric_name ].append (line )
55
+
56
+ changes = {
57
+ 'added' : {},
58
+ 'removed' : {},
59
+ 'modified' : {}
60
+ }
61
+
62
+ # Identify modified metrics (present in both added and removed)
63
+ common_metric_names = set (added_by_metric .keys ()) & set (removed_by_metric .keys ())
64
+ for name in common_metric_names :
65
+ changes ['modified' ][name ] = {
66
+ 'added' : added_by_metric .pop (name ),
67
+ 'removed' : removed_by_metric .pop (name )
72
68
}
73
69
74
- return changes
70
+ # The remaining are purely added or removed
71
+ changes ['added' ] = added_by_metric
72
+ changes ['removed' ] = removed_by_metric
75
73
76
- def extract_metric_name (line ):
77
- """Extracts metric name from a metric line, matching the diff generation format"""
78
- if '{' in line :
79
- return line .split ('{' )[0 ].strip ()
80
- return line .strip ()
74
+ return changes
81
75
82
- def generate_diff_summary (changes ):
76
+ def generate_diff_summary (changes , sample_size = 7 ):
83
77
"""
84
- Generates a markdown summary from the parsed diff changes.
78
+ Generates a markdown summary from the parsed diff changes, including samples .
85
79
"""
86
80
summary = ["## 📊 Metrics Diff Summary\n " ]
87
81
88
- # Statistics header
89
- total_added = sum (len (v ) for v in changes ['added' ].values ())
90
- total_removed = sum (len (v ) for v in changes ['removed' ].values ())
91
- total_modified = len (changes ['modified' ])
82
+ # --- Statistics Header ---
83
+ num_added = len (changes ['added' ])
84
+ num_removed = len (changes ['removed' ])
85
+ num_modified = len (changes ['modified' ])
86
+ total_changes = num_added + num_removed + num_modified
92
87
93
- summary .append (f"**Total Changes:** { total_added + total_removed + total_modified } \n " )
94
- summary .append (f"- 🆕 Added: { total_added } metrics" )
95
- summary .append (f"- ❌ Removed: { total_removed } metrics" )
96
- summary .append (f"- 🔄 Modified: { total_modified } metrics\n " )
88
+ summary .append (f"**Total Changes:** { total_changes } \n " )
89
+ summary .append (f"- 🆕 Added: { num_added } metrics" )
90
+ summary .append (f"- ❌ Removed: { num_removed } metrics" )
91
+ summary .append (f"- 🔄 Modified: { num_modified } metrics\n " )
97
92
98
- # Added metrics
93
+ # --- Modified Metrics ---
94
+ if changes ['modified' ]:
95
+ summary .append ("\n ### 🔄 Modified Metrics" )
96
+ for metric , versions in sorted (changes ['modified' ].items ()):
97
+ added_count = len (versions ['added' ])
98
+ removed_count = len (versions ['removed' ])
99
+ summary .append (f"- `{ metric } `" )
100
+ summary .append (f" - Added variants: { added_count } " )
101
+ summary .append (f" - Removed variants: { removed_count } " )
102
+
103
+ # Add collapsible sample
104
+ summary .append (" <details>" )
105
+ summary .append (" <summary>View sample</summary>\n " )
106
+ summary .append (" ```diff" )
107
+ for sample in versions ['removed' ][:sample_size ]:
108
+ summary .append (f"- { sample } " )
109
+ if removed_count > sample_size :
110
+ summary .append (f" ... and { removed_count - sample_size } more removed variants" )
111
+ for sample in versions ['added' ][:sample_size ]:
112
+ summary .append (f"+ { sample } " )
113
+ if added_count > sample_size :
114
+ summary .append (f" ... and { added_count - sample_size } more added variants" )
115
+ summary .append (" ```" )
116
+ summary .append (" </details>" )
117
+
118
+ # --- Added Metrics ---
99
119
if changes ['added' ]:
100
120
summary .append ("\n ### 🆕 Added Metrics" )
101
- for metric , samples in changes ['added' ].items ():
121
+ for metric , samples in sorted ( changes ['added' ].items () ):
102
122
summary .append (f"- `{ metric } ` ({ len (samples )} variants)" )
103
123
104
- # Removed metrics
124
+ # Add collapsible sample
125
+ summary .append (" <details>" )
126
+ summary .append (" <summary>View sample</summary>\n " )
127
+ summary .append (" ```diff" )
128
+ for sample in samples [:sample_size ]:
129
+ summary .append (f"+ { sample } " )
130
+ if len (samples ) > sample_size :
131
+ summary .append (f" ... and { len (samples ) - sample_size } more variants" )
132
+ summary .append (" ```" )
133
+ summary .append (" </details>" )
134
+
135
+ # --- Removed Metrics ---
105
136
if changes ['removed' ]:
106
137
summary .append ("\n ### ❌ Removed Metrics" )
107
- for metric , samples in changes ['removed' ].items ():
138
+ for metric , samples in sorted ( changes ['removed' ].items () ):
108
139
summary .append (f"- `{ metric } ` ({ len (samples )} variants)" )
109
140
110
- # Modified metrics
111
- if changes ['modified' ]:
112
- summary .append ("\n ### 🔄 Modified Metrics" )
113
- for metric , versions in changes ['modified' ].items ():
114
- summary .append (f"- `{ metric } `" )
115
- summary .append (f" - Added variants: { len (versions ['added' ])} " )
116
- summary .append (f" - Removed variants: { len (versions ['removed' ])} " )
141
+ # Add collapsible sample
142
+ summary .append (" <details>" )
143
+ summary .append (" <summary>View sample</summary>\n " )
144
+ summary .append (" ```diff" )
145
+ for sample in samples [:sample_size ]:
146
+ summary .append (f"- { sample } " )
147
+ if len (samples ) > sample_size :
148
+ summary .append (f" ... and { len (samples ) - sample_size } more variants" )
149
+ summary .append (" ```" )
150
+ summary .append (" </details>" )
117
151
118
152
return "\n " .join (summary )
119
153
0 commit comments