def unified_diff_ignore_space( a, b, fromfile='', tofile='', fromfiledate='', tofiledate='', n=3, lineterm='\n'): 'reduce all consecutive spaces into single, compare, and print using original lines. all else - same' from difflib import SequenceMatcher, _format_range_unified aa = [ re_spaces.sub(' ', x) for x in a] bb = [ re_spaces.sub(' ', x) for x in b] started = False for group in SequenceMatcher(None,aa,bb).get_grouped_opcodes(n): if not started: started = True fromdate = '\t{}'.format(fromfiledate) if fromfiledate else '' todate = '\t{}'.format(tofiledate) if tofiledate else '' yield '--- {}{}{}'.format(fromfile, fromdate, lineterm) yield '+++ {}{}{}'.format(tofile, todate, lineterm) first, last = group[0], group[-1] file1_range = _format_range_unified(first[1], last[2]) file2_range = _format_range_unified(first[3], last[4]) yield '@@ -{} +{} @@{}'.format(file1_range, file2_range, lineterm) for tag, i1, i2, j1, j2 in group: if tag == 'equal': for line in a[i1:i2]: yield ' ' + line continue if tag in {'replace', 'delete'}: for line in a[i1:i2]: yield '-' + line if tag in {'replace', 'insert'}: for line in b[j1:j2]: yield '+' + line
def unified_diff(a, b, fromfile='', tofile='', fromfiledate='', tofiledate='', n=1, lineterm='\n', isjunk=None): """Modified version of difflib.unified_diff with isjunk argument support. """ started = False matcher = difflib.SequenceMatcher(isjunk, a, b, autojunk=False) for group in matcher.get_grouped_opcodes(n): if not started: started = True fromdate = '\t{}'.format(fromfiledate) if fromfiledate else '' todate = '\t{}'.format(tofiledate) if tofiledate else '' yield '--- {}{}{}'.format(fromfile, fromdate, lineterm) yield '+++ {}{}{}'.format(tofile, todate, lineterm) first, last = group[0], group[-1] file1_range = difflib._format_range_unified(first[1], last[2]) file2_range = difflib._format_range_unified(first[3], last[4]) group_lines = [] group_lines.append('@@ -{} +{} @@{}'.format(file1_range, file2_range, lineterm)) keep_group = False for tag, i1, i2, j1, j2 in group: lines = [] if tag == 'equal': for line in a[i1:i2]: lines.append(' ' + line) group_lines.extend(lines) continue if tag in {'replace', 'delete'}: for line in a[i1:i2]: lines.append('-' + line) if tag in {'replace', 'insert'}: for line in b[j1:j2]: if line in matcher.bjunk: lines = None break keep_group = True lines.append('+' + line) if lines is not None: group_lines.extend(lines) if keep_group: yield from group_lines
def unified_diff(a, b, n=3, lineterm='\n'): r""" simmilar to the original difflib.unified_diff except: - no fromfile/tofile and no fromfiledate/tofiledate info lines - newline before diff control lines and not after Example: >>> for line in unified_diff('one two three four'.split(), ... 'zero one tree four'.split(), lineterm=''): ... print line # doctest: +NORMALIZE_WHITESPACE @@ -1,4 +1,4 @@ +zero one -two -three +tree four """ started = False for group in difflib.SequenceMatcher(None, a, b).get_grouped_opcodes(n): first, last = group[0], group[-1] try: file1_range = difflib._format_range_unified(first[1], last[2]) file2_range = difflib._format_range_unified(first[3], last[4]) except AttributeError: # difflib._format_range_unified() is new in python 2.7 # see also: https://github.com/jedie/django-reversion-compare/issues/5 i1, i2, j1, j2 = first[1], last[2], first[3], last[4] file1_range = "%i,%i" % (i1 + 1, i2 - i1) file2_range = "%i,%i" % (j1 + 1, j2 - j1) if not started: started = True yield '@@ -{} +{} @@'.format(file1_range, file2_range) else: yield '{}@@ -{} +{} @@'.format(lineterm, file1_range, file2_range) for tag, i1, i2, j1, j2 in group: if tag == 'equal': for line in a[i1:i2]: yield ' ' + line continue if tag in ('replace', 'delete'): for line in a[i1:i2]: yield '-' + line if tag in ('replace', 'insert'): for line in b[j1:j2]: yield '+' + line
def format_range_unified(start, stop): """ Convert range to the "ed" format. DEPRECATED (Python 2.6 backport). Use difflib._format_range_unified instead. """ return _format_range_unified(start, stop)
def colored_unified_diff(a, b, fromfile='', tofile='', fromfiledate='', tofiledate='', n=3, lineterm='\n'): difflib._check_types(a, b, fromfile, tofile, fromfiledate, tofiledate, lineterm) started = False for group in difflib.SequenceMatcher(None, a, b).get_grouped_opcodes(n): if not started: started = True fromdate = '\t{}'.format(fromfiledate) if fromfiledate else '' todate = '\t{}'.format(tofiledate) if tofiledate else '' yield wasabi.color('--- {}{}{}'.format(fromfile, fromdate, lineterm), fg=15) yield wasabi.color('+++ {}{}{}'.format(tofile, todate, lineterm), fg=15) first, last = group[0], group[-1] file1_range = difflib._format_range_unified(first[1], last[2]) file2_range = difflib._format_range_unified(first[3], last[4]) yield wasabi.color('@@ -{} +{} @@{}'.format(file1_range, file2_range, lineterm), fg="cyan") for tag, i1, i2, j1, j2 in group: if tag == 'equal': for line in a[i1:i2]: yield ' ' + line elif tag == 'delete': for line in a[i1:i2]: yield wasabi.color('-' + line, fg="red") elif tag == 'insert': for line in b[j1:j2]: yield wasabi.color('+' + line, fg="green") elif tag == 'replace': # ideally we do something intelligent here to highlight changed words for line in a[i1:i2]: yield wasabi.color('-' + line, fg="red") for line in b[j1:j2]: yield wasabi.color('+' + line, fg="green")
def unified_diff(a, b, n=3, lineterm='\n'): r""" simmilar to the original difflib.unified_diff except: - no fromfile/tofile and no fromfiledate/tofiledate info lines - newline before diff control lines and not after Example: >>> for line in unified_diff('one two three four'.split(), ... 'zero one tree four'.split(), lineterm=''): ... print line # doctest: +NORMALIZE_WHITESPACE @@ -1,4 +1,4 @@ +zero one -two -three +tree four """ started = False for group in difflib.SequenceMatcher(None, a, b).get_grouped_opcodes(n): first, last = group[0], group[-1] file1_range = difflib._format_range_unified(first[1], last[2]) file2_range = difflib._format_range_unified(first[3], last[4]) if not started: started = True yield '@@ -{0} +{1} @@'.format(file1_range, file2_range) else: yield '{0}@@ -{1} +{2} @@'.format(lineterm, file1_range, file2_range) for tag, i1, i2, j1, j2 in group: if tag == 'equal': for line in a[i1:i2]: yield ' ' + line continue if tag in ('replace', 'delete'): for line in a[i1:i2]: yield '-' + line if tag in ('replace', 'insert'): for line in b[j1:j2]: yield '+' + line
def unified_diff(a, b, n=3, lineterm="\n"): r""" simmilar to the original difflib.unified_diff except: - no fromfile/tofile and no fromfiledate/tofiledate info lines - newline before diff control lines and not after Example: >>> for line in unified_diff('one two three four'.split(), ... 'zero one tree four'.split(), lineterm=''): ... print(line) @@ -1,4 +1,4 @@ +zero one -two -three +tree four """ started = False for group in difflib.SequenceMatcher(None, a, b).get_grouped_opcodes(n): first, last = group[0], group[-1] file1_range = difflib._format_range_unified(first[1], last[2]) file2_range = difflib._format_range_unified(first[3], last[4]) if not started: started = True yield f"@@ -{file1_range} +{file2_range} @@" else: yield f"{lineterm}@@ -{file1_range} +{file2_range} @@" for tag, i1, i2, j1, j2 in group: if tag == "equal": for line in a[i1:i2]: yield " " + line continue if tag in ("replace", "delete"): for line in a[i1:i2]: yield "-" + line if tag in ("replace", "insert"): for line in b[j1:j2]: yield "+" + line
def get_header(self): """Provide header of unified diff.""" a_rng = difflib._format_range_unified(*self.a_rng) b_rng = difflib._format_range_unified(*self.b_rng) return '@@ -{} +{} @@{}'.format(a_rng, b_rng, '\n')
def update_event(self, inp=-1): self.set_output_val(0, difflib._format_range_unified(self.input(0), self.input(1)))