whatthepatch

A pure-Python library for parsing and applying unified, context, ed, and SCM-style patch/diff files.

Library
PyPI
v1.0.7
78stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
44/100Fair
Development Activity36
Maintenance20
Community48
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
59/100Fair
Architecture60
Code Quality62
Innovation58
Learning Curve55

whatthepatch is a lightweight, dependency-free Python library for reading and applying patch files. It parses an unusually broad range of diff formats — unified, context, normal, ed and RCS ed scripts, plus SCM-specific headers from Git, CVS, SVN, and Bazaar — into simple namedtuple structures your code can inspect directly, without shelling out to an external diff parser.

Beyond parsing, whatthepatch can also apply a parsed diff back onto source text, either through its own pure-Python line-splice implementation or by delegating to a system patch binary when byte-for-byte GNU patch semantics are required. It also understands Git’s binary patch format, decoding the base85-encoded, zlib-compressed payloads Git embeds for binary file changes.

What You Get

  • Parses unified, context, normal (“default”), ed, and RCS ed diff formats from a single parse_patch() call
  • Recognizes SCM-specific header conventions for Git, CVS, SVN, and Bazaar patches
  • Returns structured namedtuple objects (header, diff, Change) instead of raw strings
  • Applies a parsed diff back onto source text via a pure-Python algorithm or an optional system patch subprocess fallback
  • Decodes Git’s binary-diff format (base85 + zlib) for binary file changes

Common Use Cases

  • Extracting per-file line changes from a Git/SVN diff without spawning a subprocess
  • Building code-review or diff-viewer tooling that needs structured hunk data
  • Applying an incoming patch to in-memory text as part of an automated patching or bot workflow
  • Validating that a patch still applies cleanly to a given source file before committing it

Under The Hood

Architecture whatthepatch is organized as a small flat module set: patch.py handles multi-format diff parsing via a header/hunk regex-dispatch table, apply.py handles applying parsed diffs back to text (a pure-Python line-splice algorithm, with an optional subprocess fallback to the system patch binary), snippets.py holds two generic list-processing helpers (findall_regex, split_by_regex) shared by every parser, and exceptions.py defines a shallow exception hierarchy (WhatThePatchException -> HunkException/ApplyException -> ParseException/HunkApplyException/SubprocessException). There’s no class-based design — parsing is done through ordered lists of (regex, parser_function) tuples tried in priority order, a pattern repeated independently in parse_header, parse_diff, and parse_scm_header rather than centralized into a single registry. Diff data flows as namedtuples (header, diffobj, Change) threaded from parse_patch (which splits raw text into per-file diff blocks) into the format-specific header/hunk parsers and finally into apply_diff, which walks Change tuples and mutates a lines list by index. It’s a flat, single-package structure with no layering; because every format-specific parser pattern-matches on the same namedtuple shapes, changing those shapes or the core dispatch list would ripple through nearly every parser function.

Tech Stack The library is pure Python with zero third-party runtime dependencies, relying entirely on the standard library (re, base64, zlib, collections.namedtuple, os, subprocess, tempfile) and targeting a wide Python range per its classifiers. It’s packaged with modern setuptools via pyproject.toml (no setup.py), and the git binary-diff path decodes base85 payloads and inflates them with zlib. Local development uses a Pipfile for dependency pinning alongside optional Nix files for reproducible dev shells. Continuous integration runs a full matrix across major operating systems and several Python versions, installing a real patch binary so the subprocess fallback path gets exercised too, and publishes to PyPI automatically on GitHub Release.

Code Quality Tests are extensive relative to the codebase’s size, covering both parsing and application behavior with dedicated fixture diff files, and CI additionally executes the README’s embedded interactive examples as doctests on every push across every OS/Python combination in the matrix — a rigorous, low-ceremony testing setup for a small library. There is no type-hinting anywhere in the source and no static type checking is run. Error handling uses a small custom exception hierarchy with real semantic payloads (a parse exception carries its hunk index, a subprocess exception carries the process return code) rather than generic exceptions, though several parse paths silently return None on unrecognized input instead of raising. Naming is consistent snake_case throughout, functions stay small and single-purpose, and linting plus a comprehensive CI matrix with test-artifact uploads round out the picture.

API Design The public surface is intentionally tiny — two functions re-exported from the package root, one to parse patch text and one to apply a parsed diff — so getting started requires no configuration or boilerplate at all. It transparently supports an unusually wide span of legacy and modern diff formats behind that single parse entry point, broader coverage than most patch-parsing libraries typically offer, which usually stop at unified diff. The escape hatch to shell out to the real GNU patch binary when the pure-Python line-splice logic isn’t sufficient is a pragmatic, well-documented fallback rather than a leaky abstraction. Returned tuples are self-documenting via their field names but thinly documented in docstrings — the README’s interactive walkthroughs are the primary source of behavioral documentation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search