Parser for Python's difflib output.
Built on top of https://github.com/yebrahim/difflibparser/blob/master/difflibparser.py
Key changes from above library:
- Using generator pattern instead of using iterator pattern when iterating over diffs
- Using
@dataclassover generic dictionaries to enforce strict typing - Using type annotations for strict typing
pip install difflib-parserfromdifflib_parserimportdifflib_parserparser=difflib_parser.DiffParser(["hello world"], ["hello world!"])
fordiffinparser.iter_diffs():
print(diff)classDiffCode(Enum):
SAME=0RIGHT_ONLY=1LEFT_ONLY=2CHANGED=3@dataclassclassDiff:
code: DiffCodeline: strleft_changes: List[int] |None=Noneright_changes: List[int] |None=Nonenewline: str|None=NoneA difflib output might look something like this:
>>>importdifflib>>>print("\n".join(list(difflib.ndiff(["hello world"], ["hola world"]))))
-helloworld
? ^^^+holaworld
? ^^The specifics of diff interpretation can be found in the documentation.
There are concretely four types of changes we are interested in:
- No change
- A new line is added
- An existing line is removed
- An existing line is edited
Given that the last two cases operate on existing lines, they will always be preceded by - . As such, we need to handle them delicately.
If an existing line is removed, it will not have any follow-up lines.
If an existing line is edited, it will have several follow-up lines that provide details on the values that have been changed.
From these follow-up lines, we can further case the changes made to a line:
- Only additions made (i.e.
"Hello world"->"Hello world!") - Only removals made (i.e.
"Hello world"->"Hllo world") - Both additions and removals made (i.e.
"Hello world"->"Hola world!")
Each of them have their unique follow-up lines:
-,+,?
>>>print("\n".join(list(difflib.ndiff(["hello world"], ["hello world!"]))))
-helloworld+helloworld!
? +-,?,+
>>>print("\n".join(list(difflib.ndiff(["hello world"], ["hllo world"]))))
-helloworld
? -+hlloworld-,?,+,?
>>>print("\n".join(list(difflib.ndiff(["hello world"], ["helo world!"]))))
-helloworld
? -+heloworld!
? +As such, we have included them as separate patterns to process.