from difflib import Differ from difflib import SequenceMatcher from pyperf import Runner from pyperf import perf_counter ZEN_A = """Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!""".splitlines(keepends=True) ZEN_B = """Beautiful is better than ugly. Simple is better than hard. Complex is better than complicated. Flat is better than curve. Sparse is worse than dense. Readability doesn't counts. Special cases aren't special enough to break the rules. Star Wars is better then Star Trek. Although Harry Potter Beats both of them. Although practicality beats purity. Errors should pass silently. Unless explicitly silenced. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch or Indian. Now is better than never. Although never is often better than *right* now. If the easy is hard to explain, it's a bad idea. If the implementation is easy to explain, it might be a good idea. Namespaces are one honking great idea -- let's do more of those!""".splitlines(keepends=True) def compare_match(self, a, b): cruncher = SequenceMatcher(self.linejunk, a, b) for tag, alo, ahi, blo, bhi in cruncher.get_opcodes(): match tag: case 'replace': g = self._fancy_replace(a, alo, ahi, b, blo, bhi) case 'delete': g = self._dump('-', a, alo, ahi) case 'insert': g = self._dump('+', b, blo, bhi) case 'equal': g = self._dump(' ', a, alo, ahi) case _: raise ValueError('unknown tag %r' % (tag,)) yield from g def bench_if(count): bound_compare_if = Differ().compare start = perf_counter() for _ in range(count): for _ in bound_compare_if(ZEN_A, ZEN_B): pass return perf_counter() - start def bench_match(count): bound_compare_match = compare_match.__get__(Differ(), None) start = perf_counter() for _ in range(count): for _ in bound_compare_match(ZEN_A, ZEN_B): pass return perf_counter() - start if __name__ == "__main__": runner = Runner() runner.bench_time_func("if", bench_if) runner.bench_time_func("match", bench_match)