Path 1: 8 calls (0.62)

['hello', 'andr\udce9'] (3) ['\udca3odz is a city in Poland.'] (2) 'one' (2) ['one\n', 'two\n', 'three\n', 'four\n'] (1)

['hello', 'andr\udcc3\udca9'] (3) ['\udcc5\udc81odz is a city in Poland.'] (2) 'two' (2) ['zero\n', 'one\n', 'tree\n', 'four\n'] (1)

'Original' (3) 'a' (2) '\udcb3odz.txt' (2) '' (1)

'Current' (3) 'b' (2) '\udcc5\udc82odz.txt' (2) '' (1)

'' (5) '2005' (1) '2005-03-18' (1) '2005-01-26 23:30:50' (1)

'' (5) '2013' (1) '2005-03-19' (1) '2010-04-02 10:20:52' (1)

3 (8)

'\n' (6) '' (2)

'***************\n' (6) ' hello' (6) ' o' (4) '*** 1,2 ****\n' (3) '! andr\udce9' (3) '--- 1,2 ----\n' (3) '! andr\udcc3\udca9' (3) '*** 1 ****\n' (...

GeneratorExit (8)

1def context_diff(a, b, fromfile='', tofile='',
2                 fromfiledate='', tofiledate='', n=3, lineterm='\n'):
3    r"""
4    Compare two sequences of lines; generate the delta as a context diff.
5
6    Context diffs are a compact way of showing line changes and a few
7    lines of context.  The number of context lines is set by 'n' which
8    defaults to three.
9
10    By default, the diff control lines (those with *** or ---) are
11    created with a trailing newline.  This is helpful so that inputs
12    created from file.readlines() result in diffs that are suitable for
13    file.writelines() since both the inputs and outputs have trailing
14    newlines.
15
16    For inputs that do not have trailing newlines, set the lineterm
17    argument to "" so that the output will be uniformly newline free.
18
19    The context diff format normally has a header for filenames and
20    modification times.  Any or all of these may be specified using
21    strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
22    The modification times are normally expressed in the ISO 8601 format.
23    If not specified, the strings default to blanks.
24
25    Example:
26
27    >>> print(''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(True),
28    ...       'zero\none\ntree\nfour\n'.splitlines(True), 'Original', 'Current')),
29    ...       end="")
30    *** Original
31    --- Current
32    ***************
33    *** 1,4 ****
34      one
35    ! two
36    ! three
37      four
38    --- 1,4 ----
39    + zero
40      one
41    ! tree
42      four
43    """
44
45    _check_types(a, b, fromfile, tofile, fromfiledate, tofiledate, lineterm)
46    prefix = dict(insert='+ ', delete='- ', replace='! ', equal='  ')
47    started = False
48    for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
49        if not started:
50            started = True
51            fromdate = '\t{}'.format(fromfiledate) if fromfiledate else ''
52            todate = '\t{}'.format(tofiledate) if tofiledate else ''
53            yield '*** {}{}{}'.format(fromfile, fromdate, lineterm)
54            yield '--- {}{}{}'.format(tofile, todate, lineterm)
55
56        first, last = group[0], group[-1]
57        yield '***************' + lineterm
58
59        file1_range = _format_range_context(first[1], last[2])
60        yield '*** {} ****{}'.format(file1_range, lineterm)
61
62        if any(tag in {'replace', 'delete'} for tag, _, _, _, _ in group):
63            for tag, i1, i2, _, _ in group:
64                if tag != 'insert':
65                    for line in a[i1:i2]:
66                        yield prefix[tag] + line
67
68        file2_range = _format_range_context(first[3], last[4])
69        yield '--- {} ----{}'.format(file2_range, lineterm)
70
71        if any(tag in {'replace', 'insert'} for tag, _, _, _, _ in group):
72            for tag, _, _, j1, j2 in group:
73                if tag != 'delete':
74                    for line in b[j1:j2]:
75                        yield prefix[tag] + line
            

Path 2: 3 calls (0.23)

['hello', 'andr\udce9'] (3)

['hello', 'andr\udce9'] (3)

'a' (2) '' (1)

'a' (2) '' (1)

'' (2) '2005' (1)

'' (2) '2013' (1)

3 (3)

'\n' (3)

1def context_diff(a, b, fromfile='', tofile='',
2                 fromfiledate='', tofiledate='', n=3, lineterm='\n'):
3    r"""
4    Compare two sequences of lines; generate the delta as a context diff.
5
6    Context diffs are a compact way of showing line changes and a few
7    lines of context.  The number of context lines is set by 'n' which
8    defaults to three.
9
10    By default, the diff control lines (those with *** or ---) are
11    created with a trailing newline.  This is helpful so that inputs
12    created from file.readlines() result in diffs that are suitable for
13    file.writelines() since both the inputs and outputs have trailing
14    newlines.
15
16    For inputs that do not have trailing newlines, set the lineterm
17    argument to "" so that the output will be uniformly newline free.
18
19    The context diff format normally has a header for filenames and
20    modification times.  Any or all of these may be specified using
21    strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
22    The modification times are normally expressed in the ISO 8601 format.
23    If not specified, the strings default to blanks.
24
25    Example:
26
27    >>> print(''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(True),
28    ...       'zero\none\ntree\nfour\n'.splitlines(True), 'Original', 'Current')),
29    ...       end="")
30    *** Original
31    --- Current
32    ***************
33    *** 1,4 ****
34      one
35    ! two
36    ! three
37      four
38    --- 1,4 ----
39    + zero
40      one
41    ! tree
42      four
43    """
44
45    _check_types(a, b, fromfile, tofile, fromfiledate, tofiledate, lineterm)
46    prefix = dict(insert='+ ', delete='- ', replace='! ', equal='  ')
47    started = False
48    for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
49        if not started:
50            started = True
51            fromdate = '\t{}'.format(fromfiledate) if fromfiledate else ''
52            todate = '\t{}'.format(tofiledate) if tofiledate else ''
53            yield '*** {}{}{}'.format(fromfile, fromdate, lineterm)
54            yield '--- {}{}{}'.format(tofile, todate, lineterm)
55
56        first, last = group[0], group[-1]
57        yield '***************' + lineterm
58
59        file1_range = _format_range_context(first[1], last[2])
60        yield '*** {} ****{}'.format(file1_range, lineterm)
61
62        if any(tag in {'replace', 'delete'} for tag, _, _, _, _ in group):
63            for tag, i1, i2, _, _ in group:
64                if tag != 'insert':
65                    for line in a[i1:i2]:
66                        yield prefix[tag] + line
67
68        file2_range = _format_range_context(first[3], last[4])
69        yield '--- {} ----{}'.format(file2_range, lineterm)
70
71        if any(tag in {'replace', 'insert'} for tag, _, _, _, _ in group):
72            for tag, _, _, j1, j2 in group:
73                if tag != 'delete':
74                    for line in b[j1:j2]:
75                        yield prefix[tag] + line
            

Path 3: 2 calls (0.15)

list (1) ['hello'] (1)

['hello'] (1) list (1)

'' (2)

'' (2)

'' (2)

'' (2)

3 (2)

'\n' (2)

TypeError (2)

1def context_diff(a, b, fromfile='', tofile='',
2                 fromfiledate='', tofiledate='', n=3, lineterm='\n'):
3    r"""
4    Compare two sequences of lines; generate the delta as a context diff.
5
6    Context diffs are a compact way of showing line changes and a few
7    lines of context.  The number of context lines is set by 'n' which
8    defaults to three.
9
10    By default, the diff control lines (those with *** or ---) are
11    created with a trailing newline.  This is helpful so that inputs
12    created from file.readlines() result in diffs that are suitable for
13    file.writelines() since both the inputs and outputs have trailing
14    newlines.
15
16    For inputs that do not have trailing newlines, set the lineterm
17    argument to "" so that the output will be uniformly newline free.
18
19    The context diff format normally has a header for filenames and
20    modification times.  Any or all of these may be specified using
21    strings for 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
22    The modification times are normally expressed in the ISO 8601 format.
23    If not specified, the strings default to blanks.
24
25    Example:
26
27    >>> print(''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(True),
28    ...       'zero\none\ntree\nfour\n'.splitlines(True), 'Original', 'Current')),
29    ...       end="")
30    *** Original
31    --- Current
32    ***************
33    *** 1,4 ****
34      one
35    ! two
36    ! three
37      four
38    --- 1,4 ----
39    + zero
40      one
41    ! tree
42      four
43    """
44
45    _check_types(a, b, fromfile, tofile, fromfiledate, tofiledate, lineterm)
46    prefix = dict(insert='+ ', delete='- ', replace='! ', equal='  ')
47    started = False
48    for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n):
49        if not started:
50            started = True
51            fromdate = '\t{}'.format(fromfiledate) if fromfiledate else ''
52            todate = '\t{}'.format(tofiledate) if tofiledate else ''
53            yield '*** {}{}{}'.format(fromfile, fromdate, lineterm)
54            yield '--- {}{}{}'.format(tofile, todate, lineterm)
55
56        first, last = group[0], group[-1]
57        yield '***************' + lineterm
58
59        file1_range = _format_range_context(first[1], last[2])
60        yield '*** {} ****{}'.format(file1_range, lineterm)
61
62        if any(tag in {'replace', 'delete'} for tag, _, _, _, _ in group):
63            for tag, i1, i2, _, _ in group:
64                if tag != 'insert':
65                    for line in a[i1:i2]:
66                        yield prefix[tag] + line
67
68        file2_range = _format_range_context(first[3], last[4])
69        yield '--- {} ----{}'.format(file2_range, lineterm)
70
71        if any(tag in {'replace', 'insert'} for tag, _, _, _, _ in group):
72            for tag, _, _, j1, j2 in group:
73                if tag != 'delete':
74                    for line in b[j1:j2]:
75                        yield prefix[tag] + line