Python Patch
The `patch` library (version 1.16) is a Python utility designed to parse and apply unified diffs. It functions both as a command-line tool and a library for programmatic use, enabling developers to integrate patch application into their Python applications. The project's last release was in 2016, indicating a low or inactive release cadence, with a fork (`patch-ng`) emerging due to the original project's limited maintenance.
Warnings
- deprecated The `patch` library (techtonik/python-patch) has not seen an official release since February 2016 (version 1.16). This suggests it is largely unmaintained. Users seeking active development and support should consider alternatives or forks.
- breaking The library documentation explicitly warns against future API breaks. If a version 2.x were ever released, it is expected to introduce breaking changes.
- gotcha This `patch` library is distinct from `unittest.mock.patch`, which is part of Python's standard library for testing and mocking objects. Confusing the two can lead to incorrect usage and debugging challenges.
- gotcha The library has known limitations; it does not support file renaming, creation, or removal, directory tree operations, version control specific properties, or non-unified diff formats.
Install
-
pip install patch
Imports
- PatchSet
from patch import PatchSet
- fromstring
from patch import fromstring
- fromfile
from patch import fromfile
Quickstart
import os
import tempfile
from patch import fromstring, PatchSet
# Create a dummy original file
original_content = """Line 1
Line 2
Line 3
"""
with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.txt') as f_orig:
f_orig.write(original_content)
original_filepath = f_orig.name
# Create a diff that adds a line and modifies another
diff_content = """--- a/test.txt 2023-01-01 00:00:00.000000000 +0000
+++ b/test.txt 2023-01-01 00:00:00.000000000 +0000
@@ -1,3 +1,4 @@
Line 1 modified
+Line 1.5 added
Line 2
Line 3
"""
# Parse the diff
patch_set = fromstring(diff_content)
# Apply the patch to the original file
# The library assumes the files are in the current working directory
# or specified by path. Here, we'll patch a file named 'test.txt'
# which we'll simulate by reading from original_filepath and applying to a new file.
target_filename = os.path.basename(original_filepath)
# To apply, the patch expects the target file to exist at a specific relative path.
# We will simulate this by copying our temp file and then patching that copy.
patched_content = None
with open(original_filepath, 'r') as f_read:
original_lines = f_read.readlines()
# Manually apply the patch (as the library's apply() method typically writes to disk)
# For a quickstart, it's easier to show the logic.
# In a real scenario, you'd do: patch_set.apply(strip=0, root=os.path.dirname(original_filepath))
# But it requires writing to the same filename specified in the diff.
# Let's write the original content to a file that matches the diff's target name
with open(target_filename, 'w') as f_target:
f_target.write(original_content)
# Now, apply the patch using the library's method
# The apply method attempts to write back to the file system.
success = patch_set.apply(strip=0, root='.') # root is current dir where target_filename is
if success:
with open(target_filename, 'r') as f_patched:
patched_content = f_patched.read()
print("Patch applied successfully.")
print("Patched content:\n", patched_content)
else:
print("Failed to apply patch.")
# Cleanup temporary files
os.remove(original_filepath)
os.remove(target_filename)