1+ import difflib
12import html
23import re
34from 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
124125def 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°</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