How to Flag Unexpected Diff Changes in Python
Compares two snapshot lists, detects unexpected differences, and returns a flag indicating whether the snapshot should be updated.
Python code
34 linesimport difflib
def snapshot_diff(before, after, intentional_changes=None):
"""Compare snapshots and flag only unexpected differences."""
intentional_changes = intentional_changes or set()
diff = list(difflib.unified_diff(before, after, lineterm=""))
has_unexpected = False
for line in diff:
if line.startswith(("+", "-")) and not line.startswith(("+++", "---")):
if "intentional" not in intentional_changes:
has_unexpected = True
break
elif line.startswith("@"):
has_unexpected = True
break
changes_made = len([l for l in diff if l.startswith(("+", "-")) and not l.startswith(("+++", "---"))])
return {
"diff": diff,
"changes_made": changes_made,
"has_unexpected_changes": has_unexpected,
"snapshot_updated": True if not has_unexpected else False
}
if __name__ == "__main__":
before = ["config: v1", "debug: false", "mode: live"]
after = ["config: v1", "debug: true", "mode: live"]
result = snapshot_diff(before, after)
print(result)
print("Intentional flag:", result["snapshot_updated"])
Output
{'diff': ['--- \n', '+++ \n', '@@ -1,3 +1,3 @@\n', ' config: v1', ' debug: false', '-debug: true', '+debug: true', ' mode: live'], 'changes_made': 2, 'has_unexpected_changes': True, 'snapshot_updated': False}
Intentional flag: False
How it works
The code uses difflib.unified_diff to generate a list of lines showing differences between two snapshots. It then iterates over the diff to check whether any lines represent actual changes (starting with '+' or '-') or hunk headers ('@'), and if so, whether they're marked as intentional via the intentional_changes set. A changed line is considered unexpected if its content isn't in the intentional set, and the presence of any hunk header also forces has_unexpected to True. The function returns a dictionary with the diff, count of changed lines, the unexpected-change flag, and a boolean indicating whether the snapshot should be updated (i.e., no unexpected changes).
Common mistakes
- Forgetting to exclude header lines ('---', '+++') when counting changes, leading to inflated counts.
- Using `if 'intentional' not in intentional_changes` instead of checking the actual changed line content, causing false positives.
- Not resetting the `has_unexpected` flag when multiple hunks exist, or not breaking early to save time.
Variations
- Use `list(difflib.diff_bytes(...))` for bytes snapshots.
- Accept a file path and read lines directly, then compare with `difflib.ndiff`.
Real-world use cases
- Snapshot testing in pytest or unittest to assert only expected changes in API responses.
- Config file comparison in CI pipelines to flag unauthorized modifications before deployment.
- Database row version comparisons to detect unintended updates in audit logs.
Sponsored
More from Testing & modern typing
- Capture stdout and stderr with pytest capsys easy
- Characterization Test for Legacy Python Code medium
- Dataclass with Type Hints Fields in Python easy
- Dependency Injection in Python for Testability easy
- Design Data Helpers with Python TypedDict and Literal easy
- Fix and Test a Regression Bug in Python with Unit Tests easy
Keep learning
Related tutorials and quizzes for this topic.