33from enum import Enum
44from dataclasses import dataclass
55
6+ from difflib_parser .diff_line import DiffLine , DiffLineCode
7+
68
79class DiffCode (Enum ):
810 SAME = 0
@@ -11,44 +13,6 @@ class DiffCode(Enum):
1113 CHANGED = 3
1214
1315
14- class DiffLineCode (Enum ):
15- ADDED = 0
16- REMOVED = 1
17- COMMON = 2
18- MISSING = 3
19-
20-
21- class DiffLine :
22- def __init__ (self , line : str | None ):
23- self .__line = line
24-
25- @staticmethod
26- def parse (line : str ) -> "DiffLine" :
27- return DiffLine (line )
28-
29- @property
30- def code (self ) -> DiffLineCode | None :
31- if self .__line is None :
32- return None
33-
34- match self .__line [:2 ]:
35- case "+ " :
36- return DiffLineCode .ADDED
37- case "- " :
38- return DiffLineCode .REMOVED
39- case " " :
40- return DiffLineCode .COMMON
41- case "? " :
42- return DiffLineCode .MISSING
43-
44- @property
45- def line (self ) -> str | None :
46- if self .__line is None :
47- return None
48-
49- return self .__line [2 :]
50-
51-
5216@dataclass
5317class DiffChange :
5418 left : List [int ]
@@ -68,7 +32,7 @@ class Diff:
6832
6933# Parser inspired by https://github.com/yebrahim/difflibparser/blob/master/difflibparser.py
7034class DiffParser :
71- def __init__ (self , left_text , right_text ):
35+ def __init__ (self , left_text : List [ str ] , right_text : List [ str ] ):
7236 self .__left_text = left_text
7337 self .__right_text = right_text
7438 self .__diff = list (difflib .ndiff (self .__left_text , self .__right_text ))
@@ -80,6 +44,7 @@ def iter_diffs(self) -> Generator[Diff, Any, Any]:
8044 diff_line = DiffLine .parse (current_line )
8145 code = diff_line .code
8246 diff = Diff (code = DiffCode .SAME , line = diff_line .line )
47+
8348 if code == DiffLineCode .ADDED :
8449 diff .code = DiffCode .RIGHT_ONLY
8550 elif code == DiffLineCode .REMOVED :
@@ -92,6 +57,7 @@ def iter_diffs(self) -> Generator[Diff, Any, Any]:
9257 diff .right_changes = change .right
9358 diff .newline = change .newline
9459 self .__line_no = change .skip_lines
60+
9561 self .__line_no += 1
9662 yield diff
9763
@@ -103,6 +69,9 @@ def __get_incremental_change(self, line_no: int) -> DiffChange | None:
10369 for i in range (4 )
10470 ]
10571
72+ [_ , b , c , d ] = lines
73+
74+ # This represents the case where both additions and removals are present in the edit
10675 pattern_a = [
10776 DiffLineCode .REMOVED ,
10877 DiffLineCode .MISSING ,
@@ -111,27 +80,29 @@ def __get_incremental_change(self, line_no: int) -> DiffChange | None:
11180 ]
11281 if self .__match_pattern (lines , pattern_a ):
11382 return DiffChange (
114- left = [i for (i , c ) in enumerate (lines [ 1 ] .line ) if c in ["-" , "^" ]],
115- right = [i for (i , c ) in enumerate (lines [ 3 ] .line ) if c in ["+" , "^" ]],
116- newline = lines [ 2 ] .line ,
83+ left = [i for (i , c ) in enumerate (b .line ) if c in ["-" , "^" ]],
84+ right = [i for (i , c ) in enumerate (d .line ) if c in ["+" , "^" ]],
85+ newline = c .line ,
11786 skip_lines = 3 ,
11887 )
11988
89+ # This represents the case where only additions are present in the edit
12090 pattern_b = [DiffLineCode .REMOVED , DiffLineCode .ADDED , DiffLineCode .MISSING ]
12191 if self .__match_pattern (lines , pattern_b ):
12292 return DiffChange (
12393 left = [],
124- right = [i for (i , c ) in enumerate (lines [ 2 ] .line ) if c in ["+" , "^" ]],
125- newline = lines [ 1 ] .line ,
94+ right = [i for (i , c ) in enumerate (c .line ) if c in ["+" , "^" ]],
95+ newline = b .line ,
12696 skip_lines = 2 ,
12797 )
12898
99+ # This represents the case where only removals are present in the edit
129100 pattern_c = [DiffLineCode .REMOVED , DiffLineCode .MISSING , DiffLineCode .ADDED ]
130101 if self .__match_pattern (lines , pattern_c ):
131102 return DiffChange (
132- left = [i for (i , c ) in enumerate (lines [ 1 ] .line ) for c in ["-" , "^" ]],
103+ left = [i for (i , c ) in enumerate (b .line ) if c in ["-" , "^" ]],
133104 right = [],
134- newline = lines [ 1 ] .line ,
105+ newline = c .line ,
135106 skip_lines = 2 ,
136107 )
137108
0 commit comments