tools/manual_diff.py: word-level diff of one manual between two doc folders. version-differences.md: the 20 manuals whose revision tables list only contact information were diffed; E10 and E30 have real content changes, the rest wording only. CLAUDE.md: re-checks use the full diff. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
"""Word-level diff of one CI Server manual between two releases (e.g. R1.03 and R1.05).
|
|
|
|
Catches changes the revision table does not mention (for example R1.04 edits listed only as
|
|
"Added contact information"). Needs `pdftotext` (Poppler / Git for Windows) on PATH.
|
|
|
|
Usage:
|
|
python tools/manual_diff.py <old_pdf_dir> <new_pdf_dir> IM36K10L40-01EN [more IMs] [-o out_dir]
|
|
|
|
Prints one block per change: [replace]/[insert]/[delete] with old (-) and new (+) words.
|
|
Page footers, edition lines and dates are removed first, so only text changes remain.
|
|
Writes nothing into the repo; with -o it saves <IM>.diff.txt files in out_dir.
|
|
"""
|
|
import difflib
|
|
import os
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
|
|
NOISE = re.compile(
|
|
r'IM ?36K\w+-01EN( \d+\w\w Edition)?( : [A-Za-z]+\.? ?\d+, ?\d+-00)?'
|
|
r'|\d+(st|nd|rd|th) Edition|Toc-\d+|Rev-\d+|App\.\d+-\d+|\b\d+-\d+\b')
|
|
|
|
|
|
def words(pdf):
|
|
with tempfile.TemporaryDirectory() as d:
|
|
out = os.path.join(d, 'm.txt')
|
|
subprocess.run(['pdftotext', pdf, out], check=True)
|
|
text = open(out, encoding='utf-8', errors='replace').read()
|
|
return NOISE.sub(' ', text).split()
|
|
|
|
|
|
def diff(old_pdf, new_pdf):
|
|
a, b = words(old_pdf), words(new_pdf)
|
|
sm = difflib.SequenceMatcher(None, a, b, autojunk=False)
|
|
lines = []
|
|
for op, a1, a2, b1, b2 in sm.get_opcodes():
|
|
if op == 'equal':
|
|
continue
|
|
lines.append('[%s] at word %d\n - %s\n + %s' % (
|
|
op, a1, ' '.join(a[a1:a2]), ' '.join(b[b1:b2])))
|
|
return lines
|
|
|
|
|
|
def main(argv):
|
|
out_dir = None
|
|
if '-o' in argv:
|
|
i = argv.index('-o')
|
|
out_dir = argv[i + 1]
|
|
del argv[i:i + 2]
|
|
if len(argv) < 3:
|
|
sys.exit(__doc__)
|
|
old_dir, new_dir, ims = argv[0], argv[1], argv[2:]
|
|
for im in ims:
|
|
old_pdf = os.path.join(old_dir, im + '.pdf')
|
|
new_pdf = os.path.join(new_dir, im + '.pdf')
|
|
if not os.path.exists(old_pdf):
|
|
print('=====', im, ': new manual (no old edition)')
|
|
continue
|
|
lines = diff(old_pdf, new_pdf)
|
|
report = '\n'.join(lines)
|
|
print('=====', im, ':', len(lines), 'changes')
|
|
if out_dir:
|
|
os.makedirs(out_dir, exist_ok=True)
|
|
open(os.path.join(out_dir, im + '.diff.txt'), 'w', encoding='utf-8').write(report)
|
|
else:
|
|
print(report)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main(sys.argv[1:])
|