@@ -21,47 +21,51 @@ def parse_metrics(content):
21
21
def parse_diff_file (diff_path ):
22
22
"""
23
23
Parses a unified diff file and categorizes changes into added, removed, and modified metrics.
24
+ Also captures the raw diff sections for each metric.
24
25
"""
25
26
changes = {
26
27
'added' : defaultdict (list ),
27
28
'removed' : defaultdict (list ),
28
29
'modified' : defaultdict (list )
29
30
}
30
31
31
- current_block = []
32
- current_change = None
32
+ # Store raw diff sections for each metric - just collect all lines related to each metric
33
+ raw_diff_sections = defaultdict ( list )
33
34
34
35
with open (diff_path , 'r' ) as f :
35
- for line in f :
36
- line = line .strip ()
37
- # Skip diff headers
38
- if line .startswith ('+++' ) or line .startswith ('---' ):
39
- continue
40
-
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 ())
36
+ lines = f .readlines ()
37
+
38
+ current_metric = None
39
+
40
+ for line in lines :
41
+ original_line = line .rstrip ()
42
+ stripped = line .strip ()
43
+
44
+ # Skip diff headers
45
+ if stripped .startswith ('+++' ) or stripped .startswith ('---' ):
46
+ continue
47
+
48
+ # Check if this line contains a metric change
49
+ if stripped .startswith ('+' ) or stripped .startswith ('-' ):
50
+ metric_name = extract_metric_name (stripped [1 :].strip ())
51
+ if metric_name :
52
+ # Track the change type
53
+ change_type = 'added' if stripped .startswith ('+' ) else 'removed'
54
+ changes [change_type ][metric_name ].append (stripped [1 :].strip ())
55
+
56
+ # Always add to raw diff sections regardless of change type
57
+ raw_diff_sections [metric_name ].append (original_line )
58
+ current_metric = metric_name
52
59
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 ])
63
- if metric_name :
64
- changes [current_change ][metric_name ].append ('\n ' .join (current_block ))
60
+ # If we're in a metric section, keep adding lines
61
+ if current_metric :
62
+ raw_diff_sections [current_metric ].append (original_line )
63
+ elif stripped .startswith (' ' ) and current_metric :
64
+ # Context line - add to current metric's raw section
65
+ raw_diff_sections [current_metric ].append (original_line )
66
+ else :
67
+ # End of current metric section
68
+ current_metric = None
65
69
66
70
# Identify modified metrics (same metric name with both additions and removals)
67
71
common_metrics = set (changes ['added' ].keys ()) & set (changes ['removed' ].keys ())
@@ -71,17 +75,36 @@ def parse_diff_file(diff_path):
71
75
'removed' : changes ['removed' ].pop (metric )
72
76
}
73
77
74
- return changes
78
+ return changes , raw_diff_sections
75
79
76
80
def extract_metric_name (line ):
77
81
"""Extracts metric name from a metric line, matching the diff generation format"""
78
82
if '{' in line :
79
83
return line .split ('{' )[0 ].strip ()
80
84
return line .strip ()
81
85
86
+ def get_raw_diff_sample (raw_sections , max_lines = 7 ):
87
+ """
88
+ Get sample raw diff lines, preserving original diff formatting.
89
+ """
90
+ if not raw_sections :
91
+ return []
92
+
93
+ # Take first section and limit lines
94
+ sample_lines = []
95
+ for section in raw_sections [:1 ]: # Just take first section to keep it concise
96
+ lines = section .split ('\n ' )
97
+ for i , line in enumerate (lines ):
98
+ if i >= max_lines :
99
+ sample_lines .append ("..." )
100
+ break
101
+ sample_lines .append (line )
102
+
103
+ return sample_lines
104
+
82
105
def generate_diff_summary (changes ):
83
106
"""
84
- Generates a markdown summary from the parsed diff changes.
107
+ Generates a markdown summary from the parsed diff changes with sample lines .
85
108
"""
86
109
summary = ["## 📊 Metrics Diff Summary\n " ]
87
110
@@ -100,12 +123,30 @@ def generate_diff_summary(changes):
100
123
summary .append ("\n ### 🆕 Added Metrics" )
101
124
for metric , samples in changes ['added' ].items ():
102
125
summary .append (f"- `{ metric } ` ({ len (samples )} variants)" )
126
+ sample_lines = get_sample_lines (samples )
127
+ if sample_lines :
128
+ summary .append ("<details>" )
129
+ summary .append ("<summary>View samples</summary>" )
130
+ summary .append ("" )
131
+ summary .append ("```" )
132
+ summary .extend (sample_lines )
133
+ summary .append ("```" )
134
+ summary .append ("</details>" )
103
135
104
136
# Removed metrics
105
137
if changes ['removed' ]:
106
138
summary .append ("\n ### ❌ Removed Metrics" )
107
139
for metric , samples in changes ['removed' ].items ():
108
140
summary .append (f"- `{ metric } ` ({ len (samples )} variants)" )
141
+ sample_lines = get_sample_lines (samples )
142
+ if sample_lines :
143
+ summary .append ("<details>" )
144
+ summary .append ("<summary>View samples</summary>" )
145
+ summary .append ("" )
146
+ summary .append ("```" )
147
+ summary .extend (sample_lines )
148
+ summary .append ("```" )
149
+ summary .append ("</details>" )
109
150
110
151
# Modified metrics
111
152
if changes ['modified' ]:
@@ -115,6 +156,32 @@ def generate_diff_summary(changes):
115
156
summary .append (f" - Added variants: { len (versions ['added' ])} " )
116
157
summary .append (f" - Removed variants: { len (versions ['removed' ])} " )
117
158
159
+ # Show samples of added variants
160
+ if versions ['added' ]:
161
+ added_samples = get_sample_lines (versions ['added' ], max_lines = 3 )
162
+ if added_samples :
163
+ summary .append (" - Sample added:" )
164
+ summary .append (" <details>" )
165
+ summary .append (" <summary>View added samples</summary>" )
166
+ summary .append ("" )
167
+ summary .append (" ```" )
168
+ summary .extend ([f" { line } " for line in added_samples ])
169
+ summary .append (" ```" )
170
+ summary .append (" </details>" )
171
+
172
+ # Show samples of removed variants
173
+ if versions ['removed' ]:
174
+ removed_samples = get_sample_lines (versions ['removed' ], max_lines = 3 )
175
+ if removed_samples :
176
+ summary .append (" - Sample removed:" )
177
+ summary .append (" <details>" )
178
+ summary .append (" <summary>View removed samples</summary>" )
179
+ summary .append ("" )
180
+ summary .append (" ```" )
181
+ summary .extend ([f" { line } " for line in removed_samples ])
182
+ summary .append (" ```" )
183
+ summary .append (" </details>" )
184
+
118
185
return "\n " .join (summary )
119
186
120
187
def main ():
@@ -124,8 +191,8 @@ def main():
124
191
125
192
args = parser .parse_args ()
126
193
127
- changes = parse_diff_file (args .diff )
128
- summary = generate_diff_summary (changes )
194
+ changes , raw_diff_sections = parse_diff_file (args .diff )
195
+ summary = generate_diff_summary (changes , raw_diff_sections )
129
196
130
197
with open (args .output , 'w' ) as f :
131
198
f .write (summary )
0 commit comments