whatthepatch
What The Patch is a Python library for parsing and applying patch files. It is currently at version 1.0.7, with its latest release on November 16, 2024. While the functions are stable and reliable, the project has historically had limited active development from the maintainer, though pull requests are considered and released.
Warnings
- breaking Version 1.0.0 dropped support for Python 2 and Python 3.4. Users on these older Python versions must use `whatthepatch<1.0.0` or upgrade their Python environment.
- gotcha An incorrect regular expression matching `diffcmd` was fixed in version 1.0.7. Older versions might misinterpret diff commands in some patch files, leading to parsing errors.
- gotcha Issues with parsing binary diffs and context diffs were fixed in versions 1.0.5 and 1.0.1 respectively. Users dealing with these specific patch formats in older library versions might encounter parsing failures.
- gotcha The project's maintainer notes limited active development; while pull requests are considered, direct issue fixes by the maintainer are not guaranteed. Users encountering bugs may need to contribute fixes.
- gotcha Open issues exist regarding the parser not discarding 'a/' and 'b/' prefixes in paths for certain Git patches (issue #43) and incorrect parsing of colored diffs (issue #28). These might affect specific Git patch workflows or diff outputs.
Install
-
pip install whatthepatch
Imports
- whatthepatch
import whatthepatch
- parse_patch
from whatthepatch import parse_patch
- apply_diff
from whatthepatch import apply_diff
Quickstart
import whatthepatch
import io
patch_content = """--- lao\t2012-12-26 23:16:54.000000000 -0600
+++ tzu\t2012-12-26 23:16:50.000000000 -0600
@@ -1,7 +1,6 @@
-The Way that can be told of is not the eternal Way;
-The name that can be named is not the eternal name.
The Nameless is the origin of Heaven and Earth;
-The Named is the mother of all things.
+The named is the mother of all things.
Therefore let there always be non-being, so we may see their subtlety,
And let there always be being,
@@ -9,3 +8,6 @@
The two are the same,
But after they are produced,
they have different names.
+They both may be called deep and profound.
+Deeper and more profound,
+The door of all subtleties!"""
original_file_content = """The Way that can be told of is not the eternal Way;
The name that can be named is not the eternal name.
The Nameless is the origin of Heaven and Earth;
The Named is the mother of all things.
Therefore let there always be non-being, so we may see their subtlety,
And let there always be being,
The two are the same,
But after they are produced,
they have different names."""
# Parse the patch
print("--- Parsing Patch ---")
patches = list(whatthepatch.parse_patch(patch_content))
for diff in patches:
print(f"Diff for file: {diff.header.old_path} -> {diff.header.new_path}")
for change in diff.changes:
print(f" Change: old={change.old}, new={change.new}, line='{change.line.strip()}'")
# Apply the patch (example for the first diff in the patch)
if patches:
first_diff = patches[0]
print("\n--- Applying Patch ---")
# Simulate reading the original file lines
original_lines = original_file_content.splitlines(keepends=True)
try:
patched_lines = whatthepatch.apply_diff(first_diff, original_lines)
print("Patch applied successfully. New content:")
print("".join(patched_lines))
except whatthepatch.exceptions.PatchException as e:
print(f"Failed to apply patch: {e}")