コード例 #1
0
    def compare(self):
        """
        example: 深圳市福田区华富路1018号  vs   深川市福田区华富路1018号
        :return:
        """

        # 全部转换为全角字符
        self.file = [
            l.replace(' ', '').replace(',', ',').replace(';', ';').replace(
                ':', ':').replace('(', '(').replace(')', ')')
            for l in self.file
        ]
        self.to_file = [
            l.replace(' ', '').replace(',', ',').replace(';', ';').replace(
                ':', ':').replace('(', '(').replace(')', ')')
            for l in self.to_file if l
        ]

        self.diff = difflib._mdiff(self.file,
                                   self.to_file,
                                   charjunk=is_char_junk)
        differences = {'changes': [], 'adds': [], 'subs': []}
        same_lines = []
        diff_lines = []

        for (_, line_a), (_,
                          line_b), is_different in self.diff:  # 拆包直接拆出需要的文字段落

            if not is_different:
                same_lines.append(line_b)
                self.chars_counter.update_appear_time(line_b)

            else:
                chgs, adds, subs, line_a, line_b = self.char_diffs(
                    line_a, line_b)
                if (not chgs) and (not adds) and (not subs):
                    same_lines.append(line_b)
                    self.chars_counter.update_appear_time(line_b)
                    continue

                differences['changes'] += chgs
                differences['adds'] += adds
                differences['subs'] += subs
                diff_lines.append((line_a, line_b))
                self.chars_counter.update_appear_time(line_b)
                self.chars_counter.update_miss(chgs, adds, subs)

        differences = {k: Counter(v) for k, v in differences.items()}
        self.chars_counter.summarize()

        s_no = len(same_lines)
        t_no = s_no + len(diff_lines)
        count_dict = {
            'number of same lines:': s_no,
            'number of total lines:': t_no,
            'ratio of same:': round(s_no / t_no, 4)
        }
        self.diff_lines = diff_lines
        self.count_dict = count_dict
        self.differences = differences
コード例 #2
0
ファイル: difflib_ext.py プロジェクト: kalyptorisk/daversy
def make_table(table_id, header, fromlines, tolines, context=None, versions=['old', 'new']):
    diff = list(difflib._mdiff(fromlines, tolines, context))
    if not diff:
        return None

    same = lambda c, l, r: (c, l[0], r[0], 'l', format_line(l[1]))
    add  = lambda c, l, r: (c, '',   r[0], 'r', format_line(r[1]))
    sub  = lambda c, l, r: (c, l[0], '',   'l', format_line(l[1]))

    html = TABLE_HEADER % tuple([table_id, header] + versions)
    for type, start, end in group_types(diff):
        if type == 'same':
            html += '<tbody>%s</tbody>\n' % \
                    merge_group(diff[start:end], same)

        elif type == 'add':
            html += '<tbody class="add">%s</tbody>\n' % \
                    merge_group(diff[start:end], add)

        elif type == 'del':
            html += '<tbody class="rem">%s</tbody>\n' % \
                    merge_group(diff[start:end], sub)

        elif type == 'mod':
            html += '<tbody class="mod">%s%s</tbody>\n' % \
                    (merge_group(diff[start:end], sub, end=False),
                     merge_group(diff[start:end], add, start=False))
        elif type == 'skipped':
            html += '<tbody class="skipped"><tr><th>...</th><th>...</th><td>&nbsp;</td></tr></tbody>\n'
    html += TABLE_FOOTER
    return html
コード例 #3
0
    def diff(self):
        if not self.field:
            return False

        if self.field.choices:
            # if a field is a choice field e.g. chars or ints used to represent a list of choices,
            # then its value is just that database, non-bilingual char/int value
            # fortunately model instances provide a hook for this
            func_name = f"get_{self.field.name}_display"
            last_original = getattr(self.last_original, func_name)()
            original = getattr(self.original, func_name)()
        else:
            last_original = getattr(self.last_original, self.field.name)
            original = getattr(self.original, self.field.name)

        if last_original is None:
            last_original = "empty"
        if original is None:
            original = "empty"
        # if isinstance(self.field,fields.MarkdownField):
        #   return (
        #     escape(last_original),
        #     escape(original)
        #   )
        mdiff = next(
            difflib._mdiff([escape(last_original)], [escape(original)]))
        return (
            Diff.replace_diff_tags_with_html(mdiff[0][1]),
            Diff.replace_diff_tags_with_html(mdiff[1][1]),
        )
コード例 #4
0
ファイル: nice_diff.py プロジェクト: jumasheff/redakcja
def html_diff_table(la, lb, context=None):
    all_changes = difflib._mdiff(la, lb)

    if context is None:
        changes = (format_changeset(*c) for c in all_changes)
    else:
        changes = []
        q = deque()
        after_change = False

        for changeset in all_changes:
            q.append(changeset)

            if changeset[2]:
                after_change = True
                if not after_change:
                    changes.append((0, '-----', 0, '-----', False))
                changes.extend(format_changeset(*c) for c in q)
                q.clear()
            else:
                if len(q) == context and after_change:
                    changes.extend(format_changeset(*c) for c in q)
                    q.clear()
                    after_change = False
                elif len(q) > context:
                    q.popleft()

    return render_to_string("wiki/diff_table.html", {
        "changes": changes,
    })
コード例 #5
0
ファイル: sourceimp_ida.py プロジェクト: raystyle/pigaios
    def make_file(self, lhs, rhs):
        rows = []
        for left, right, changed in difflib._mdiff(
                lhs, rhs, charjunk=difflib.IS_CHARACTER_JUNK):
            lno, ltxt = left
            rno, rtxt = right
            ltxt = self._stop_wasting_space(ltxt)
            rtxt = self._stop_wasting_space(rtxt)
            ltxt = self._trunc(ltxt, changed).replace(" ", "&nbsp;")
            rtxt = self._trunc(rtxt, changed).replace(" ", "&nbsp;")
            row = self._row_template % (str(lno), ltxt, str(rno), rtxt)
            rows.append(row)

        all_the_rows = "\n".join(rows)
        all_the_rows = all_the_rows.replace(
            "\x00+", '<span class="diff_add">').replace(
                "\x00-", '<span class="diff_sub">').replace(
                    "\x00^", '<span class="diff_chg">').replace(
                        "\x01", '</span>').replace("\t", 4 * "&nbsp;")

        res = self._html_template % {
            "style": self._style,
            "rows": all_the_rows
        }
        return res
コード例 #6
0
   def getDiffDetails(self, fromdesc='', todesc='', context=False, numlines=5, tabSize=8):

      # change tabs to spaces before it gets more difficult after we insert
      # markkup
      def expand_tabs(line):
         # hide real spaces
         line = line.replace(' ','\0')
         # expand tabs into spaces
         line = line.expandtabs(tabSize)
         # replace spaces from expanded tabs back into tab characters
         # (we'll replace them with markup after we do differencing)
         line = line.replace(' ','\t')
         return line.replace('\0',' ').rstrip('\n')

      self.fromlines = [expand_tabs(line) for line in self.fromlines]
      self.tolines = [expand_tabs(line) for line in self.tolines]

      # create diffs iterator which generates side by side from/to data
      if context:
         context_lines = numlines
      else:
         context_lines = None

      diffs = difflib._mdiff(self.fromlines, self.tolines, context_lines, linejunk=None, charjunk=difflib.IS_CHARACTER_JUNK)
      return list(diffs)
コード例 #7
0
    def getDiffDetails(self,
                       fromdesc='',
                       todesc='',
                       context=False,
                       numlines=5,
                       tabSize=8):
        # change tabs to spaces before it gets more difficult after we insert
        # markkup
        def expand_tabs(line):
            # hide real spaces
            line = line.replace(' ', '\0')
            # expand tabs into spaces
            line = line.expandtabs(tabSize)
            # replace spaces from expanded tabs back into tab characters
            # (we'll replace them with markup after we do differencing)
            line = line.replace(' ', '\t')
            return line.replace('\0', ' ').rstrip('\n')

        self.fromlines = [expand_tabs(line) for line in self.fromlines]
        self.tolines = [expand_tabs(line) for line in self.tolines]

        # create diffs iterator which generates side by side from/to data
        if context:
            context_lines = numlines
        else:
            context_lines = None

        diffs = difflib._mdiff(self.fromlines,
                               self.tolines,
                               context_lines,
                               linejunk=None,
                               charjunk=difflib.IS_CHARACTER_JUNK)
        return list(diffs)
コード例 #8
0
ファイル: diff2HtmlCompare.py プロジェクト: EmyTest/Doraemon
    def getDiffDetails(
        self,
        fromdesc='',
        todesc='',
        context=False,
        numlines=5,
        tabSize=8,
    ):
        def expand_tabs(line):
            line = line.replace(' ', '\0')
            line = line.expandtabs(tabSize)
            line = line.replace(' ', '\t')
            return line.replace('\0', ' ').rstrip('\n')

        self.fromlines = [expand_tabs(line) for line in self.fromlines]
        self.tolines = [expand_tabs(line) for line in self.tolines]

        # create diffs iterator which generates side by side from/to data

        if context:
            context_lines = numlines
        else:
            context_lines = None

        diffs = difflib._mdiff(self.fromlines,
                               self.tolines,
                               context_lines,
                               linejunk=None,
                               charjunk=difflib.IS_CHARACTER_JUNK)
        return list(diffs)
コード例 #9
0
def sidebyside(fromlines, tolines, context):
    """Generate side by side diff"""

    # for some reason mdiff chokes on \n's in input lines
    def _stripnl(line):
        return line.rstrip("\n")

    fromlines = list(map(_stripnl, fromlines))
    tolines = list(map(_stripnl, tolines))
    had_changes = 0

    gap = False
    for fromdata, todata, flag in difflib._mdiff(fromlines, tolines, context):
        if fromdata is None and todata is None and flag is None:
            gap = True
        else:
            from_item = _mdiff_split(flag, fromdata)
            to_item = _mdiff_split(flag, todata)
            had_changes = 1
            yield _item(gap=ezt.boolean(gap),
                        columns=(from_item, to_item),
                        type="intraline")
            gap = False
    if not had_changes:
        yield _item(type=_RCSDIFF_NO_CHANGES)
コード例 #10
0
def aligner(lines1, lines2):
    diffs = difflib._mdiff(lines1, lines2)
    fromlist, tolist, flaglist = [], [], []
    # pull from/to data and flags from mdiff style iterator
    itercount = 0
    for fromdata, todata, flag in diffs:
        try:
            # pad lists with "None" at empty lines to align both sides
            if todata[1].startswith('\0+') and fromdata[1].strip() == "":
                fromlist.append(
                    None
                )  # if todata has an extra line, stuff fromlist with None
            else:
                fromlist.append(fromdata[1])  # otherwise append line

            if fromdata[1].startswith('\0-') and todata[1].strip() == "":
                tolist.append(
                    None
                )  # if fromdata has an extra line, stuff tolist with None
            else:
                tolist.append(todata[1])  # otherwise append line

        except TypeError:
            # exceptions occur for lines where context separators go
            fromlist.append(None)
            tolist.append(None)
        flaglist.append(flag)

    #for l in fromlist:
    #    print([l])
    return fromlist, tolist, flaglist
コード例 #11
0
def gen_diff_counts(text1, text2):
    htmldiffer = difflib.HtmlDiff()
    htmldiffer._make_prefix()
    text1, text2 = htmldiffer._tab_newline_replace(text1, text2)
    diffs = difflib._mdiff(fromlines=text1, tolines=text2)
    add_count = 0
    beginwithadd = False
    endwithadd = False
    delete_count = 0
    beginwithdelete = False
    endwithdelete = False
    change_count = 0
    beginwithchange = False
    endwithchange = False
    for diff in diffs:
        print(diff)
        # print(diff[2])s
        if diff[2]:
            from_line = diff[0][1]
            to_line = diff[1][1]
            beg = ""
            if len(from_line) > 3:
                for i in range(1, len(from_line)):  # delete
                    if from_line[i - 1] == "\x00" and from_line[i] == "-":
                        beg = from_line[i]
                        if i == 1:
                            beginwithdelete = True
                    if from_line[i] == "\x01" and beg == "-":
                        if not endwithdelete or not beginwithdelete:
                            delete_count += 1
                        else:
                            endwithdelete = False
                        beg = ""
                        if i == len(from_line) - 1:
                            endwithdelete = True

            beg = ""
            if len(to_line) > 3:
                for i in range(1, len(to_line)):  # add change
                    if to_line[i - 1] == "\x00" and to_line[
                            i] == "+" or to_line[i] == "^":
                        beg = to_line[i]
                        if i == 1:
                            if beg == "+":
                                beginwithadd = True
                            if beg == "^":
                                beginwithchange = True
                    if to_line[i] == "\x01":
                        if beg == "^":
                            if not endwithchange or not beginwithchange:
                                change_count += 1
                            if i == len(to_line) - 1:
                                endwithchange = True
                        if beg == "+":
                            if not beginwithadd or not endwithadd:
                                add_count += 1
                            if i == len(to_line) - 1:
                                endwithadd = True
    return {"add": add_count, "delete": delete_count, "change": change_count}
コード例 #12
0
def count_diff(text1, text2):
    htmldiffer = difflib.HtmlDiff()
    htmldiffer._make_prefix()
    text1, text2 = htmldiffer._tab_newline_replace(text1, text2)
    diffs = difflib._mdiff(fromlines=text1, tolines=text2)
    # fromlist, tolist, flaglist = htmldiffer._collect_lines(diffs)
    # fromlist, tolist, flaglist, next_href, next_id = htmldiffer._convert_flags(
    #     fromlist, tolist, flaglist, context=False,numlines=5)
    # print(fromlist)
    # print(tolist)
    # for i in range(len(fromlist)):
    #     doc1 = pq(fromlist[i])
    #     print(doc1.text())
    # for i in range(len(tolist)):
    #     doc2 = pq(tolist[i])
    #     print(doc2.text())

    # print(flaglist)
    # print(next_href)
    # print(next_id)
    flags = []
    types = []
    for diff in diffs:
        print(diff)
        # print(diff[2])
        if diff[2]:
            f_line = diff[0][1]
            t_line = diff[1][1]
            if "\x00^" in f_line:
                flags.append("^")
            if "\x00-" in f_line:
                # print("-")
                flags.append("-")
            if "\x00+" in t_line:
                # print("+")
                flags.append("+")
        else:
            flags.append("&")
    add_count = 0
    delete_count = 0
    change_count = 0
    pre_flag = flags[0]
    if pre_flag == "+":
        add_count += 1
    elif pre_flag == "-":
        delete_count += 1
    elif pre_flag == "^":
        change_count += 1
    for i in range(1, len(flags)):
        now_page = flags[i]
        if now_page == "+" and now_page != pre_flag:
            add_count += 1
        elif now_page == "-" and now_page != pre_flag:
            delete_count += 1
        elif now_page == "^" and now_page != pre_flag:
            change_count += 1
        pre_flag = now_page
    return {"add": add_count, "delete": delete_count, "change": change_count}
コード例 #13
0
ファイル: diff.py プロジェクト: igorzakhar/35_diff_service
def get_diffs(a, b):
    fromlines = a.splitlines(keepends=False)
    tolines = b.splitlines(keepends=False)
    context_lines = None
    diffs = difflib._mdiff(fromlines,
                           tolines,
                           context_lines,
                           linejunk=None,
                           charjunk=difflib.IS_CHARACTER_JUNK)
    return list(diffs)
コード例 #14
0
 def diff_string_content_file(self):
     diff = difflib._mdiff(self.left_contents_lines,
                           self.right_contents_lines)
     diff = list(diff)
     json = ContentDiffResultBuilder(
         self.file_name, self.left_file_object.file_path,
         self.right_file_object.file_path,
         self.left_file_object.modification_time,
         self.right_file_object.modification_time, diff).get_data()
     self.save_diff_json(json)
     return json.get(COMPARE_RESULT_HAS_CHANGES)
コード例 #15
0
ファイル: icdiff.py プロジェクト: termicoder/termicoder-beta
    def make_table(self,
                   fromlines,
                   tolines,
                   fromdesc='',
                   todesc='',
                   context=False,
                   numlines=5):
        """Generates table of side by side comparison with change highlights

        Arguments:
        fromlines -- list of "from" lines
        tolines -- list of "to" lines
        fromdesc -- "from" file column header string
        todesc -- "to" file column header string
        context -- set to True for contextual differences (defaults to False
            which shows full differences).
        numlines -- number of context lines.  When context is set True,
            controls number of lines displayed before and after the change.
            When context is False, controls the number of lines to place
            the "next" link anchors before the next change (so click of
            "next" link jumps to just before the change).
        """
        if context:
            context_lines = numlines
        else:
            context_lines = None

        # change tabs to spaces before it gets more difficult after we insert
        # markup
        fromlines, tolines = self._tab_newline_replace(fromlines, tolines)

        if self.strip_trailing_cr or (self._all_cr_nl(fromlines)
                                      and self._all_cr_nl(tolines)):
            fromlines = self._strip_trailing_cr(fromlines)
            tolines = self._strip_trailing_cr(tolines)

        # create diffs iterator which generates side by side from/to data
        diffs = difflib._mdiff(fromlines,
                               tolines,
                               context_lines,
                               linejunk=self._linejunk,
                               charjunk=self._charjunk)

        # set up iterator to wrap lines that exceed desired width
        if self._wrapcolumn:
            diffs = self._line_wrapper(diffs)
        diffs = self._collect_lines(diffs)

        for left, right in self._generate_table(fromdesc, todesc, diffs):
            yield self.colorize("%s %s" %
                                (self._lpad(left, self.cols // 2 - 1),
                                 self._lpad(right, self.cols // 2 - 1)))
コード例 #16
0
ファイル: color_diff.py プロジェクト: mrzor/gcloud_sync_ssh
def pretty_diff(a, b, cols=None, fromdesc='', todesc='', context_lines=3):
    cols = terminal_width() if not cols else cols
    half_col = (
        cols //
        2) - 3 - 7  # 3 because of center ' | ', 7 because of line numbers

    a = [line.rstrip('\n') for line in a]
    b = [line.rstrip('\n') for line in b]
    table = _make_table(fromdesc, todesc, difflib._mdiff(a, b, context_lines))

    for linenum, left, right in table:
        text = _colorize(f"{_rpad(left, half_col)} | {_rpad(right, half_col)}")
        yield _add_line_numbers(linenum, text)
コード例 #17
0
def sbsdiff(a, b, linenumberwidth=4):
    """
    Compare two sequences of lines; generate the delta for display side by
    side.
    
    @param a first sequence of lines (list of strings)
    @param b second sequence of lines (list of strings)
    @param linenumberwidth width (in characters) of the linenumbers (integer)
    @return a generator yielding tuples of differences. The tuple is composed
        of strings as follows.
        <ul>
            <li>opcode -- one of e, d, i, r for equal, delete, insert,
                replace</li>
            <li>lineno a -- linenumber of sequence a</li>
            <li>line a -- line of sequence a</li>
            <li>lineno b -- linenumber of sequence b</li>
            <li>line b -- line of sequence b</li>
        </ul>
    """
    def removeMarkers(line):
        """
        Internal function to remove all diff markers.
        
        @param line line to work on (string)
        @return line without diff markers (string)
        """
        return line\
            .replace('\0+', "")\
            .replace('\0-', "")\
            .replace('\0^', "")\
            .replace('\1', "")

    linenumberformat = "{{0:{0:d}d}}".format(linenumberwidth)
    emptylineno = ' ' * linenumberwidth

    for (ln1, l1), (ln2, l2), flag in _mdiff(a, b, None, None,
                                             IS_CHARACTER_JUNK):
        if not flag:
            yield ('e', linenumberformat.format(ln1), l1,
                   linenumberformat.format(ln2), l2)
            continue
        if ln2 == "" and l2 == "\n":
            yield ('d', linenumberformat.format(ln1), removeMarkers(l1),
                   emptylineno, '\n')
            continue
        if ln1 == "" and l1 == "\n":
            yield ('i', emptylineno, '\n', linenumberformat.format(ln2),
                   removeMarkers(l2))
            continue
        yield ('r', linenumberformat.format(ln1), l1,
               linenumberformat.format(ln2), l2)
コード例 #18
0
ファイル: CompareDialog.py プロジェクト: chiamingyen/kmol2016
def sbsdiff(a, b, linenumberwidth=4):
    """
    Compare two sequences of lines; generate the delta for display side by
    side.
    
    @param a first sequence of lines (list of strings)
    @param b second sequence of lines (list of strings)
    @param linenumberwidth width (in characters) of the linenumbers (integer)
    @return a generator yielding tuples of differences. The tuple is composed
        of strings as follows.
        <ul>
            <li>opcode -- one of e, d, i, r for equal, delete, insert,
                replace</li>
            <li>lineno a -- linenumber of sequence a</li>
            <li>line a -- line of sequence a</li>
            <li>lineno b -- linenumber of sequence b</li>
            <li>line b -- line of sequence b</li>
        </ul>
    """
    def removeMarkers(line):
        """
        Internal function to remove all diff markers.
        
        @param line line to work on (string)
        @return line without diff markers (string)
        """
        return line\
            .replace('\0+', "")\
            .replace('\0-', "")\
            .replace('\0^', "")\
            .replace('\1', "")

    linenumberformat = "{{0:{0:d}d}}".format(linenumberwidth)
    emptylineno = ' ' * linenumberwidth
    
    for (ln1, l1), (ln2, l2), flag in _mdiff(a, b, None, None,
                                             IS_CHARACTER_JUNK):
        if not flag:
            yield ('e', linenumberformat.format(ln1), l1,
                   linenumberformat.format(ln2), l2)
            continue
        if ln2 == "" and l2 == "\n":
            yield ('d', linenumberformat.format(ln1), removeMarkers(l1),
                   emptylineno, '\n')
            continue
        if ln1 == "" and l1 == "\n":
            yield ('i', emptylineno, '\n',
                   linenumberformat.format(ln2), removeMarkers(l2))
            continue
        yield ('r', linenumberformat.format(ln1), l1,
               linenumberformat.format(ln2), l2)
コード例 #19
0
ファイル: page.py プロジェクト: happytk/moin
    def diff_content(self, from_text, to_text, message=u''):
        """Generate the HTML markup for a diff."""

        def infiniter(iterator):
            """Turn an iterator into an infinite one, padding it with None"""

            for i in iterator:
                yield i
            while True:
                yield None

        diff = difflib._mdiff(from_text.split('\n'), to_text.split('\n'))
        mark_re = re.compile('\0[-+^]([^\1\0]*)\1|([^\0\1])')
        yield message
        yield u'<pre class="diff">'
        for old_line, new_line, changed in diff:
            old_no, old_text = old_line
            new_no, new_text = new_line
            line_no = (new_no or old_no or 1) - 1
            if changed:
                yield u'<div class="change" id="line_%d">' % line_no
                old_iter = infiniter(mark_re.finditer(old_text))
                new_iter = infiniter(mark_re.finditer(new_text))
                old = old_iter.next()
                new = new_iter.next()
                buff = u''
                while old or new:
                    while old and old.group(1):
                        if buff:
                            yield werkzeug.escape(buff)
                            buff = u''
                        yield u'<del>%s</del>' % werkzeug.escape(old.group(1))
                        old = old_iter.next()
                    while new and new.group(1):
                        if buff:
                            yield werkzeug.escape(buff)
                            buff = u''
                        yield u'<ins>%s</ins>' % werkzeug.escape(new.group(1))
                        new = new_iter.next()
                    if new:
                        buff += new.group(2)
                    old = old_iter.next()
                    new = new_iter.next()
                if buff:
                    yield werkzeug.escape(buff)
                yield u'</div>'
            else:
                yield u'<div class="orig" id="line_%d">%s</div>' % (
                    line_no, werkzeug.escape(old_text))
        yield u'</pre>'
コード例 #20
0
def gen_html(filename, funcname):
    offset0 = lookup(filename, funcname, V0_MANIFEST)
    offset1 = lookup(filename, funcname, V1_MANIFEST)
    assert offset0 != -1 and offset1 != -1
    loc0 = gen_gcc(filename, funcname, V0_CODE, offset0, V0_BUILD, TMP_V0_GCC+EXT1)
    loc1 = gen_gcc(filename, funcname, V1_CODE, offset1, V1_BUILD, TMP_V1_GCC+EXT1)
    gum = check_output(['java', '-jar', '/home/wxjin11/gumtree/client/target/gumtree.jar', '-o', 'tag', TMP_V0_GCC, TMP_V1_GCC])
    # print gum
    gum_dict = parse_gum(gum)
    code0 = extract_code(filename, loc0, V0_CODE)
    code1 = extract_code(filename, loc1, V1_CODE)
    diff = list(difflib._mdiff(code0, code1))
    # print gum_dict
    merge_mark(gum_dict, diff, loc0, loc1)
コード例 #21
0
ファイル: sub.py プロジェクト: kiwitreekor/namuplant
 def _make_table(self, a, b):
     self.setRowCount(0)
     al, bl = [], []
     bn = 1
     for ar, br, flag in difflib._mdiff(a.splitlines(keepends=True),
                                        b.splitlines(keepends=True),
                                        context=2):
         if flag is None:
             self.insertRow(self.rowCount())
             self.setItem(self.rowCount() - 1, 0, self._table_item())
             self.setItem(self.rowCount() - 1, 1, self._table_item('...'))
             self.setItem(self.rowCount() - 1, 2, self._table_item('...'))
             self.setItem(self.rowCount() - 1, 3,
                          self._table_item('(생략)', center=False))
         else:
             an, at = ar
             bn, bt = br
             if flag:
                 if type(an) is int:
                     al.append([str(an), at])
                 if type(bn) is int:
                     bl.append([str(bn), bt])
             else:
                 self._insert_merged(
                     al, bl)  # flag가 True일 때 모아둔 al, bl을 표에 실제 입력
                 al, bl = [], []
                 self.insertRow(self.rowCount())
                 self.setItem(self.rowCount() - 1, 0, self._table_item())
                 self.setItem(self.rowCount() - 1, 1,
                              self._table_item(str(an)))
                 self.setItem(self.rowCount() - 1, 2,
                              self._table_item(str(bn)))
                 self.setItem(
                     self.rowCount() - 1, 3,
                     self._table_item((lambda x: x[:-1]
                                       if x.endswith('\n') else x)(at),
                                      center=False))
     self._insert_merged(al, bl)
     if self.rowCount() == 0:
         self.insertRow(0)
         self.setItem(0, 3, self._table_item('변경 사항이 없습니다.', False))
     elif type(bn) is int and bn < len(
             b.splitlines()):  # 맨 마지막에 생략 표시가 자동으로 안 됨
         self.insertRow(self.rowCount())
         self.setItem(self.rowCount() - 1, 0, self._table_item())
         self.setItem(self.rowCount() - 1, 1, self._table_item('...'))
         self.setItem(self.rowCount() - 1, 2, self._table_item('...'))
         self.setItem(self.rowCount() - 1, 3,
                      self._table_item('(생략)', center=False))
コード例 #22
0
ファイル: page.py プロジェクト: davestgermain/datta
    def diff_content(self, from_text, to_text, message=''):
        """Generate the HTML markup for a diff."""
        def infiniter(iterator):
            """Turn an iterator into an infinite one, padding it with None"""

            for i in iterator:
                yield i
            while True:
                yield None

        diff = difflib._mdiff(from_text.split('\n'), to_text.split('\n'))
        mark_re = re.compile('\0[-+^]([^\1\0]*)\1|([^\0\1])')
        yield message
        yield '<pre class="diff">'
        for old_line, new_line, changed in diff:
            old_no, old_text = old_line
            new_no, new_text = new_line
            line_no = (new_no or old_no or 1) - 1
            if changed:
                yield '<div class="change" id="line_%d">' % line_no
                old_iter = infiniter(mark_re.finditer(old_text))
                new_iter = infiniter(mark_re.finditer(new_text))
                old = next(old_iter)
                new = next(new_iter)
                buff = ''
                while old or new:
                    while old and old.group(1):
                        if buff:
                            yield werkzeug.escape(buff)
                            buff = ''
                        yield '<del>%s</del>' % werkzeug.escape(old.group(1))
                        old = next(old_iter)
                    while new and new.group(1):
                        if buff:
                            yield werkzeug.escape(buff)
                            buff = ''
                        yield '<ins>%s</ins>' % werkzeug.escape(new.group(1))
                        new = next(new_iter)
                    if new:
                        buff += new.group(2)
                    old = next(old_iter)
                    new = next(new_iter)
                if buff:
                    yield werkzeug.escape(buff)
                yield '</div>'
            else:
                yield '<div class="orig" id="line_%d">%s</div>' % (
                    line_no, werkzeug.escape(old_text))
        yield '</pre>'
コード例 #23
0
def html_diff(from_sequence, to_sequence, linejunk=None, charjunk=None):

    diffs = _mdiff(from_sequence,
                   to_sequence,
                   linejunk=linejunk,
                   charjunk=charjunk)

    from_list = []
    to_list = []

    for from_data, to_data, flag in diffs:
        from_list.append(_markup(_unescape(from_data[1])))
        to_list.append(_markup(_unescape(to_data[1])))

    return from_list, to_list
コード例 #24
0
ファイル: ydiff.py プロジェクト: kingsamchen/ydiff
    def mdiff(self):
        r"""The difflib._mdiff() function returns an interator which returns a
        tuple: (from line tuple, to line tuple, boolean flag)

        from/to line tuple -- (line num, line text)
            line num -- integer or None (to indicate a context separation)
            line text -- original line text with following markers inserted:
                '\0+' -- marks start of added text
                '\0-' -- marks start of deleted text
                '\0^' -- marks start of changed text
                '\1' -- marks end of added/deleted/changed text

        boolean flag -- None indicates context separation, True indicates
            either "from" or "to" line contains a change, otherwise False.
        """
        return difflib._mdiff(self._get_old_text(), self._get_new_text())
コード例 #25
0
ファイル: cdiff.py プロジェクト: albfan/cdiff
    def mdiff(self):
        r"""The difflib._mdiff() function returns an interator which returns a
        tuple: (from line tuple, to line tuple, boolean flag)

        from/to line tuple -- (line num, line text)
            line num -- integer or None (to indicate a context separation)
            line text -- original line text with following markers inserted:
                '\0+' -- marks start of added text
                '\0-' -- marks start of deleted text
                '\0^' -- marks start of changed text
                '\1' -- marks end of added/deleted/changed text

        boolean flag -- None indicates context separation, True indicates
            either "from" or "to" line contains a change, otherwise False.
        """
        return difflib._mdiff(self._get_old_text(), self._get_new_text())
コード例 #26
0
    def format_diff(self, fromlines, tolines, fromdesc='', todesc='', context=False, numlines=5, *, charset='utf-8'):
        self._make_prefix()

        # change tabs to spaces before it gets more difficult after we insert
        # markup
        fromlines, tolines = self._tab_newline_replace(fromlines, tolines)

        # create diffs iterator which generates side by side from/to data
        if context:
            context_lines = numlines
        else:
            context_lines = None
        diffs = difflib._mdiff(fromlines, tolines, context_lines, linejunk=self._linejunk,
                               charjunk=self._charjunk)

        return list(diffs)
コード例 #27
0
ファイル: idiff.py プロジェクト: jrdalpra/svnedge-console
def sidebyside(fromlines, tolines, context):
  """Generate side by side diff"""

  ### for some reason mdiff chokes on \n's in input lines
  line_strip = lambda line: line.rstrip("\n")
  fromlines = map(line_strip, fromlines)
  tolines = map(line_strip, tolines)

  gap = False
  for fromdata, todata, flag in difflib._mdiff(fromlines, tolines, context):
    if fromdata is None and todata is None and flag is None:
      gap = True
    else:
      from_item = _mdiff_split(flag, fromdata)
      to_item = _mdiff_split(flag, todata)
      yield _item(gap=ezt.boolean(gap), columns=(from_item, to_item))
      gap = False
コード例 #28
0
def gen_html(filename, funcname, o):
    S0 = sys.argv[1]
    S1 = sys.argv[2]
    #print S0,S1
    global V0_CODE, V1_CODE, V0_MANIFEST, V1_MANIFEST
    V0_CODE = '/tmp/' + S0 + '/'
    V1_CODE = '/tmp/' + S1 + '/'
    V0_MANIFEST = '/tmp/V-' + S0
    V1_MANIFEST = '/tmp/V-' + S1
    V0_BUILD = '/tmp/build-' + S0 + '-allno'
    V1_BUILD = '/tmp/build-' + S1 + '-allno'
    TMP_V0_GCC = '/tmp/tmp-' + S0 + '.c'
    TMP_V1_GCC = '/tmp/tmp-' + S1 + '.c'
    #print TMP_V0_GCC
    offset0 = lookup(filename, funcname, V0_MANIFEST)
    offset1 = lookup(filename, funcname, V1_MANIFEST)
    #print TMP_V0_GCC,TMP_V1_GCC
    if offset0 == -1 or offset1 == -1:
        print 'Your config is wrong!'
        return
    assert offset0 != -1 and offset1 != -1
    #    print("see2");
    #print V1_CODE;
    #   print offset1
    #  print V1_BUILD,TMP_V1_GCC+EXT1
    loc0 = gen_gcc(filename, funcname, V0_CODE, offset0, V0_BUILD,
                   TMP_V0_GCC + EXT1)
    loc1 = gen_gcc(filename, funcname, V1_CODE, offset1, V1_BUILD,
                   TMP_V1_GCC + EXT1)
    #    print ("see3");
    gum = check_output([
        'java', '-jar', '/usr/local/share/cg-rtl/lxr/gumtree.jar', '-o', 'tag',
        TMP_V0_GCC, TMP_V1_GCC
    ])
    #    print gum
    ret_gum = (gum != '-----\n')
    #    print ("see4");
    #print ret_gum
    gum_dict = parse_gum(gum)
    code0 = extract_code(filename, loc0, V0_CODE)
    code1 = extract_code(filename, loc1, V1_CODE)
    #  print code0,code1
    diff = list(difflib._mdiff(code0, code1))
    # print gum_dict
    ret_diff = merge_mark(gum_dict, diff, loc0, loc1, o)
    return ret_gum, ret_diff
コード例 #29
0
    def make_table(self, a, b, adesc=None, bdesc=None, context=5):
        """Make html table that displays side-by-side diff

        Arguments:
         - a -- list of text lines to be compared to b
         - b -- list of text lines to be compared to a
         - adesc -- description of the 'a' lines (e.g. filename)
         - bdesc -- description of the 'b' lines (e.g. filename)
         - context -- number of context lines to display

        Uses difflib._mdiff function to generate diff.
        """
        adesc = adesc or ''
        bdesc = bdesc or ''
        diff = difflib._mdiff(a, b, context=context)
        lines = [self._make_line(d) for d in diff]
        return self.table_tmpl % (adesc, bdesc, '\n'.join(lines))
コード例 #30
0
def sidebyside(fromlines, tolines, context):
    """Generate side by side diff"""

    ### for some reason mdiff chokes on \n's in input lines
    line_strip = lambda line: line.rstrip("\n")
    fromlines = map(line_strip, fromlines)
    tolines = map(line_strip, tolines)

    gap = False
    for fromdata, todata, flag in difflib._mdiff(fromlines, tolines, context):
        if fromdata is None and todata is None and flag is None:
            gap = True
        else:
            from_item = _mdiff_split(flag, fromdata)
            to_item = _mdiff_split(flag, todata)
            yield _item(gap=ezt.boolean(gap), columns=(from_item, to_item))
            gap = False
コード例 #31
0
ファイル: icdiff.py プロジェクト: sharad/rc
    def make_table(self, fromlines, tolines, fromdesc='', todesc='',
                   context=False, numlines=5):
        """Generates table of side by side comparison with change highlights

        Arguments:
        fromlines -- list of "from" lines
        tolines -- list of "to" lines
        fromdesc -- "from" file column header string
        todesc -- "to" file column header string
        context -- set to True for contextual differences (defaults to False
            which shows full differences).
        numlines -- number of context lines.  When context is set True,
            controls number of lines displayed before and after the change.
            When context is False, controls the number of lines to place
            the "next" link anchors before the next change (so click of
            "next" link jumps to just before the change).
        """
        if context:
            context_lines = numlines
        else:
            context_lines = None

        # change tabs to spaces before it gets more difficult after we insert
        # markup
        fromlines, tolines = self._tab_newline_replace(fromlines, tolines)

        if self.strip_trailing_cr or (
                self._all_cr_nl(fromlines) and self._all_cr_nl(tolines)):
            fromlines = self._strip_trailing_cr(fromlines)
            tolines = self._strip_trailing_cr(tolines)

        # create diffs iterator which generates side by side from/to data
        diffs = difflib._mdiff(fromlines, tolines, context_lines,
                               linejunk=self._linejunk,
                               charjunk=self._charjunk)

        # set up iterator to wrap lines that exceed desired width
        if self._wrapcolumn:
            diffs = self._line_wrapper(diffs)
        diffs = self._collect_lines(diffs)

        for left, right in self._generate_table(fromdesc, todesc, diffs):
            yield self.colorize(
                "%s %s" % (self._lpad(left, self.cols // 2 - 1),
                           self._lpad(right, self.cols // 2 - 1)))
コード例 #32
0
ファイル: text_diff.py プロジェクト: GingerNg/P_Stack
 def text_diff(self, text1, text2):
     """
     文本比对
     :param text1:
     :param text2:
     :return:
     """
     htmldiffer = difflib.HtmlDiff()
     htmldiffer._make_prefix()
     text1, text2 = htmldiffer._tab_newline_replace(text1, text2)
     diffs = difflib._mdiff(fromlines=text1, tolines=text2)
     # if self._wrapcolumn:
     # diffs = htmldiffer._line_wrapper(diffs)
     # for diff in diffs:
     #     print(diff)
     # fromlist, tolist, flaglist = htmldiffer._collect_lines(diffs)
     # print(fromlist)
     return diffs
コード例 #33
0
ファイル: diff.py プロジェクト: uva-slp/pico
	def asTable(self):
		table = Table().addClass('diff-table')
		
		headers = Row().addCell(Th()).addCell(Th('Submission'))
		headers.addCell(Th()).addCell(Th('Solution'))
		table.addHeader(headers)

		num_changes = 0
		for diff in difflib._mdiff(self.fromlines, self.tolines):
			fromline, toline, hasChange = diff
			row = Row()

			# tag
			tag = ''
			if hasChange:
				num_changes+=1
				tag = str(Anchor().setName(num_changes).addClass('diff-anchor'))

			# from
			line_num, text = fromline
			line_num = line_num if len(str(line_num)) > 0 else '&nbsp;'
			row.addCell(Td(Div(tag+str(line_num)))
				.addClass('diff-cell')
				.addClass('line-number'))
			row.addCell(Td(self.prepare(0, text))
				.addClass('diff-cell')
				.addClass('line-text'))

			# to
			line_num, text = toline
			line_num = line_num if len(str(line_num)) > 0 else '&nbsp;'
			row.addCell(Td(Div(line_num))
				.addClass('diff-cell')
				.addClass('line-number'))
			row.addCell(Td(self.prepare(1, text))
				.addClass('diff-cell')
				.addClass('line-text'))

			table.addRow(row)

		return str(table), num_changes
コード例 #34
0
    def diff(self):
        left_diff = self.diff_array[0]
        right_diff = self.diff_array[1]

        if left_diff == "":
            self.left_result = ""
            self.right_result = RulesetDiffOneSideResultBuilder(
                right_diff).get_data()
        elif right_diff == "":
            self.right_result = ""
            self.left_result = RulesetDiffOneSideResultBuilder(
                left_diff).get_data()
        else:

            diff = difflib._mdiff(left_diff, right_diff)
            diff_list = list(diff)

            left_row_object = RulesetDiffResultBuilder(diff_list, True)
            right_row_object = RulesetDiffResultBuilder(diff_list, False)
            self.left_result = left_row_object.get_data()
            self.right_result = right_row_object.get_data()
コード例 #35
0
ファイル: idiff.py プロジェクト: gbremer/viewvc
def sidebyside(fromlines, tolines, context):
  """Generate side by side diff"""

  ### for some reason mdiff chokes on \n's in input lines
  line_strip = lambda line: line.rstrip("\n")
  fromlines = map(line_strip, fromlines)
  tolines = map(line_strip, tolines)
  had_changes = 0

  gap = False
  for fromdata, todata, flag in difflib._mdiff(fromlines, tolines, context):
    if fromdata is None and todata is None and flag is None:
      gap = True
    else:
      from_item = _mdiff_split(flag, fromdata)
      to_item = _mdiff_split(flag, todata)
      had_changes = 1
      yield _item(gap=ezt.boolean(gap), columns=(from_item, to_item), type="intraline")
      gap = False
  if not had_changes:
    yield _item(type=_RCSDIFF_NO_CHANGES)
コード例 #36
0
    def get_lines(self):
        # `readlines` because `difflib._mdiff` can't operate on a generator
        with open(self.old_filename, 'r') as old_file:
            old_lines = old_file.readlines()
        with open(self.new_filename, 'r') as new_file:
            new_lines = new_file.readlines()

        yield self._format_file_header()

        # Determine line number column widths; note: in some cases this is
        # unnecessarily wide (e.g. if changes only in beginning of a long file)
        old_ln_width = len(str(len(old_lines)))
        new_ln_width = len(str(len(new_lines)))

        mdiff = difflib._mdiff(old_lines, new_lines, context=self.context)

        # `mdiff` context separators don't have the metadata necessary to generate
        # git-diff-like hunk headers (`@@ -%d,%d @@` and `@@ +%d,%d @@`), so we
        # partition `mdiff` into hunks and process each one separately
        for hunk in self._get_hunks(mdiff):
            for line in self._format_hunk(hunk, old_ln_width, new_ln_width):
                yield line
コード例 #37
0
def getdiff(seq1list, seq2list, args, file1=file1, file2=file2, header=False):

    diff = ""
    if args.side:
        w, _ = terminal_size()
        numline = None
        if args.context:
            numline = args.lines
        diffs = difflib._mdiff(seq1list, seq2list, numline)
        width = int(w / 2.4) - 2
        if header:
            print(('\n{lside:{width}}{flag:^5}{rside:{width}}').format(
                lside=file1, rside=file2, width=width, flag=" "))

            # print(('\n{:%d.%d}{}{:%d.%d}' %
            #       (width, width, width, width)).format(file1, file2))
        for fl, tl, flag in diffs:
            flag = "!" if flag else " "

            if fl and tl:
                lside = str(fl[-1]).strip().replace('\0', "|").replace(
                    '\1', "|").replace("\n", "")
                rside = str(tl[-1]).strip().replace('\0', "|").replace(
                    '\1', "|").replace("\n", "")
                if args.color:
                    lside = lside.replace('|+', color.ADD).replace(
                        '|-',
                        color.DEL).replace('|^',
                                           color.SUB).replace('|', color.END)
                    rside = rside.replace('|+', color.ADD).replace(
                        '|-',
                        color.DEL).replace('|^',
                                           color.SUB).replace('|', color.END)

                if lside or rside:
                    line2 = ('{lside:{width}}{flag:^5}{rside:{width}}').format(
                        lside=lside, rside=rside, width=width, flag=flag)
                    print(line2)
コード例 #38
0
ファイル: text_diff.py プロジェクト: GingerNg/P_Stack
 def count_diff(self, text1, text2):
     """
     按字比对后统计
     :param text1:
     :param text2:
     :return:
     """
     htmldiffer = difflib.HtmlDiff()
     htmldiffer._make_prefix()
     text1, text2 = htmldiffer._tab_newline_replace(text1, text2)
     diffs = difflib._mdiff(fromlines=text1, tolines=text2)
     froms, tos, fsflags, flags = convert_diffs(diffs)
     flags = fsflags
     add_count = 0
     delete_count = 0
     change_count = 0
     pre_flag = flags[0]
     if pre_flag == "+":
         add_count += 1
     elif pre_flag == "-":
         delete_count += 1
     elif pre_flag == "^":
         change_count += 1
     for i in range(1, len(flags)):
         now_page = flags[i]
         if now_page == "+" and now_page != pre_flag:
             add_count += 1
         elif now_page == "-" and now_page != pre_flag:
             delete_count += 1
         elif now_page == "^" and now_page != pre_flag:
             change_count += 1
         pre_flag = now_page
     return {
         "add": add_count,
         "delete": delete_count,
         "change": change_count
     }
コード例 #39
0
def make_table(table_id,
               header,
               fromlines,
               tolines,
               context=None,
               versions=['old', 'new']):
    diff = list(difflib._mdiff(fromlines, tolines, context))
    if not diff:
        return None

    same = lambda c, l, r: (c, l[0], r[0], 'l', format_line(l[1]))
    add = lambda c, l, r: (c, '', r[0], 'r', format_line(r[1]))
    sub = lambda c, l, r: (c, l[0], '', 'l', format_line(l[1]))

    html = TABLE_HEADER % tuple([table_id, header] + versions)
    for type, start, end in group_types(diff):
        if type == 'same':
            html += '<tbody>%s</tbody>\n' % \
                    merge_group(diff[start:end], same)

        elif type == 'add':
            html += '<tbody class="add">%s</tbody>\n' % \
                    merge_group(diff[start:end], add)

        elif type == 'del':
            html += '<tbody class="rem">%s</tbody>\n' % \
                    merge_group(diff[start:end], sub)

        elif type == 'mod':
            html += '<tbody class="mod">%s%s</tbody>\n' % \
                    (merge_group(diff[start:end], sub, end=False),
                     merge_group(diff[start:end], add, start=False))
        elif type == 'skipped':
            html += '<tbody class="skipped"><tr><th>...</th><th>...</th><td>&nbsp;</td></tr></tbody>\n'
    html += TABLE_FOOTER
    return html
コード例 #40
0
ファイル: mdiff.py プロジェクト: seansay/ellen
def _get_mdiff(lines):
    ''' return difflib._mdiff generator '''
    old = _get_old(lines)
    new = _get_new(lines)
    return difflib._mdiff(old, new)
コード例 #41
0
 def test_mdiff_catch_stop_iteration(self):
     # Issue #33224
     self.assertEqual(
         list(difflib._mdiff(["2"], ["3"], 1)),
         [((1, '\x00-2\x01'), (1, '\x00+3\x01'), True)],
     )
コード例 #42
0
ファイル: icdiff.py プロジェクト: cpriest/BanBot
	def make_table( self, fromlines, tolines, fromdesc='', todesc='', context=False,
				   numlines=5 ):
		"""Returns table of side by side comparison with change highlights

		Arguments:
		fromlines -- list of "from" lines
		tolines -- list of "to" lines
		fromdesc -- "from" file column header string
		todesc -- "to" file column header string
		context -- set to True for contextual differences (defaults to False
			which shows full differences).
		numlines -- number of context lines.  When context is set True,
			controls number of lines displayed before and after the change.
			When context is False, controls the number of lines to place
			the "next" link anchors before the next change (so click of
			"next" link jumps to just before the change).
		"""

		# change tabs to spaces before it gets more difficult after we insert
		# markkup
		fromlines, tolines = self._tab_newline_replace( fromlines, tolines )

		# create diffs iterator which generates side by side from/to data
		if context:
			context_lines = numlines
		else:
			context_lines = None
		diffs = difflib._mdiff( fromlines, tolines, context_lines, linejunk=self._linejunk,
							   charjunk=self._charjunk )


		# set up iterator to wrap lines that exceed desired width
		if self._wrapcolumn:
			diffs = self._line_wrapper( diffs )

		# collect up from/to lines and flags into lists (also format the lines)
		fromlist, tolist, flaglist = self._collect_lines( diffs )

		# process change flags, generating middle column of next anchors/links
		fromlist, tolist, flaglist, next_href, next_id = self._convert_flags(
			fromlist, tolist, flaglist, context, numlines )

		s = []

		if fromdesc or todesc:
			s.append( ( fromdesc, todesc ) )

		for i in range( len( flaglist ) ):
			if flaglist[i] is None:
				# mdiff yields None on separator lines skip the bogus ones
				# generated for the first line
				if i > 0:
					s.append( ( '---', '---' ) )
			else:
				s.append( ( fromlist[i], tolist[i] ) )

		table_lines = []
		for sides in s:
			line = []
			for side in sides:
				line.append( self._lpad( side, self.cols / 2 - 1 ) )
			table_lines.append( " ".join( line ) )

		table_line_string = "\n".join( table_lines )

		colorized_table_line_string = self.colorize( table_line_string )

		return colorized_table_line_string
コード例 #43
0
ファイル: diff.py プロジェクト: 4T-Shirt/code
def mdiff(old, new):
    return difflib._mdiff(old, new)
コード例 #44
0
ファイル: utils.py プロジェクト: Kozea/wdb
    def make_table(
            self,
            fromlines,
            tolines,
            fromdesc='',
            todesc='',
            context=False,
            numlines=5
    ):
        """Returns HTML table of side by side comparison with change highlights

        Arguments:
        fromlines -- list of "from" lines
        tolines -- list of "to" lines
        fromdesc -- "from" file column header string
        todesc -- "to" file column header string
        context -- set to True for contextual differences (defaults to False
            which shows full differences).
        numlines -- number of context lines.  When context is set True,
            controls number of lines displayed before and after the change.
            When context is False, controls the number of lines to place
            the "next" link anchors before the next change (so click of
            "next" link jumps to just before the change).
        """

        # make unique anchor prefixes so that multiple tables may exist
        # on the same page without conflict.
        self._make_prefix()

        # change tabs to spaces before it gets more difficult after we insert
        # markup
        fromlines, tolines = self._tab_newline_replace(fromlines, tolines)

        # create diffs iterator which generates side by side from/to data
        if context:
            context_lines = numlines
        else:
            context_lines = None
            diffs = _mdiff(
                fromlines,
                tolines,
                context_lines,
                linejunk=self._linejunk,
                charjunk=self._charjunk
            )

        # set up iterator to wrap lines that exceed desired width
        if self._wrapcolumn:
            diffs = self._line_wrapper(diffs)

        # collect up from/to lines and flags into lists (also format the lines)
        fromlist, tolist, flaglist = self._collect_lines(diffs)

        # process change flags, generating middle column of next anchors/links
        fromlist, tolist, flaglist, next_href, next_id = self._convert_flags(
            fromlist, tolist, flaglist, context, numlines
        )

        s = []
        fmt = ' <tr>%s%s</tr>\n'

        for i in range(len(flaglist)):
            if flaglist[i] is None:
                # mdiff yields None on separator lines skip the bogus ones
                # generated for the first line
                if i > 0:
                    s.append('        </tbody>        \n        <tbody>\n')
            else:
                s.append(fmt % (fromlist[i], tolist[i]))
        if fromdesc or todesc:
            header_row = '<thead><tr>%s%s</tr></thead>' % (
                '<th colspan="2" class="diff_header">%s</th>' % fromdesc,
                '<th colspan="2" class="diff_header">%s</th>' % todesc
            )
        else:
            header_row = ''

        table = self._table_template % dict(
            data_rows=''.join(s),
            header_row=header_row,
            prefix=self._prefix[1]
        )

        return (
            table.replace('\0+', '<span class="diff_add">').replace(
                '\0-', '<span class="diff_sub">'
            ).replace('\0^', '<span class="diff_chg">').replace(
                '\1', '</span>'
            ).replace('\t', '&nbsp;')
        )