mrkeyoor.com_
Sat 08 Aug 20:59 UTC
PyPIDataupdated 08 Aug 2026

daff

Daff compares tables as rows and columns instead of treating them as lines of text. Given two related CSV, TSV, SQLite, or newline-delimited JSON datasets, its CLI can align records, show inserted, deleted, updated, and moved values, emit a machine-applicable tabular patch, render that patch as HTML, and perform three-way merges. The same Haxe codebase is translated into Python and several other languages. It is built for versions of the same table, not general object diffs or statistical comparison.

Verdict

Daff is excellent when a CSV deserves the kind of structural diff and merge that source code already gets. Use explicit keys and separate output files for automation; choose a dataframe comparator when types and numeric tolerances matter more than portable patches.

API stability4/5The command vocabulary covers diff, patch, merge, trim, render, copy, and git integration, and the README documents a stable highlighter table format used as both report and patch. Version 1.4.2 still supports translations across several languages from the same Haxe source. The Python package's Alpha classifier and generated library surface lower confidence for direct imports, so the CLI is the safer compatibility boundary to pin and test.
Docs4/5The README contains the complete CLI grammar and flags, supported formats, exit-code behavior, git setup, a full JavaScript library walkthrough, three-way comparison, patching, HTML rendering, language build instructions, format specifications, and links to class documentation and a live demo. Python-specific library examples are notably absent, and some linked background material and translation references are older, which makes the CLI much easier to adopt than the generated module.
Maintenance4/5Daff 1.4.2 was published to PyPI in May 2025, while the GitHub repository was pushed in May 2026, so source activity continued after the current Python release. GitHub reported about 920 stars and 47 open issues and PRs at the metadata snapshot. This is a smaller project with a multi-language release burden and an Alpha PyPI classifier, but the recent repository activity and current live demo argue against calling it abandoned.
Ecosystem3/5Daff's unusual strength is portability: one tabular diff model is translated to JavaScript, Python, Java, C#, C++, Ruby, and PHP, with an R wrapper and browser build also referenced. It integrates with git as a CSV diff and merge driver and can render HTML. The supported storage surface is narrow by modern data standards, and pandas, Polars, Arrow, Parquet, and warehouse-native workflows need conversion or a different comparator.

Use it if

  • You review versioned CSV or TSV files and ordinary line diffs make column changes unreadable
  • You need a tabular diff that can later be applied as a patch rather than a visual-only report
  • You need three-way merging for tables that share a common ancestor
  • You want the same diff format and behavior across command-line, browser, Python, and other language builds
Skip it if

Setup reality

`pip install daff` installs the Python translation and a `daff` command with no declared runtime dependencies. There is no service or config file, but useful results depend on telling the tool what a row means. For CSV, ordered comparison is the default; JSON-style inputs default to unordered. Supply one or more `--id` columns whenever a stable primary key exists, and use `--unordered` when file order is incidental. Without a trustworthy key, daff aligns similar rows heuristically, which is convenient for human review but risky as an automated migration decision. The CLI supports CSV, TSV, SQLite, and ndjson, not Parquet or Excel. SQLite inputs may need `--table`, and comparing renamed tables uses the documented `old:new` form. Diff output uses daff's highlighter table format, which is itself the patch; preserve it exactly if another step will apply it. `patch --inplace` and `merge --inplace` modify the target file, so CI should write to a separate output and compare before replacing source data. `--fail-if-diff` provides useful exit codes: 0 equal, 1 different, 2 error. Color defaults suit terminals but should be disabled for captured logs. The library API is cross-generated from Haxe and the README demonstrates JavaScript objects such as `TableView`, `CompareFlags`, and `HighlightPatch`; Python-heavy teams should prefer the well-documented CLI boundary unless they are willing to inspect the generated module and pin the release.

Patterns

Compare two CSV filescompare-csv-files

daff before.csv after.csv

CSV comparison treats row order as meaningful by default; add `--unordered` if ordering is incidental.

Save a diff as an applicable patchwrite-tabular-diff

daff --output changes.csv before.csv after.csv

The highlighter-format diff is also the patch input, so preserve its rows and marker columns.

Align rows by a primary keycompare-by-primary-key

daff diff --id customer_id before.csv after.csv

Repeat `--id` for a composite key; explicit stable keys are safer than heuristic row alignment.

Ignore a column during comparisonignore-volatile-column

daff diff --ignore updated_at --ignore exported_at before.csv after.csv

Ignored columns disappear from the comparison, so do not use this to hide fields that downstream patches must preserve deliberately.

Show only updated cells and rowsshow-update-only

daff diff --act update before.csv after.csv

Other accepted change filters include insert, delete, and column; filtering is for reporting, not a complete patch.

Ignore row ordercompare-unordered-data

daff diff --unordered --id id before.csv after.csv

Combine unordered comparison with a key so duplicate or similar rows do not align unpredictably.

Return a distinct CI exit code for differencesgate-ci-on-difference

daff diff --fail-if-diff --no-color expected.csv actual.csv

The documented statuses are 0 for equal, 1 for different, and 2 for a processing problem.

Apply a patch to a new output fileapply-patch-safely

daff patch before.csv changes.csv > after.csv

Avoid `--inplace` until the generated output has been checked; in-place mode modifies the source file.

Perform a three-way table mergemerge-three-versions

daff merge parent.csv ours.csv theirs.csv > merged.csv

The first file is the common ancestor; conflict quality depends on all branches being versions of that same table.

Render a saved diff as HTMLrender-html-report

daff render --output changes.html changes.csv

Use `--fragment` when embedding the table in an existing page and `--css` to generate a matching stylesheet.

Compare a named SQLite tablecompare-sqlite-table

daff diff --input-format sqlite --table customers old.db new.db

For a renamed table, the README documents `--table old_name:new_name`.

Install daff as git's CSV diff and merge handlerconfigure-git-csv-diffs

daff git csv

This changes repository or user git configuration; run `daff git` first to inspect the manual setup if shared policy matters.

Alternatives

PackageRegistryPick it when
csv-diffPyPIYou need a small Python CLI for key-based CSV and JSON differences without patch or merge machinery
datacompyPyPIYou compare pandas or Spark dataframes and need keyed mismatch reports with numeric tolerances
deepdiffPyPIYour data is nested Python or JSON objects rather than rectangular tables