Skip to content

Commit e6c8a3a

Browse files
committed
feat: use difflib SequenceMatcher to handle frame offsets in test diffs
1 parent 8e4f6f8 commit e6c8a3a

1 file changed

Lines changed: 68 additions & 64 deletions

File tree

mod_test/nicediff/diff.py

Lines changed: 68 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import difflib
12
import html
23
import re
34
from typing import Any, List, Optional, Tuple, Union
@@ -122,11 +123,11 @@ def create_diff_entries(suffix_id: str, id_name: str, events: List[List[object]]
122123

123124

124125
def get_html_diff(test_correct_lines: List[str], test_res_lines: List[str], to_view: bool = True) -> str:
125-
"""Return generated difference in HTML formatted table."""
126+
"""Return generated difference in HTML formatted table using smart sequence matching."""
126127
# variable to keep count of diff lines noted
127128
number_of_noted_diff_lines = 0
128129

129-
html = """
130+
html_out = """
130131
<table>
131132
<tr>
132133
<td class="diff-table-td" style="width: 30px;">n&deg;</td>
@@ -138,81 +139,84 @@ def get_html_diff(test_correct_lines: List[str], test_res_lines: List[str], to_v
138139
</tr>
139140
</table>"""
140141

141-
res_len = len(test_res_lines)
142-
correct_len = len(test_correct_lines)
143-
144-
if res_len <= correct_len:
145-
use = res_len
146-
till = correct_len
147-
148-
else:
149-
use = correct_len
150-
till = res_len
151-
152-
for line in range(use):
142+
sm = difflib.SequenceMatcher(None, test_res_lines, test_correct_lines)
143+
144+
for tag, i1, i2, j1, j2 in sm.get_opcodes():
153145
if to_view and number_of_noted_diff_lines >= MAX_NUMBER_OF_LINES_TO_VIEW:
154146
break
155-
156-
if test_correct_lines[line] == test_res_lines[line]:
147+
148+
if tag == 'equal':
157149
continue
158-
html += """
150+
151+
if tag == 'replace':
152+
max_len = max(i2 - i1, j2 - j1)
153+
for k in range(max_len):
154+
if to_view and number_of_noted_diff_lines >= MAX_NUMBER_OF_LINES_TO_VIEW:
155+
break
156+
157+
html_out += """
159158
<table>"""
160-
actual, expected = _process(test_res_lines[line], test_correct_lines[line], suffix_id=str(line))
161-
162-
html += f"""
159+
160+
res_idx = i1 + k
161+
corr_idx = j1 + k
162+
163+
res_line = test_res_lines[res_idx] if res_idx < i2 else " "
164+
corr_line = test_correct_lines[corr_idx] if corr_idx < j2 else " "
165+
line_display = str(res_idx + 1) if res_idx < i2 else ""
166+
167+
actual, expected = _process(res_line, corr_line, suffix_id=str(res_idx if res_idx < i2 else corr_idx))
168+
169+
html_out += f"""
163170
<tr>
164-
<td class="diff-table-td" style="width: 30px;">{line + 1}</td>
171+
<td class="diff-table-td" style="width: 30px;">{line_display}</td>
165172
<td class="diff-table-td">{actual}</td>
166173
</tr>
167174
<tr>
168175
<td class="diff-table-td" style="width: 30px;"></td>
169176
<td class="diff-table-td">{expected}</td>
170177
</tr>"""
171-
html += """
178+
html_out += """
172179
</table>"""
180+
number_of_noted_diff_lines += 1
173181

174-
# increase noted diff line by one
175-
number_of_noted_diff_lines += 1
176-
177-
# processing remaining lines
178-
for line in range(use, till):
179-
180-
# stop at 50 lines if test-data for viewing
181-
if to_view and number_of_noted_diff_lines >= MAX_NUMBER_OF_LINES_TO_VIEW:
182-
break
183-
184-
html += """
182+
elif tag == 'delete':
183+
for k in range(i1, i2):
184+
if to_view and number_of_noted_diff_lines >= MAX_NUMBER_OF_LINES_TO_VIEW:
185+
break
186+
html_out += """
185187
<table>"""
186-
187-
if till == res_len:
188-
output, _ = _process(test_res_lines[line], " ", suffix_id=str(line))
189-
html += f"""
190-
<tr>
191-
<td class="diff-table-td" style="width: 30px;">{line + 1}</td>
192-
<td class="diff-table-td">{output}</td>
193-
</tr>
194-
<tr>
195-
<td class="diff-table-td" style="width: 30px;"></td>
196-
<td class="diff-table-td"></td>
197-
</tr>
198-
"""
199-
else:
200-
_, output = _process(" ", test_correct_lines[line], suffix_id=str(line))
201-
html += f"""
202-
<tr>
203-
<td class="diff-table-td" style="width: 30px;">{line + 1}</td>
204-
<td class="diff-table-td"></td>
205-
</tr>
206-
<tr>
207-
<td class="diff-table-td" style="width: 30px;"></td>
208-
<td class="diff-table-td">{output}</td>
209-
</tr>
210-
"""
211-
212-
html += """
188+
output, _ = _process(test_res_lines[k], " ", suffix_id=str(k))
189+
html_out += f"""
190+
<tr>
191+
<td class="diff-table-td" style="width: 30px;">{k + 1}</td>
192+
<td class="diff-table-td">{output}</td>
193+
</tr>
194+
<tr>
195+
<td class="diff-table-td" style="width: 30px;"></td>
196+
<td class="diff-table-td"></td>
197+
</tr>"""
198+
html_out += """
199+
</table>"""
200+
number_of_noted_diff_lines += 1
201+
202+
elif tag == 'insert':
203+
for k in range(j1, j2):
204+
if to_view and number_of_noted_diff_lines >= MAX_NUMBER_OF_LINES_TO_VIEW:
205+
break
206+
html_out += """
213207
<table>"""
208+
_, output = _process(" ", test_correct_lines[k], suffix_id=str(k))
209+
html_out += f"""
210+
<tr>
211+
<td class="diff-table-td" style="width: 30px;"></td>
212+
<td class="diff-table-td"></td>
213+
</tr>
214+
<tr>
215+
<td class="diff-table-td" style="width: 30px;"></td>
216+
<td class="diff-table-td">{output}</td>
217+
</tr>"""
218+
html_out += """
219+
</table>"""
220+
number_of_noted_diff_lines += 1
214221

215-
# increase noted diff line by one
216-
number_of_noted_diff_lines += 1
217-
218-
return html
222+
return html_out

0 commit comments

Comments
 (0)