修剪difflib.Differ的输出

时间:2018-07-10 18:35:13

标签: python unit-testing compare

我想为assertEqual不匹配提供更多信息,为此我正在使用difflib.Differ。但是,当文件很大时,它将返回太多信息。

如何实现类似diff窗口这样的功能,只显示一些上下文行?

@@ -155,6 +155,8 @@ except (ImportError,) as e:
     raise
+tst
+
 class KeepTextFilter(object):
     def __init__(self, regexes = [], f_notify=None):

这是我的测试代码:

def get_data():

    left, right = [],[]
    for num in range(0,10):
        lmark = rmark = " "
        if not (num % 5):
            lmark, rmark = "L", "R"
        left.append("%02d%s" % (num, lmark))
        right.append("%02d%s" % (num,rmark))

    return left, right

from difflib import Differ

differ = Differ()
left, right = get_data()
print(left)
print(right)    

output = "\n".join(differ.compare(left, right))
print(output)

这就是输出的样子(给出更大的列表,它将输出所有内容)

['00L', '01 ', '02 ', '03 ', '04 ', '05L', '06 ', '07 ', '08 ', '09 ']
['00R', '01 ', '02 ', '03 ', '04 ', '05R', '06 ', '07 ', '08 ', '09 ']
- 00L
+ 00R
  01 
  02 
  03 
  04 
- 05L
+ 05R
  06 
  07 
  08 
  09 

如何获得一个说1的窗口。即

- 00L
+ 00R
  01 
  04 
- 05L
+ 05R
  06 

我正在考虑与deque(maxlen=1)一起入侵某物,但我想问一下-这似乎是显而易见的要求。我查看了Differ()compare签名的构造函数,但没有这个选项。

1 个答案:

答案 0 :(得分:0)

这就是我想出的

class DiffFormatter(difflib.Differ):

    def _window(self, lines, window=None):
        try:

            if not window:
                return lines
            if not isinstance(window, int):
                raise TypeError("window has to be an int")

            #remember, at most, `window` # of lines
            dq = deque(maxlen=window)
            cntr = 0

            res = []

            for line in lines:

                if line[0] in ("+","-"):
                    #reset cntr
                    cntr = window
                    while True:
                        #add `before` context lines
                        try:
                            #try if res.extend(dq) works
                            res.append(dq.popleft())
                        except (IndexError,) as e:
                            break
                    res.append(line)
                elif cntr > 0:
                    #`after` context
                    #cntr, while > 0 adds line to res
                    cntr -= 1
                    res.append(line)
                else:
                    #this line won't be used, unless a later line
                    #requires it in context.
                    dq.append(line)
            return res
        except (Exception,) as e:
            raise

    def format(self, exp, got, window=None):
        try:
            exp_ = exp.splitlines()
            got_ = got.splitlines()
            lines = self.compare(exp_, got_)

            if window:
                lines2 = self._window(lines, window)
            else:
                lines2 = list(lines)

            msg = "\n".join(lines2)
            msg = msg.strip()
            if msg and msg[1] != " ":
                msg = "  %s" % (msg) 
            return msg 

        except (Exception,) as e:
            raise